static void mppe_GetMasterKey(uint8_t *nt_hashhash,uint8_t *nt_response, uint8_t *masterkey) { uint8_t digest[20]; fr_SHA1_CTX Context; fr_SHA1Init(&Context); fr_SHA1Update(&Context,nt_hashhash,16); fr_SHA1Update(&Context,nt_response,24); fr_SHA1Update(&Context,magic1,27); fr_SHA1Final(digest,&Context); memcpy(masterkey,digest,16); }
/* * challenge_hash() is used by mschap2() and auth_response() * implements RFC2759 ChallengeHash() * generates 64 bit challenge */ void mschap_challenge_hash(uint8_t const *peer_challenge, uint8_t const *auth_challenge, char const *user_name, uint8_t *challenge ) { fr_SHA1_CTX Context; uint8_t hash[20]; fr_SHA1Init(&Context); fr_SHA1Update(&Context, peer_challenge, 16); fr_SHA1Update(&Context, auth_challenge, 16); fr_SHA1Update(&Context, (uint8_t const *) user_name, strlen(user_name)); fr_SHA1Final(hash, &Context); memcpy(challenge, hash, 8); }
/** * @brief Calculate the SHA1 hash of a string. * * Example: "%{sha1:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" */ static size_t sha1_xlat(UNUSED void *instance, REQUEST *request, char *fmt, char *out, size_t outlen, UNUSED RADIUS_ESCAPE_STRING func) { char buffer[1024]; uint8_t digest[20]; int i; fr_SHA1_CTX ctx; if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { *out = '\0'; return 0; } fr_SHA1Init(&ctx); fr_SHA1Update(&ctx, (void *) buffer, strlen(buffer)); fr_SHA1Final(digest, &ctx); if (outlen < 41) { snprintf(out, outlen, "sha1_overflow"); return strlen(out); } for (i = 0; i < 20; i++) { snprintf(out + i * 2, 3, "%02x", digest[i]); } return strlen(out); }
/** * @brief Calculate the SHA1 hash of a string. * * Example: "%{sha1:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" */ static size_t sha1_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t outlen) { uint8_t digest[16]; int i, len; fr_SHA1_CTX ctx; /* * We need room for at least one octet of output. */ if (outlen < 3) { *out = '\0'; return 0; } fr_SHA1Init(&ctx); fr_SHA1Update(&ctx, (const void *) fmt, strlen(fmt)); fr_SHA1Final(digest, &ctx); /* * Each digest octet takes two hex digits, plus one for * the terminating NUL. SHA1 is 160 bits (20 bytes) */ len = (outlen / 2) - 1; if (len > 20) len = 20; for (i = 0; i < len; i++) { snprintf(out + i * 2, 3, "%02x", digest[i]); } return strlen(out); }
static void calc_sha1_digest(uint8_t *buffer, uint8_t const *challenge, size_t challen, char const *password) { uint8_t buf[1024]; int i; fr_SHA1_CTX context; memset(buf, 0, 1024); memset(buf, 0x36, 64); for(i=0; i<64 && password[i]; i++) buf[i]^=password[i]; memcpy(buf+64, challenge, challen); fr_SHA1Init(&context); fr_SHA1Update(&context,buf,64+challen); memset(buf, 0x5c, 64); for(i=0; i<64 && password[i]; i++) buf[i]^=password[i]; fr_SHA1Final(buf+64,&context); fr_SHA1Init(&context); fr_SHA1Update(&context,buf,64+20); fr_SHA1Final(buffer,&context); }
/* * auth_response() generates MS-CHAP v2 SUCCESS response * according to RFC 2759 GenerateAuthenticatorResponse() * returns 42-octet response string */ void mschap_auth_response(char const *username, uint8_t const *nt_hash_hash, uint8_t const *ntresponse, uint8_t const *peer_challenge, uint8_t const *auth_challenge, char *response) { fr_SHA1_CTX Context; static const uint8_t magic1[39] = { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; static const uint8_t magic2[41] = { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E }; static char const hex[16] = "0123456789ABCDEF"; size_t i; uint8_t challenge[8]; uint8_t digest[20]; fr_SHA1Init(&Context); fr_SHA1Update(&Context, nt_hash_hash, 16); fr_SHA1Update(&Context, ntresponse, 24); fr_SHA1Update(&Context, magic1, 39); fr_SHA1Final(digest, &Context); mschap_challenge_hash(peer_challenge, auth_challenge, username, challenge); fr_SHA1Init(&Context); fr_SHA1Update(&Context, digest, 20); fr_SHA1Update(&Context, challenge, 8); fr_SHA1Update(&Context, magic2, 41); fr_SHA1Final(digest, &Context); /* * Encode the value of 'Digest' as "S=" followed by * 40 ASCII hexadecimal digits and return it in * AuthenticatorResponse. * For example, * "S=0123456789ABCDEF0123456789ABCDEF01234567" */ response[0] = 'S'; response[1] = '='; /* * The hexadecimal digits [A-F] MUST be uppercase. */ for (i = 0; i < sizeof(digest); i++) { response[2 + (i * 2)] = hex[(digest[i] >> 4) & 0x0f]; response[3 + (i * 2)] = hex[digest[i] & 0x0f]; } }
static void mppe_GetAsymmetricStartKey(uint8_t *masterkey,uint8_t *sesskey, int keylen,int issend) { uint8_t digest[20]; const uint8_t *s; fr_SHA1_CTX Context; memset(digest,0,20); if(issend) { s = magic3; } else { s = magic2; } fr_SHA1Init(&Context); fr_SHA1Update(&Context,masterkey,16); fr_SHA1Update(&Context,SHSpad1,40); fr_SHA1Update(&Context,s,84); fr_SHA1Update(&Context,SHSpad2,40); fr_SHA1Final(digest,&Context); memcpy(sesskey,digest,keylen); }
void eapsim_calculate_keys(struct eapsim_keys *ek) { fr_SHA1_CTX context; uint8_t fk[160]; unsigned char buf[256]; unsigned char *p; unsigned int blen; p = buf; memcpy(p, ek->identity, ek->identitylen); p = p+ek->identitylen; memcpy(p, ek->Kc[0], EAPSIM_Kc_SIZE); p = p+EAPSIM_Kc_SIZE; memcpy(p, ek->Kc[1], EAPSIM_Kc_SIZE); p = p+EAPSIM_Kc_SIZE; memcpy(p, ek->Kc[2], EAPSIM_Kc_SIZE); p = p+EAPSIM_Kc_SIZE; memcpy(p, ek->nonce_mt, sizeof(ek->nonce_mt)); p=p+sizeof(ek->nonce_mt); memcpy(p, ek->versionlist, ek->versionlistlen);p=p+ek->versionlistlen; memcpy(p, ek->versionselect, sizeof(ek->versionselect)); p=p+sizeof(ek->versionselect); /* *p++ = ek->versionselect[1]; */ blen = p - buf; #if defined(TEST_CASE) || defined(DUMP_EAPSIM_KEYS) { unsigned int i, j, k; j=0; k=0; printf("SHA1buffer was: "); for (i = 0; i < blen; i++) { if(j==4) { printf("_"); j=0; } if(k==20) { printf("\n "); k=0; j=0; } j++; k++; printf("%02x", buf[i]); } printf("\n"); } #endif /* do the master key first */ fr_SHA1Init(&context); fr_SHA1Update(&context, buf, blen); fr_SHA1Final(ek->master_key, &context); /* * now use the PRF to expand it, generated K_aut, K_encr, * MSK and EMSK. */ fips186_2prf(ek->master_key, fk); /* split up the result */ memcpy(ek->K_encr, fk + 0, 16); /* 128 bits for encryption */ memcpy(ek->K_aut, fk + 16, EAPSIM_AUTH_SIZE); /*128 bits for auth */ memcpy(ek->msk, fk + 32, 64); /* 64 bytes for Master Session Key */ memcpy(ek->emsk, fk + 96, 64); /* 64- extended Master Session Key */ }
void fr_hmac_sha1(const uint8_t *text, int text_len, const uint8_t *key, int key_len, uint8_t *digest) { fr_SHA1_CTX context; uint8_t k_ipad[65]; /* inner padding - * key XORd with ipad */ uint8_t k_opad[65]; /* outer padding - * key XORd with opad */ uint8_t tk[20]; int i; /* if key is longer than 64 bytes reset it to key=SHA1(key) */ if (key_len > 64) { fr_SHA1_CTX tctx; fr_SHA1Init(&tctx); fr_SHA1Update(&tctx, key, key_len); fr_SHA1Final(tk, &tctx); key = tk; key_len = 20; } #ifdef HMAC_SHA1_DATA_PROBLEMS if(sha1_data_problems) { int j,k; printf("\nhmac-sha1 key(%d): ", key_len); j=0; k=0; for (i = 0; i < key_len; i++) { if(j==4) { printf("_"); j=0; } j++; printf("%02x", key[i]); } printf("\nDATA: (%d) ",text_len); j=0; k=0; for (i = 0; i < text_len; i++) { if(k==20) { printf("\n "); k=0; j=0; } if(j==4) { printf("_"); j=0; } k++; j++; printf("%02x", text[i]); } printf("\n"); } #endif /* * the HMAC_SHA1 transform looks like: * * SHA1(K XOR opad, SHA1(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in pads */ memset( k_ipad, 0, sizeof(k_ipad)); memset( k_opad, 0, sizeof(k_opad)); memcpy( k_ipad, key, key_len); memcpy( k_opad, key, key_len); /* XOR key with ipad and opad values */ for (i = 0; i < 64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* * perform inner SHA1 */ fr_SHA1Init(&context); /* init context for 1st * pass */ fr_SHA1Update(&context, k_ipad, 64); /* start with inner pad */ fr_SHA1Update(&context, text, text_len); /* then text of datagram */ fr_SHA1Final(digest, &context); /* finish up 1st pass */ /* * perform outer MD5 */ fr_SHA1Init(&context); /* init context for 2nd * pass */ fr_SHA1Update(&context, k_opad, 64); /* start with outer pad */ fr_SHA1Update(&context, digest, 20); /* then results of 1st * hash */ fr_SHA1Final(digest, &context); /* finish up 2nd pass */ #ifdef HMAC_SHA1_DATA_PROBLEMS if(sha1_data_problems) { int j; printf("\nhmac-sha1 mac(20): "); j=0; for (i = 0; i < 20; i++) { if(j==4) { printf("_"); j=0; } j++; printf("%02x", digest[i]); } printf("\n"); } #endif }