/******************************************************************* Encode or Decode the sequence number (which is symmetric) ********************************************************************/ static void netsec_do_seq_num(struct schannel_state *state, const uint8_t *checksum, uint32_t checksum_length, uint8_t seq_num[8]) { if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { AES_KEY key; uint8_t iv[AES_BLOCK_SIZE]; AES_set_encrypt_key(state->creds->session_key, 128, &key); ZERO_STRUCT(iv); memcpy(iv+0, checksum, 8); memcpy(iv+8, checksum, 8); aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT); } else { static const uint8_t zeros[4]; uint8_t sequence_key[16]; uint8_t digest1[16]; hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); hmac_md5(digest1, checksum, checksum_length, sequence_key); arcfour_crypt(seq_num, sequence_key, 8); } state->seq_num++; }
/******************************************************************* Encode or Decode the sequence number (which is symmetric) ********************************************************************/ static void netsec_deal_with_seq_num(struct schannel_state *state, const uint8_t packet_digest[8], uint8_t seq_num[8]) { static const uint8_t zeros[4]; uint8_t sequence_key[16]; uint8_t digest1[16]; hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); hmac_md5(digest1, packet_digest, 8, sequence_key); arcfour_crypt(seq_num, sequence_key, 8); state->seq_num++; }
/******************************************************************* Encode or Decode the sequence number (which is symmetric) ********************************************************************/ static void netsec_do_seq_num(struct schannel_state *state, const uint8_t *checksum, uint32_t checksum_length, uint8_t seq_num[8]) { static const uint8_t zeros[4]; uint8_t sequence_key[16]; uint8_t digest1[16]; hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); hmac_md5(digest1, checksum, checksum_length, sequence_key); arcfour_crypt(seq_num, sequence_key, 8); state->seq_num++; }
/******************************************************************* Create a digest over the entire packet (including the data), and MD5 it with the session key. ********************************************************************/ static void netsec_digest(struct netsec_auth_struct *a, int auth_flags, RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len, uchar digest_final[16]) { uchar whole_packet_digest[16]; static uchar zeros[4]; struct MD5Context ctx3; /* verfiy the signature on the packet by MD5 over various bits */ MD5Init(&ctx3); /* use our sequence number, which ensures the packet is not out of order */ MD5Update(&ctx3, zeros, sizeof(zeros)); MD5Update(&ctx3, verf->sig, sizeof(verf->sig)); if (auth_flags & AUTH_PIPE_SEAL) { MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder)); } MD5Update(&ctx3, (const unsigned char *)data, data_len); MD5Final(whole_packet_digest, &ctx3); dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest)); /* MD5 this result and the session key, to prove that only a valid client could had produced this */ hmac_md5(a->sess_key, whole_packet_digest, sizeof(whole_packet_digest), digest_final); }
/******************************************************************* Calculate the key with which to encode the data payload ********************************************************************/ static void netsec_get_sealing_key(const uint8_t session_key[16], const uint8_t seq_num[8], uint8_t sealing_key[16]) { static const uint8_t zeros[4]; uint8_t digest2[16]; uint8_t sess_kf0[16]; int i; for (i = 0; i < 16; i++) { sess_kf0[i] = session_key[i] ^ 0xf0; } hmac_md5(sess_kf0, zeros, 4, digest2); hmac_md5(digest2, seq_num, 8, sealing_key); }
/******************************************************************* Create a digest over the entire packet (including the data), and MD5 it with the session key. ********************************************************************/ static void netsec_do_sign(struct schannel_state *state, const uint8_t *confounder, const uint8_t *data, size_t data_len, uint8_t header[8], uint8_t *checksum) { uint8_t packet_digest[16]; static const uint8_t zeros[4]; struct MD5Context ctx; MD5Init(&ctx); MD5Update(&ctx, zeros, 4); if (confounder) { SSVAL(header, 0, NL_SIGN_HMAC_MD5); SSVAL(header, 2, NL_SEAL_RC4); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); MD5Update(&ctx, header, 8); MD5Update(&ctx, confounder, 8); } else { SSVAL(header, 0, NL_SIGN_HMAC_MD5); SSVAL(header, 2, NL_SEAL_NONE); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); MD5Update(&ctx, header, 8); } MD5Update(&ctx, data, data_len); MD5Final(packet_digest, &ctx); hmac_md5(state->creds->session_key, packet_digest, sizeof(packet_digest), checksum); }
int crammd5(char *challengeb64, char *username, char *password, char *responseb64) { int i; unsigned char digest[MD5_DIGEST_LEN]; unsigned char digascii[MD5_DIGEST_LEN * 2]; unsigned char challenge[(BUF_SZ + 1)]; unsigned char response[(BUF_SZ + 1)]; unsigned char secret[(MD5_BLOCK_LEN + 1)]; memset (secret,0,sizeof(secret)); memset (challenge,0,sizeof(challenge)); strncpy (secret, password, sizeof(secret)); if (!challengeb64 || strlen(challengeb64) > sizeof(challenge) * 3 / 4) return 0; from64tobits(challenge, challengeb64); hmac_md5(challenge, strlen(challenge), secret, strlen(secret), digest); for (i = 0; i < MD5_DIGEST_LEN; i++) { digascii[2 * i] = hextab[digest[i] >> 4]; digascii[2 * i + 1] = hextab[(digest[i] & 0x0F)]; } digascii[MD5_DIGEST_LEN * 2] = '\0'; if (sizeof(response) <= strlen(username) + sizeof(digascii)) return 0; strncpy (response, username, sizeof(response) - sizeof(digascii) - 2); strcat (response, " "); strcat (response, digascii); to64frombits(responseb64, response, strlen(response)); return 1; }
int radius_msg_finish(struct radius_msg *msg, u8 *secret, size_t secret_len) { if (secret) { u8 auth[MD5_MAC_LEN]; struct radius_attr_hdr *attr; os_memset(auth, 0, MD5_MAC_LEN); attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, auth, MD5_MAC_LEN); if (attr == NULL) { printf("WARNING: Could not add " "Message-Authenticator\n"); return -1; } msg->hdr->length = htons(msg->buf_used); hmac_md5(secret, secret_len, msg->buf, msg->buf_used, (u8 *) (attr + 1)); } else msg->hdr->length = htons(msg->buf_used); if (msg->buf_used > 0xffff) { printf("WARNING: too long RADIUS message (%lu)\n", (unsigned long) msg->buf_used); return -1; } return 0; }
static void test4() { unsigned char key[25] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }; unsigned char data[50] = {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd }; unsigned char digest[DIGEST_LENGTH] = {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 }; unsigned char new_digest[DIGEST_LENGTH]; hmac_md5(data, 50, key, 25, new_digest); assert(memcmp(digest, new_digest, DIGEST_LENGTH) == 0); }
inline void hmac_md5( const char* ds, int dl, const char* ak, int al, char* dig ) { return hmac_md5( reinterpret_cast<const unsigned char *>(ds), dl, reinterpret_cast<const unsigned char *>(ak), al, reinterpret_cast<unsigned char *>(dig)); }
Gc_rc gc_hmac_md5 (const void *key, size_t keylen, const void *in, size_t inlen, char *resbuf) { hmac_md5 (key, keylen, in, inlen, resbuf); return GC_OK; }
// Register to the NET OVMS server void net_msg_register(void) { char k; char *p; unsigned int sr; // Make a (semi-)random client token sr = TMR0L*256; sr += TMR0H; for (k=0;k<8;k++) { sr += can_databuffer[k]; } srand(sr); for (k=0;k<TOKEN_SIZE;k++) { token[k] = cb64[rand()%64]; } token[TOKEN_SIZE] = 0; p = par_get(PARAM_SERVERPASS); hmac_md5(token, TOKEN_SIZE, p, strlen(p), digest); net_puts_rom("MP-C 0 "); net_puts_ram(token); net_puts_rom(" "); base64encodesend(digest, MD5_SIZE); net_puts_rom(" "); p = par_get(PARAM_VEHICLEID); net_puts_ram(p); net_puts_rom("\r\n"); }
/* Compute Message Integrity Code (MIC) over EAPOL message */ bool BCMROMFN(wpa_make_mic)(eapol_header_t *eapol, uint key_desc, uint8 *mic_key, uchar *mic) { int mic_length; /* length of eapol pkt from the version field on */ mic_length = 4 + ntoh16_ua((uint8 *)&eapol->length); /* Create the MIC for the pkt */ switch (key_desc) { case WPA_KEY_DESC_V1: hmac_md5(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; case WPA_KEY_DESC_V2: hmac_sha1(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; case WPA_KEY_DESC_V3: aes_cmac_calc(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; default: return FALSE; } return TRUE; }
/** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written * Returns: 0 on success, -1 on failure * * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has * to be cleared (all zeroes) when calling this function. * * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the * description of the Key MIC calculation. It includes packet data from the * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, u8 *mic) { u8 hash[SHA1_MAC_LEN]; switch (ver) { #ifndef CONFIG_FIPS case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: return hmac_md5(key, 16, buf, len, mic); #endif /* CONFIG_FIPS */ case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: if (hmac_sha1(key, 16, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) case WPA_KEY_INFO_TYPE_AES_128_CMAC: return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ #ifdef CONFIG_HS20 case WPA_KEY_INFO_TYPE_AKM_DEFINED: /* FIX: This should be based on negotiated AKM */ return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_HS20 */ default: return -1; } return 0; }
int radius_msg_finish(struct radius_msg *msg, const u8 *secret, size_t secret_len) { if (secret) { u8 auth[MD5_MAC_LEN]; struct radius_attr_hdr *attr; os_memset(auth, 0, MD5_MAC_LEN); attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, auth, MD5_MAC_LEN); if (attr == NULL) { wpa_printf(MSG_WARNING, "RADIUS: Could not add " "Message-Authenticator"); return -1; } msg->hdr->length = htons(wpabuf_len(msg->buf)); hmac_md5(secret, secret_len, wpabuf_head(msg->buf), wpabuf_len(msg->buf), (u8 *) (attr + 1)); } else msg->hdr->length = htons(wpabuf_len(msg->buf)); if (wpabuf_len(msg->buf) > 0xffff) { wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)", (unsigned long) wpabuf_len(msg->buf)); return -1; } return 0; }
static void test6() { unsigned char key[80] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; unsigned char *data = (unsigned char *)"Test Using Larger Than Block-Size Key - " "Hash Key First"; unsigned char digest[DIGEST_LENGTH] = {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd }; unsigned char new_digest[DIGEST_LENGTH]; hmac_md5(data, 54, key, 80, new_digest); assert(memcmp(digest, new_digest, DIGEST_LENGTH) == 0); }
static void test7() { unsigned char key[80] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; unsigned char *data = (unsigned char *)"Test Using Larger Than Block-Size Key" " and Larger Than One Block-Size Data"; unsigned char digest[DIGEST_LENGTH] = {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }; unsigned char new_digest[DIGEST_LENGTH]; hmac_md5(data, 73, key, 80, new_digest); assert(memcmp(digest, new_digest, DIGEST_LENGTH) == 0); }
void test_hmac() { int x = 0, y = 0; char keystr[100]; size_t keylen; char teststr[100]; size_t testlen; char hmac[100]; char res[64]; size_t reslen; while(strcmp(test_hmac_data[x].key,"") != 0) { keylen = hex_to_char_buf(test_hmac_data[x].key, test_hmac_data[x].keylen, keystr, 100); testlen = hex_to_char_buf(test_hmac_data[x].data, test_hmac_data[x].datalen, teststr, 100); reslen = hex_to_char_buf(test_hmac_data[x].hmac_result, 32, res, 64); hmac_md5(keystr, keylen, teststr, testlen, hmac); if(strncmp(hmac, res, 64) != 0) { y++; } CU_ASSERT(strncmp(hmac, res, 64) == 0); x++; } CU_FAIL("Test not implemented"); }
int do_auth(unsigned char *challenge, int challenge_len) { int rval = 0; if (DialogBox(hModule, MAKEINTRESOURCE(IDD_AUTH), mainWindow, AuthDlgProc) == 1) { uchar hmac[16]; hmac_md5(challenge, challenge_len, pwhash, sizeof(pwhash), hmac); memset(pwhash, 0, sizeof(pwhash)); //connection to server successful. Buffer auth; auth.writeInt(MSG_AUTH_REQUEST); //send plugin protocol version auth.writeInt(PROTOCOL_VERSION); //send user name auth.writeUTF8(username); //send hmac auth.write(hmac, sizeof(hmac)); send_data(auth); } else { msg(PLUGIN_NAME": authentication cancelled.\n"); rval = 1; } return rval; }
VOS_STATUS vos_md5_hmac_str(v_U32_t cryptHandle, /* Handle */ v_U8_t *pText, /* pointer to data stream */ v_U32_t textLen, /* length of data stream */ v_U8_t *pKey, /* pointer to authentication key */ v_U32_t keyLen, /* length of authentication key */ v_U8_t digest[VOS_DIGEST_MD5_SIZE])/* caller digest to be filled in */ { int ret = 0; ret = hmac_md5( pKey, //v_U8_t *key, (v_U8_t) keyLen, //v_U8_t ksize, (char *)pText, //char *plaintext, (v_U8_t) textLen, //v_U8_t psize, digest, //v_U8_t *output, VOS_DIGEST_MD5_SIZE //v_U8_t outlen ); if (ret != 0) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"hmac_md5() call failed"); return VOS_STATUS_E_FAULT; } return VOS_STATUS_SUCCESS; }
AuthInfo* passLogin(char *user, char *secret) { AuthInfo *ai; Chalstate *cs; uint8_t digest[MD5dlen]; char response[2*MD5dlen+1]; int i; if((cs = auth_challenge("proto=cram role=server")) == nil) return nil; hmac_md5((uint8_t*)cs->chal, strlen(cs->chal), (uint8_t*)secret, strlen(secret), digest, nil); for(i = 0; i < MD5dlen; i++) snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]); cs->user = user; cs->resp = response; cs->nresp = strlen(response); ai = auth_response(cs); auth_freechal(cs); return ai; }
void ntlmssp_genauth_ntlm2(char *password, uint8_t *lm_response, uint8_t *nt_response, uint8_t *session_key, char *challenge_data, unsigned char* nt_hash) { unsigned char lm_hash[16]; E_deshash_ntlmssp(password, lm_hash); struct MD5Context md5_session_nonce_ctx; uchar session_nonce_hash[16]; uchar session_nonce[16]; uchar user_session_key[16]; generate_random_buffer_ntlmssp(lm_response, 8); memset(lm_response+8, 0, 16); memcpy(session_nonce, challenge_data, 8); memcpy(&session_nonce[8], lm_response, 8); MD5Init(&md5_session_nonce_ctx); MD5Update(&md5_session_nonce_ctx, (unsigned char const*)challenge_data, 8); MD5Update(&md5_session_nonce_ctx, (unsigned char const*)lm_response, 8); MD5Final(session_nonce_hash, &md5_session_nonce_ctx); SMBNTencrypt_hash_ntlmssp(nt_hash, session_nonce_hash, nt_response); SMBsesskeygen_ntv1_ntlmssp(nt_hash, NULL, user_session_key); hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key); }
/* * This is not really nescessary as all fields hmac_md5'ed * in the ntlmv2 protocol are less than 64 bytes long, however * I still do this for completeness */ static DigestState * hmac_t64(uchar *data, ulong dlen, uchar *key, ulong klen, uchar *digest, DigestState *state) { if(klen > 64) klen = 64; return hmac_md5(data, dlen, key, klen, digest, state); }
/* Generate a truncated HMAC-MD5-80 signature for *message, length message_len, * with key *key, length key_len, and store the result in the 10-byte buffer at * *hash */ void hmac_md5_80(const uint8_t *message, uint8_t message_len, const uint8_t *key, uint8_t key_len, uint8_t *hash) { uint8_t full_hash[16]; hmac_md5(message, message_len, key, key_len, full_hash); memcpy(hash, full_hash, 10); }
static void netsec_do_seal(struct schannel_state *state, const uint8_t seq_num[8], uint8_t confounder[8], uint8_t *data, uint32_t length, bool forward) { if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { AES_KEY key; uint8_t iv[AES_BLOCK_SIZE]; uint8_t sess_kf0[16]; int i; for (i = 0; i < 16; i++) { sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; } AES_set_encrypt_key(sess_kf0, 128, &key); ZERO_STRUCT(iv); memcpy(iv+0, seq_num, 8); memcpy(iv+8, seq_num, 8); if (forward) { aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT); aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT); } else { aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT); aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT); } } else { uint8_t sealing_key[16]; static const uint8_t zeros[4]; uint8_t digest2[16]; uint8_t sess_kf0[16]; int i; for (i = 0; i < 16; i++) { sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; } hmac_md5(sess_kf0, zeros, 4, digest2); hmac_md5(digest2, seq_num, 8, sealing_key); arcfour_crypt(confounder, sealing_key, 8); arcfour_crypt(data, sealing_key, length); } }
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret, size_t secret_len) { const u8 *addr[4]; size_t len[4]; u8 zero[MD5_MAC_LEN]; u8 hash[MD5_MAC_LEN]; u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN]; u8 orig_authenticator[16]; struct radius_attr_hdr *attr = NULL, *tmp; size_t i; os_memset(zero, 0, sizeof(zero)); addr[0] = (u8 *) msg->hdr; len[0] = sizeof(struct radius_hdr) - MD5_MAC_LEN; addr[1] = zero; len[1] = MD5_MAC_LEN; addr[2] = (u8 *) (msg->hdr + 1); len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr); addr[3] = secret; len[3] = secret_len; md5_vector(4, addr, len, hash); if (os_memcmp(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0) return 1; for (i = 0; i < msg->attr_used; i++) { tmp = radius_get_attr_hdr(msg, i); if (tmp->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { if (attr != NULL) { wpa_printf(MSG_WARNING, "Multiple " "Message-Authenticator attributes " "in RADIUS message"); return 1; } attr = tmp; } } if (attr == NULL) { /* Message-Authenticator is MAY; not required */ return 0; } os_memcpy(orig, attr + 1, MD5_MAC_LEN); os_memset(attr + 1, 0, MD5_MAC_LEN); os_memcpy(orig_authenticator, msg->hdr->authenticator, sizeof(orig_authenticator)); os_memset(msg->hdr->authenticator, 0, sizeof(msg->hdr->authenticator)); hmac_md5(secret, secret_len, wpabuf_head(msg->buf), wpabuf_len(msg->buf), auth); os_memcpy(attr + 1, orig, MD5_MAC_LEN); os_memcpy(msg->hdr->authenticator, orig_authenticator, sizeof(orig_authenticator)); return os_memcmp(orig, auth, MD5_MAC_LEN) != 0; }
/******************************************************************* Encode or Decode the sequence number (which is symmetric) ********************************************************************/ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, RPC_AUTH_NETSEC_CHK *verf) { static uchar zeros[4]; uchar sequence_key[16]; uchar digest1[16]; hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1); dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1)); hmac_md5(digest1, verf->packet_digest, 8, sequence_key); dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key)); dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num)); SamOEMhash(verf->seq_num, sequence_key, 8); dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num)); }
/* * compute_hash -- Compute the hash given a candidate password * * Inputs: * * psk_params Pointer to PSK params structure * password The candidate password * * Returns: * * Pointer to the computed hash. * * This function calculates a hash given the PSK parameters and * a candidate password. * * The standard process used to calculate the hash is detailed in * RFC 2409. The hash used by Nortel Contivity systems use a different, * proprietary, method. * * In all cases, the calculation of the hash is a two-stage process: * * a) Calculate SKEYID using some of the PSK parameters and the password; * b) Calculate HASH_R using SKEYID and the other PSK parameters. * */ static inline unsigned char * compute_hash (const psk_entry *psk_params, const char *password) { size_t password_len = strlen(password); unsigned char skeyid[SHA1_HASH_LEN]; static unsigned char hash_r[SHA1_HASH_LEN]; /* * Calculate SKEYID */ if (psk_params->nortel_user == NULL) { /* RFC 2409 SKEYID calculation */ if (psk_params->hash_type == HASH_TYPE_MD5) { hmac_md5(psk_params->skeyid_data, psk_params->skeyid_data_len, (const unsigned char *) password, password_len, skeyid); } else { /* SHA1 */ hmac_sha1(psk_params->skeyid_data, psk_params->skeyid_data_len, (const unsigned char *) password, password_len, skeyid); } } else { /* Nortel proprietary SKEYID calculation */ unsigned char nortel_psk[SHA1_HASH_LEN]; unsigned char nortel_pwd_hash[SHA1_HASH_LEN]; SHA1((const unsigned char *) password, password_len, nortel_pwd_hash); hmac_sha1((const unsigned char *)psk_params->nortel_user, strlen(psk_params->nortel_user), nortel_pwd_hash, SHA1_HASH_LEN, nortel_psk); if (psk_params->hash_type == HASH_TYPE_MD5) { hmac_md5(psk_params->skeyid_data, psk_params->skeyid_data_len, nortel_psk, SHA1_HASH_LEN, skeyid); } else { /* SHA1 */ hmac_sha1(psk_params->skeyid_data, psk_params->skeyid_data_len, nortel_psk, SHA1_HASH_LEN, skeyid); } } /* * Calculate HASH_R */ if (psk_params->hash_type == HASH_TYPE_MD5) { hmac_md5(psk_params->hash_r_data, psk_params->hash_r_data_len, skeyid, psk_params->hash_r_len, hash_r); } else { /* SHA1 */ hmac_sha1(psk_params->hash_r_data, psk_params->hash_r_data_len, skeyid, psk_params->hash_r_len, hash_r); } return hash_r; }
int main() { char * tests[][3] = { { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There", "9294727a3638bb1c13f48ef8158bfc9d" }, { "Jefe", "what do ya want for nothing?", "750c783e6ab0b503eaa86e310a5db738" }, { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", "56be34521d144c88dbb8c733f0e8b3f6" }, { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", "697eaf0aca3a3aea3a75164746ffaa79" }, { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", "Test With Truncation", "56461ef2342edc00f9bab995690efd4c" }, { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First", "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" }, { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "6f630fad67cda0ee1fb1f562db3aa53e" }, }; unsigned char digest[16]; char hex[33]; for (int i = 0; i < (int)(sizeof(tests) / sizeof(char *[3])); i++) { hmac_md5(digest, tests[i][0], strlen(tests[i][0]), tests[i][1], strlen(tests[i][1])); for (int j = 0; j < 16; j++) { sprintf(hex + j * 2, "%02x", digest[j] & 0xffu); } hex[32] = '\0'; printf("%s\n%s\n\n", hex, tests[i][2]); fflush(stdout); assert(memcmp(hex, tests[i][2], 32) == 0); } return 0; }
void hmac_hash(int ver, u8 *key, int hashlen, u8 *buf, int buflen, u8 *mic) { u8 hash[SHA1_MAC_LEN]; if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { hmac_md5(key, hashlen, buf, buflen, mic); } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { hmac_sha1(key, hashlen, buf, buflen, hash, NOCACHED); memcpy(mic, hash, MD5_DIGEST_LENGTH); /* only 16 bytes, not 20 */ } }