1/* 2 * Copyright (c) 2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 30/* 31 * Copyright (C) 1998 by the FundsXpress, INC. 32 * 33 * All rights reserved. 34 * 35 * Export of this software from the United States of America may require 36 * a specific license from the United States Government. It is the 37 * responsibility of any person or organization contemplating export to 38 * obtain such a license before exporting. 39 * 40 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 41 * distribute this software and its documentation for any purpose and 42 * without fee is hereby granted, provided that the above copyright 43 * notice appear in all copies and that both that copyright notice and 44 * this permission notice appear in supporting documentation, and that 45 * the name of FundsXpress. not be used in advertising or publicity pertaining 46 * to distribution of the software without specific, written prior 47 * permission. FundsXpress makes no representations about the suitability of 48 * this software for any purpose. It is provided "as is" without express 49 * or implied warranty. 50 * 51 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 52 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 53 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 54 */ 55 56#include "nfs_gss_crypto.h" 57 58 59/* 60n-fold(k-bits): 61 l = lcm(n,k) 62 r = l/k 63 s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) 64 compute the 1's complement sum: 65 n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] 66*/ 67 68/* representation: msb first, assume n and k are multiples of 8, and 69 that k>=16. this is the case of all the cryptosystems which are 70 likely to be used. this function can be replaced if that 71 assumption ever fails. */ 72 73/* input length is in bits */ 74 75void 76krb5_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits, 77 unsigned char *out) 78{ 79 int a,b,c,lcm; 80 int byte, i, msbit; 81 82 /* the code below is more readable if I make these bytes 83 instead of bits */ 84 85 inbits >>= 3; 86 outbits >>= 3; 87 88 /* first compute lcm(n,k) */ 89 90 a = outbits; 91 b = inbits; 92 93 while(b != 0) { 94 c = b; 95 b = a%b; 96 a = c; 97 } 98 99 lcm = outbits*inbits/a; 100 101 /* now do the real work */ 102 103 memset(out, 0, outbits); 104 byte = 0; 105 106 /* this will end up cycling through k lcm(k,n)/k times, which 107 is correct */ 108 for (i=lcm-1; i>=0; i--) { 109 /* compute the msbit in k which gets added into this byte */ 110 msbit = (/* first, start with the msbit in the first, unrotated 111 byte */ 112 ((inbits<<3)-1) 113 /* then, for each byte, shift to the right for each 114 repetition */ 115 +(((inbits<<3)+13)*(i/inbits)) 116 /* last, pick out the correct byte within that 117 shifted repetition */ 118 +((inbits-(i%inbits))<<3) 119 )%(inbits<<3); 120 121 /* pull out the byte value itself */ 122 byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| 123 (in[((inbits)-(msbit>>3))%inbits])) 124 >>((msbit&7)+1))&0xff; 125 126 /* do the addition */ 127 byte += out[i%outbits]; 128 out[i%outbits] = byte&0xff; 129 130#if 0 131 printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit, 132 (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| 133 (in[((inbits)-(msbit>>3))%inbits])) 134 >>((msbit&7)+1))&0xff, byte); 135#endif 136 137 /* keep around the carry bit, if any */ 138 byte >>= 8; 139 140#if 0 141 printf("carry=%d\n", byte); 142#endif 143 } 144 145 /* if there's a carry bit left over, add it back in */ 146 if (byte) { 147 for (i=outbits-1; i>=0; i--) { 148 /* do the addition */ 149 byte += out[i]; 150 out[i] = byte&0xff; 151 152 /* keep around the carry bit, if any */ 153 byte >>= 8; 154 } 155 } 156} 157 158/* 159 * Given 21 bytes of random bits, make a triple DES key. 160 */ 161 162void 163des3_make_key(const unsigned char randombits[21], des_cblock key[3]) 164{ 165 int i; 166 167 for (i = 0; i < 3; i++) { 168 memcpy(&key[i], &randombits[i*7], 7); 169 key[i][7] = (((key[i][0] & 1) << 1) | 170 ((key[i][1] & 1) << 2) | 171 ((key[i][2] & 1) << 3) | 172 ((key[i][3] & 1) << 4) | 173 ((key[i][4] & 1) << 5) | 174 ((key[i][5] & 1) << 6) | 175 ((key[i][6] & 1) << 7)); 176 des_fixup_key_parity(&key[i]); 177 } 178} 179 180/* 181 * Key derivation for triple DES. 182 * Given the session key in in key, produce a new key in out key using 183 * the supplied constant. 184 */ 185 186int 187des3_derive_key(des_cblock inkey[3], des_cblock outkey[3], 188 const unsigned char *constant, int clen) 189{ 190 des_cblock inblock, outblock, ivec; 191 des3_cbc_key_schedule sched; 192 unsigned char rawkey[21]; 193 size_t n, keybytes = sizeof(rawkey); 194 195 /* initialize the input block */ 196 197 if (clen == sizeof(des_cblock)) { 198 memcpy(inblock, constant, clen); 199 } else { 200 krb5_nfold(clen*8, constant, sizeof(des_cblock)*8, inblock); 201 } 202 203 /* loop encrypting the blocks until enough key bytes are generated */ 204 205 bzero(ivec, sizeof(ivec)); 206 des3_cbc_key_sched(inkey, &sched); 207 for (n = 0; n < sizeof(rawkey); n += sizeof(des_cblock)) { 208 des3_cbc_encrypt(&inblock, &outblock, sizeof(outblock), &sched, &ivec, NULL, 1); 209 if ((keybytes - n) <= sizeof (des_cblock)) { 210 memcpy(rawkey+n, outblock, (keybytes - n)); 211 break; 212 } 213 memcpy(rawkey+n, outblock, sizeof(des_cblock)); 214 memcpy(inblock, outblock, sizeof(des_cblock)); 215 } 216 217 /* postprocess the key */ 218 des3_make_key(rawkey, outkey); 219 220 /* clean memory, free resources and exit */ 221 222 bzero(inblock, sizeof (des_cblock)); 223 bzero(outblock, sizeof (des_cblock)); 224 bzero(rawkey, keybytes); 225 bzero(&sched, sizeof (sched)); 226 227 return(0); 228} 229 230/* 231 * Initialize a context for HMAC SHA1 232 * if drived is true we derive a new key 233 * based on KG_USAGE_SIGN 234 */ 235 236void 237HMAC_SHA1_DES3KD_Init(HMAC_SHA1_DES3KD_CTX *ctx, des_cblock key[3], int derive) 238{ 239 unsigned char ipad[64]; 240 size_t i, j; 241 242 SHA1Init(&ctx->sha1_ctx); 243 if (derive) 244 des3_derive_key(key, ctx->dk, KEY_USAGE_DES3_SIGN, KEY_USAGE_LEN); 245 else 246 memcpy(ctx->dk, key, 3*sizeof(des_cblock)); 247 memset(ipad, 0x36, sizeof(ipad)); 248 for (i = 0; i < 3; i++) 249 for (j = 0; j < sizeof(des_cblock); j++) 250 ipad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; 251 SHA1Update(&ctx->sha1_ctx, ipad, sizeof(ipad)); 252} 253 254/* 255 * Update the HMAC SHA1 context with the supplied data. 256 */ 257void 258HMAC_SHA1_DES3KD_Update(HMAC_SHA1_DES3KD_CTX *ctx, void *data, size_t len) 259{ 260 SHA1Update(&ctx->sha1_ctx, data, len); 261} 262 263/* 264 * Finish the context and produce the HMAC SHA1 digest. 265 */ 266 267void 268HMAC_SHA1_DES3KD_Final(void *digest, HMAC_SHA1_DES3KD_CTX *ctx) 269{ 270 unsigned char opad[64]; 271 size_t i, j; 272 273 SHA1Final(digest, &ctx->sha1_ctx); 274 memset(opad, 0x5c, sizeof(opad)); 275 for (i = 0; i < 3; i++) 276 for (j = 0; j < sizeof(des_cblock); j++) 277 opad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; 278 SHA1Init(&ctx->sha1_ctx); 279 SHA1Update(&ctx->sha1_ctx, opad, sizeof(opad)); 280 SHA1Update(&ctx->sha1_ctx, digest, SHA1_RESULTLEN); 281 SHA1Final(digest, &ctx->sha1_ctx); 282} 283 284/* 285 * Initialize an MD5 DES CBC context with a schedule. 286 */ 287 288void MD5_DESCBC_Init(MD5_DESCBC_CTX *ctx, des_cbc_key_schedule *sched) 289{ 290 MD5Init(&ctx->md5_ctx); 291 ctx->sched = sched; 292} 293 294/* 295 * Update MD5 DES CBC context with the supplied data. 296 */ 297 298void MD5_DESCBC_Update(MD5_DESCBC_CTX *ctx, void *data, size_t len) 299{ 300 MD5Update(&ctx->md5_ctx, data, len); 301} 302 303/* 304 * Finalize the context and extract the digest. 305 */ 306 307void MD5_DESCBC_Final(void *digest, MD5_DESCBC_CTX *ctx) 308{ 309 unsigned char md5_digest[MD5_DIGEST_LENGTH]; 310 311 MD5Final(md5_digest, &ctx->md5_ctx); 312 313 /* 314 * Now get the DES CBC checksum for the digest. 315 */ 316 des_cbc_cksum((des_cblock *) md5_digest, (des_cblock *)digest, 317 sizeof (md5_digest), ctx->sched); 318} 319 320