17c478bd9Sstevel@tonic-gate /*
2159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
9*55fea89dSDan Cross  *
107c478bd9Sstevel@tonic-gate  * All rights reserved.
11*55fea89dSDan Cross  *
127c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
137c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
147c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
157c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
16*55fea89dSDan Cross  *
177c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
257c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
267c478bd9Sstevel@tonic-gate  * or implied warranty.
27*55fea89dSDan Cross  *
287c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
297c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
307c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
33159d09a2SMark Phalan #include "k5-int.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Solaris Kerberos defines memory management macros in <krb5.h>,
377c478bd9Sstevel@tonic-gate  * which is included by <k5-int.h>, so we need not include <memory.h>
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate /* #include <memory.h> */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate n-fold(k-bits):
437c478bd9Sstevel@tonic-gate   l = lcm(n,k)
447c478bd9Sstevel@tonic-gate   r = l/k
457c478bd9Sstevel@tonic-gate   s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
467c478bd9Sstevel@tonic-gate   compute the 1's complement sum:
477c478bd9Sstevel@tonic-gate 	n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /* representation: msb first, assume n and k are multiples of 8, and
517c478bd9Sstevel@tonic-gate    that k>=16.  this is the case of all the cryptosystems which are
527c478bd9Sstevel@tonic-gate    likely to be used.  this function can be replaced if that
537c478bd9Sstevel@tonic-gate    assumption ever fails.  */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /* input length is in bits */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate void
krb5_nfold(unsigned int inbits,const unsigned char * in,unsigned int outbits,unsigned char * out)58159d09a2SMark Phalan krb5_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits,
59159d09a2SMark Phalan 	   unsigned char *out)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate     int a,b,c,lcm;
627c478bd9Sstevel@tonic-gate     int byte, i, msbit;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate     /* the code below is more readable if I make these bytes
657c478bd9Sstevel@tonic-gate        instead of bits */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     inbits >>= 3;
687c478bd9Sstevel@tonic-gate     outbits >>= 3;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     /* first compute lcm(n,k) */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate     a = outbits;
737c478bd9Sstevel@tonic-gate     b = inbits;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate     while(b != 0) {
767c478bd9Sstevel@tonic-gate 	c = b;
777c478bd9Sstevel@tonic-gate 	b = a%b;
787c478bd9Sstevel@tonic-gate 	a = c;
797c478bd9Sstevel@tonic-gate     }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate     lcm = outbits*inbits/a;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate     /* now do the real work */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate     (void) memset(out, 0, outbits);
867c478bd9Sstevel@tonic-gate     byte = 0;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate     /* this will end up cycling through k lcm(k,n)/k times, which
897c478bd9Sstevel@tonic-gate        is correct */
907c478bd9Sstevel@tonic-gate     for (i=lcm-1; i>=0; i--) {
917c478bd9Sstevel@tonic-gate 	/* compute the msbit in k which gets added into this byte */
927c478bd9Sstevel@tonic-gate 	msbit = (/* first, start with the msbit in the first, unrotated
937c478bd9Sstevel@tonic-gate 		    byte */
947c478bd9Sstevel@tonic-gate 		 ((inbits<<3)-1)
957c478bd9Sstevel@tonic-gate 		 /* then, for each byte, shift to the right for each
967c478bd9Sstevel@tonic-gate 		    repetition */
977c478bd9Sstevel@tonic-gate 		 +(((inbits<<3)+13)*(i/inbits))
987c478bd9Sstevel@tonic-gate 		 /* last, pick out the correct byte within that
997c478bd9Sstevel@tonic-gate 		    shifted repetition */
1007c478bd9Sstevel@tonic-gate 		 +((inbits-(i%inbits))<<3)
1017c478bd9Sstevel@tonic-gate 		 )%(inbits<<3);
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* pull out the byte value itself */
1047c478bd9Sstevel@tonic-gate 	byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
1057c478bd9Sstevel@tonic-gate 		  (in[((inbits)-(msbit>>3))%inbits]))
1067c478bd9Sstevel@tonic-gate 		 >>((msbit&7)+1))&0xff;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/* do the addition */
1097c478bd9Sstevel@tonic-gate 	byte += out[i%outbits];
1107c478bd9Sstevel@tonic-gate 	out[i%outbits] = byte&0xff;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate #if 0
1137c478bd9Sstevel@tonic-gate 	printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit,
1147c478bd9Sstevel@tonic-gate 	       (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
1157c478bd9Sstevel@tonic-gate 		 (in[((inbits)-(msbit>>3))%inbits]))
1167c478bd9Sstevel@tonic-gate 		>>((msbit&7)+1))&0xff, byte);
1177c478bd9Sstevel@tonic-gate #endif
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/* keep around the carry bit, if any */
1207c478bd9Sstevel@tonic-gate 	byte >>= 8;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate #if 0
1237c478bd9Sstevel@tonic-gate 	printf("carry=%d\n", byte);
1247c478bd9Sstevel@tonic-gate #endif
1257c478bd9Sstevel@tonic-gate     }
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate     /* if there's a carry bit left over, add it back in */
1287c478bd9Sstevel@tonic-gate     if (byte) {
1297c478bd9Sstevel@tonic-gate 	for (i=outbits-1; i>=0; i--) {
1307c478bd9Sstevel@tonic-gate 	    /* do the addition */
1317c478bd9Sstevel@tonic-gate 	    byte += out[i];
1327c478bd9Sstevel@tonic-gate 	    out[i] = byte&0xff;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	    /* keep around the carry bit, if any */
1357c478bd9Sstevel@tonic-gate 	    byte >>= 8;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate     }
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
140