BSD 4_1_snap release
[unix-history] / usr / src / cmd / berknet / nbs.c
CommitLineData
442dbcf7 1# include <stdio.h>
4b9ccde7
C
2/* sccs id variable */
3static char *nbs_sid = "@(#)nbs.c 1.2";
4
442dbcf7
BJ
5/* file nbs.c
6 This file has the necessary procedures to use the NBS algorithm
7 to encrypt and decrypt strings of arbitrary length.
8
9 Basically
10
11 ciphertext = nbsencrypt(cleartext,secretkey,ciphertext);
12
13 yields a string ciphertext from string cleartext using
14 the secret string secretkey.
15 Then
16
17 cleartext = nbsdecrypt(ciphertext,secretkey,cleartext);
18
19 yields the original string cleartext IF the string secretkey
20 is the same for both calls.
21 The third parameter is filled with the result of the call-
22 it must be (11/8)*size(firstarg).
23 The first and third areguments must be different.
24 The cleartext must be ASCII - the top eighth bit is ignored,
25 so binary data won't work.
26 The plaintext is broken into 8 character sections,
27 encrypted, and concatenated separated by $'s to make the ciphertext.
28 The first 8 letter section uses the secretkey, subsequent
29 sections use the cleartext of the previous section as
30 the key.
31 Thus the ciphertext depends on itself, except for
32 the first section, which depends on the key.
33 This means that sections of the ciphertext, except the first,
34 may not stand alone.
35 Only the first 8 characters of the key matter.
36*/
37char *deblknot(), *deblkclr();
38char *nbs8decrypt(), *nbs8encrypt();
39static char E[48];
40char e[];
41char *nbsencrypt(str,key,result)
42 char *result;
4b9ccde7 43 char *str, *key; {
442dbcf7
BJ
44 static char buf[20],oldbuf[20];
45 register int j;
46 result[0] = 0;
47 strcpy(oldbuf,key);
48 while(*str){
49 for(j=0;j<10;j++)buf[j] = 0;
50 for(j=0;j<8 && *str;j++)buf[j] = *str++;
51 strcat(result,nbs8encrypt(buf,oldbuf));
52 strcat(result,"$");
53 strcpy(oldbuf,buf);
54 }
55 return(result);
56 }
57char *nbsdecrypt(cpt,key,result)
58 char *result;
4b9ccde7
C
59 char *cpt,*key; {
60 char *s;
442dbcf7
BJ
61 char c,oldbuf[20];
62 result[0] = 0;
63 strcpy(oldbuf,key);
64 while(*cpt){
65 for(s = cpt;*s && *s != '$';s++);
66 c = *s;
67 *s = 0;
68 strcpy(oldbuf,nbs8decrypt(cpt,oldbuf));
69 strcat(result,oldbuf);
70 if(c == 0)break;
71 cpt = s + 1;
72 }
73 return(result);
74 }
75/* make key to be sent across the network */
76makeuukey(skey,sn,mch)
77char *skey, *sn, mch;
78{
79 skey[0] = mch;
80 skey[1] = 0;
81 strcat(skey,sn);
82}
83
84/* all other calls are private */
85/*
86char _sobuf[BUFSIZ];
87testing(){
88 static char res[BUFSIZ];
4b9ccde7 89 char *s;
442dbcf7
BJ
90 char str[BUFSIZ];
91 setbuf(stdout,_sobuf);
92 while(!feof(stdin)){
93 fprintf(stderr,"String:\n");
94 fgets(str,BUFSIZ,stdin);
95 if(feof(stdin))break;
96 strcat(str,"\n");
97 s = nbsencrypt(str,"hellothere",res);
98 fprintf(stderr,"encrypted:\n%s\n",s);
99 fprintf(stderr,"decrypted:\n");
100 printf("%s",nbsdecrypt(s,"hellothere",str));
101 fprintf(stderr,"\n");
102 }
103 }
104*/
105/*
106 To encrypt:
107 The first level of call splits the input strings into strings
108 no longer than 8 characters, for encryption.
109 Then the encryption of 8 characters breaks all but the top bit
110 of each character into a 64-character block, each character
111 with 1 or 0 corresponding to binary.
112 The key is set likewise.
113 The encrypted form is then converted, 6 bits at a time,
114 into an ASCII string.
115
116 To decrypt:
117 We take the result of the encryption, 6 significant bits
118 per character, and convert it to the block(64-char) fmt.
119 This is decrypted by running the nbs algorithm in reverse,
120 and transformed back into 7bit ASCII.
121
122 The subroutines to do ASCII blocking and deblocking
123 are .....clr and the funny 6-bit code are .....not.
124
125*/
126
127char *nbs8encrypt(str,key)
4b9ccde7 128char *str, *key; {
442dbcf7
BJ
129 static char keyblk[100], blk[100];
130 register int i;
131
132 enblkclr(keyblk,key);
133 nbssetkey(keyblk);
134
135 for(i=0;i<48;i++) E[i] = e[i];
136 enblkclr(blk,str);
137 blkencrypt(blk,0); /* forward dir */
138
139 return(deblknot(blk));
140}
141char *nbs8decrypt(crp,key)
4b9ccde7 142char *crp, *key; {
442dbcf7
BJ
143 static char keyblk[100], blk[100];
144 register int i;
145
146 enblkclr(keyblk,key);
147 nbssetkey(keyblk);
148
149 for(i=0;i<48;i++) E[i] = e[i];
150 enblknot(blk,crp);
151 blkencrypt(blk,1); /* backward dir */
152
153 return(deblkclr(blk));
154}
155enblkclr(blk,str) /* ignores top bit of chars in string str */
156char *blk,*str; {
157 register int i,j;
4b9ccde7 158 char c;
442dbcf7
BJ
159 for(i=0;i<70;i++)blk[i] = 0;
160 for(i=0; (c= *str) && i<64; str++){
161 for(j=0; j<7; j++, i++)
162 blk[i] = (c>>(6-j)) & 01;
163 i++;
164 }
165 }
166char *deblkclr(blk)
167char *blk; {
168 register int i,j;
4b9ccde7 169 char c;
442dbcf7
BJ
170 static char iobuf[30];
171 for(i=0; i<10; i++){
172 c = 0;
173 for(j=0; j<7; j++){
174 c <<= 1;
175 c |= blk[8*i+j];
176 }
177 iobuf[i] = c;
178 }
179 iobuf[i] = 0;
180 return(iobuf);
181 }
182enblknot(blk,crp)
183char *blk;
184char *crp; {
185 register int i,j;
4b9ccde7 186 char c;
442dbcf7
BJ
187 for(i=0;i<70;i++)blk[i] = 0;
188 for(i=0; (c= *crp) && i<64; crp++){
189 if(c>'Z') c -= 6;
190 if(c>'9') c -= 7;
191 c -= '.';
192 for(j=0; j<6; j++, i++)
193 blk[i] = (c>>(5-j)) & 01;
194 }
195 }
196char *deblknot(blk)
197char *blk; {
198 register int i,j;
4b9ccde7 199 char c;
442dbcf7
BJ
200 static char iobuf[30];
201 for(i=0; i<11; i++){
202 c = 0;
203 for(j=0; j<6; j++){
204 c <<= 1;
205 c |= blk[6*i+j];
206 }
207 c += '.';
208 if(c > '9')c += 7;
209 if(c > 'Z')c += 6;
210 iobuf[i] = c;
211 }
212 iobuf[i] = 0;
213 return(iobuf);
214 }
215/*
216 * This program implements the
217 * Proposed Federal Information Processing
218 * Data Encryption Standard.
219 * See Federal Register, March 17, 1975 (40FR12134)
220 */
221
222/*
223 * Initial permutation,
224 */
225static char IP[] = {
226 58,50,42,34,26,18,10, 2,
227 60,52,44,36,28,20,12, 4,
228 62,54,46,38,30,22,14, 6,
229 64,56,48,40,32,24,16, 8,
230 57,49,41,33,25,17, 9, 1,
231 59,51,43,35,27,19,11, 3,
232 61,53,45,37,29,21,13, 5,
233 63,55,47,39,31,23,15, 7,
234};
235
236/*
237 * Final permutation, FP = IP^(-1)
238 */
239static char FP[] = {
240 40, 8,48,16,56,24,64,32,
241 39, 7,47,15,55,23,63,31,
242 38, 6,46,14,54,22,62,30,
243 37, 5,45,13,53,21,61,29,
244 36, 4,44,12,52,20,60,28,
245 35, 3,43,11,51,19,59,27,
246 34, 2,42,10,50,18,58,26,
247 33, 1,41, 9,49,17,57,25,
248};
249
250/*
251 * Permuted-choice 1 from the key bits
252 * to yield C and D.
253 * Note that bits 8,16... are left out:
254 * They are intended for a parity check.
255 */
256static char PC1_C[] = {
257 57,49,41,33,25,17, 9,
258 1,58,50,42,34,26,18,
259 10, 2,59,51,43,35,27,
260 19,11, 3,60,52,44,36,
261};
262
263static char PC1_D[] = {
264 63,55,47,39,31,23,15,
265 7,62,54,46,38,30,22,
266 14, 6,61,53,45,37,29,
267 21,13, 5,28,20,12, 4,
268};
269
270/*
271 * Sequence of shifts used for the key schedule.
272*/
273static char shifts[] = {
274 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
275};
276
277/*
278 * Permuted-choice 2, to pick out the bits from
279 * the CD array that generate the key schedule.
280 */
281static char PC2_C[] = {
282 14,17,11,24, 1, 5,
283 3,28,15, 6,21,10,
284 23,19,12, 4,26, 8,
285 16, 7,27,20,13, 2,
286};
287
288static char PC2_D[] = {
289 41,52,31,37,47,55,
290 30,40,51,45,33,48,
291 44,49,39,56,34,53,
292 46,42,50,36,29,32,
293};
294
295/*
296 * The C and D arrays used to calculate the key schedule.
297 */
298
299static char C[28];
300static char D[28];
301/*
302 * The key schedule.
303 * Generated from the key.
304 */
305static char KS[16][48];
306
307/*
308 * Set up the key schedule from the key.
309 */
310
311nbssetkey(key)
312char *key;
313{
314 register i, j, k;
315 int t;
316
317 /*
318 * First, generate C and D by permuting
319 * the key. The low order bit of each
320 * 8-bit char is not used, so C and D are only 28
321 * bits apiece.
322 */
323 for (i=0; i<28; i++) {
324 C[i] = key[PC1_C[i]-1];
325 D[i] = key[PC1_D[i]-1];
326 }
327 /*
328 * To generate Ki, rotate C and D according
329 * to schedule and pick up a permutation
330 * using PC2.
331 */
332 for (i=0; i<16; i++) {
333 /*
334 * rotate.
335 */
336 for (k=0; k<shifts[i]; k++) {
337 t = C[0];
338 for (j=0; j<28-1; j++)
339 C[j] = C[j+1];
340 C[27] = t;
341 t = D[0];
342 for (j=0; j<28-1; j++)
343 D[j] = D[j+1];
344 D[27] = t;
345 }
346 /*
347 * get Ki. Note C and D are concatenated.
348 */
349 for (j=0; j<24; j++) {
350 KS[i][j] = C[PC2_C[j]-1];
351 KS[i][j+24] = D[PC2_D[j]-28-1];
352 }
353 }
354}
355
356/*
357 * The E bit-selection table.
358 */
359static char e[] = {
360 32, 1, 2, 3, 4, 5,
361 4, 5, 6, 7, 8, 9,
362 8, 9,10,11,12,13,
363 12,13,14,15,16,17,
364 16,17,18,19,20,21,
365 20,21,22,23,24,25,
366 24,25,26,27,28,29,
367 28,29,30,31,32, 1,
368};
369
370/*
371 * The 8 selection functions.
372 * For some reason, they give a 0-origin
373 * index, unlike everything else.
374 */
375static char S[8][64] = {
376 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
377 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
378 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
379 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
380
381 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
382 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
383 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
384 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
385
386 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
387 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
388 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
389 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
390
391 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
392 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
393 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
394 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
395
396 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
397 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
398 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
399 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
400
401 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
402 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
403 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
404 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
405
406 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
407 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
408 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
409 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
410
411 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
412 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
413 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
414 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
415};
416
417/*
418 * P is a permutation on the selected combination
419 * of the current L and key.
420 */
421static char P[] = {
422 16, 7,20,21,
423 29,12,28,17,
424 1,15,23,26,
425 5,18,31,10,
426 2, 8,24,14,
427 32,27, 3, 9,
428 19,13,30, 6,
429 22,11, 4,25,
430};
431
432/*
433 * The current block, divided into 2 halves.
434 */
435static char L[32], R[32];
436static char tempL[32];
437static char f[32];
438
439/*
440 * The combination of the key and the input, before selection.
441 */
442static char preS[48];
443
444/*
445 * The payoff: encrypt a block.
446 */
447
448blkencrypt(block, edflag)
449char *block;
450{
451 int i, ii;
452 register t, j, k;
453
454 /*
455 * First, permute the bits in the input
456 */
457 for (j=0; j<64; j++)
458 L[j] = block[IP[j]-1];
459 /*
460 * Perform an encryption operation 16 times.
461 */
462 for (ii=0; ii<16; ii++) {
463 /*
464 * Set direction
465 */
466 if (edflag)
467 i = 15-ii;
468 else
469 i = ii;
470 /*
471 * Save the R array,
472 * which will be the new L.
473 */
474 for (j=0; j<32; j++)
475 tempL[j] = R[j];
476 /*
477 * Expand R to 48 bits using the E selector;
478 * exclusive-or with the current key bits.
479 */
480 for (j=0; j<48; j++)
481 preS[j] = R[E[j]-1] ^ KS[i][j];
482 /*
483 * The pre-select bits are now considered
484 * in 8 groups of 6 bits each.
485 * The 8 selection functions map these
486 * 6-bit quantities into 4-bit quantities
487 * and the results permuted
488 * to make an f(R, K).
489 * The indexing into the selection functions
490 * is peculiar; it could be simplified by
491 * rewriting the tables.
492 */
493 for (j=0; j<8; j++) {
494 t = 6*j;
495 k = S[j][(preS[t+0]<<5)+
496 (preS[t+1]<<3)+
497 (preS[t+2]<<2)+
498 (preS[t+3]<<1)+
499 (preS[t+4]<<0)+
500 (preS[t+5]<<4)];
501 t = 4*j;
502 f[t+0] = (k>>3)&01;
503 f[t+1] = (k>>2)&01;
504 f[t+2] = (k>>1)&01;
505 f[t+3] = (k>>0)&01;
506 }
507 /*
508 * The new R is L ^ f(R, K).
509 * The f here has to be permuted first, though.
510 */
511 for (j=0; j<32; j++)
512 R[j] = L[j] ^ f[P[j]-1];
513 /*
514 * Finally, the new L (the original R)
515 * is copied back.
516 */
517 for (j=0; j<32; j++)
518 L[j] = tempL[j];
519 }
520 /*
521 * The output L and R are reversed.
522 */
523 for (j=0; j<32; j++) {
524 t = L[j];
525 L[j] = R[j];
526 R[j] = t;
527 }
528 /*
529 * The final output
530 * gets the inverse permutation of the very original.
531 */
532 for (j=0; j<64; j++)
533 block[j] = L[FP[j]-1];
534}