/** * Update the HMAC_DRBG key * * @v hash Underlying hash algorithm * @v state HMAC_DRBG internal state * @v data Provided data * @v len Length of provided data * @v single Single byte used in concatenation * * This function carries out the operation * * K = HMAC ( K, V || single || provided_data ) * * as used by hmac_drbg_update() */ static void hmac_drbg_update_key ( struct digest_algorithm *hash, struct hmac_drbg_state *state, const void *data, size_t len, const uint8_t single ) { uint8_t context[ hash->ctxsize ]; size_t out_len = hash->digestsize; DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state ); DBGC_HDA ( state, 0, data, len ); /* Sanity checks */ assert ( hash != NULL ); assert ( state != NULL ); assert ( ( data != NULL ) || ( len == 0 ) ); assert ( ( single == 0x00 ) || ( single == 0x01 ) ); /* K = HMAC ( K, V || single || provided_data ) */ hmac_init ( hash, context, state->key, &out_len ); assert ( out_len == hash->digestsize ); hmac_update ( hash, context, state->value, out_len ); hmac_update ( hash, context, &single, sizeof ( single ) ); hmac_update ( hash, context, data, len ); hmac_final ( hash, context, state->key, &out_len, state->key ); assert ( out_len == hash->digestsize ); DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || " "provided_data ) :\n", hash->name, state, single ); DBGC_HDA ( state, 0, state->key, out_len ); }
/** * @internal * * @brief Verify the hmac of a packet * * @param session The session to use. * @param buffer The buffer to verify the hmac from. * @param mac The mac to compare with the hmac. * * @return 0 if hmac and mac are equal, < 0 if not or an error * occurred. */ int packet_hmac_verify(ssh_session session, ssh_buffer buffer, unsigned char *mac) { unsigned char hmacbuf[EVP_MAX_MD_SIZE] = {0}; HMACCTX ctx; unsigned int len; uint32_t seq; ctx = hmac_init(session->current_crypto->decryptMAC, 20, SSH_HMAC_SHA1); if (ctx == NULL) { return -1; } seq = htonl(session->recv_seq); hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t)); hmac_update(ctx, buffer_get_rest(buffer), buffer_get_rest_len(buffer)); hmac_final(ctx, hmacbuf, &len); #ifdef DEBUG_CRYPTO ssh_print_hexa("received mac",mac,len); ssh_print_hexa("Computed mac",hmacbuf,len); ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(uint32_t)); #endif if (memcmp(mac, hmacbuf, len) == 0) { return 0; } return -1; }
void pbkdf(buffer password, buffer salt, word block_index, int rounds, buffer *key) { assert(key->length == 32); hmac base_mac = hmac_init(password), mac; buffer temp = buffer_calloc(32); // First iteration // U1 = HMAC(P, S || (i+1)) mac = hmac_clone(base_mac); hmac_update(&mac, salt); buffer index = buffer_calloc(4); // 1 word index.words[0] = block_index+1; hmac_update(&mac, index); buffer_free(&index); hmac_end(&mac, key); buffer_copy(&temp, *key); // Next iterations // U_(n+1) = U_n ^ HMAC(P, U_n) for (int i=1; i<rounds; i++) { mac = hmac_clone(base_mac); hmac_update(&mac, temp); hmac_end(&mac, &temp); buffer_xor(key, temp); } buffer_free(&temp); hmac_free(&base_mac); }
unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) { struct ssh_cipher_struct *crypto = NULL; HMACCTX ctx = NULL; char *out = NULL; unsigned int finallen; uint32_t seq; if (!session->current_crypto) { return NULL; /* nothing to do here */ } if(len % session->current_crypto->in_cipher->blocksize != 0){ ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len); return NULL; } out = malloc(len); if (out == NULL) { return NULL; } seq = ntohl(session->send_seq); crypto = session->current_crypto->out_cipher; if (crypto->set_encrypt_key(crypto, session->current_crypto->encryptkey, session->current_crypto->encryptIV) < 0) { SAFE_FREE(out); return NULL; } if (session->version == 2) { ctx = hmac_init(session->current_crypto->encryptMAC,20,SSH_HMAC_SHA1); if (ctx == NULL) { SAFE_FREE(out); return NULL; } hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t)); hmac_update(ctx,data,len); hmac_final(ctx,session->current_crypto->hmacbuf,&finallen); #ifdef DEBUG_CRYPTO ssh_print_hexa("mac: ",data,len); if (finallen != 20) { printf("Final len is %d\n",finallen); } ssh_print_hexa("Packet hmac", session->current_crypto->hmacbuf, 20); #endif } crypto->cbc_encrypt(crypto, data, out, len); memcpy(data, out, len); memset(out, 0, len); SAFE_FREE(out); if (session->version == 2) { return session->current_crypto->hmacbuf; } return NULL; }
unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) { struct ssh_cipher_struct *crypto = NULL; HMACCTX ctx = NULL; char *out = NULL; unsigned int finallen; uint32_t seq; enum ssh_hmac_e type; assert(len); if (!session->current_crypto) { return NULL; /* nothing to do here */ } if((len - session->current_crypto->out_cipher->lenfield_blocksize) % session->current_crypto->out_cipher->blocksize != 0){ ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len); return NULL; } out = malloc(len); if (out == NULL) { return NULL; } type = session->current_crypto->out_hmac; seq = ntohl(session->send_seq); crypto = session->current_crypto->out_cipher; if (crypto->aead_encrypt != NULL) { crypto->aead_encrypt(crypto, data, out, len, session->current_crypto->hmacbuf, session->send_seq); } else { ctx = hmac_init(session->current_crypto->encryptMAC, hmac_digest_len(type), type); if (ctx == NULL) { SAFE_FREE(out); return NULL; } hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t)); hmac_update(ctx,data,len); hmac_final(ctx,session->current_crypto->hmacbuf,&finallen); #ifdef DEBUG_CRYPTO ssh_print_hexa("mac: ",data,hmac_digest_len(type)); if (finallen != hmac_digest_len(type)) { printf("Final len is %d\n",finallen); } ssh_print_hexa("Packet hmac", session->current_crypto->hmacbuf, hmac_digest_len(type)); #endif crypto->encrypt(crypto, data, out, len); } memcpy(data, out, len); explicit_bzero(out, len); SAFE_FREE(out); return session->current_crypto->hmacbuf; }
void fs_hmac_generic(const unsigned char *data, int size, const unsigned char *extra, int extra_size, unsigned char *hmac) { int i; hmac_ctx ctx; hmac_init(&ctx,hmac_key,0x14); hmac_update(&ctx,extra,extra_size); hmac_update(&ctx,data,size); hmac_final(&ctx,hmac); }
/* * Assumes: prng != NULL, e != NULL, len >= 0. */ static void update (HmacPrng_t prng, const uint8_t *e, uint32_t len) { const uint8_t separator0 = 0x00; const uint8_t separator1 = 0x01; /* use current state, e and separator 0 to compute a new prng key: */ (void) hmac_init (&prng->h); (void) hmac_update (&prng->h, prng->v, sizeof (prng->v)); (void) hmac_update (&prng->h, &separator0, sizeof (separator0)); (void) hmac_update (&prng->h, e, len); (void) hmac_final (prng->key, sizeof(prng->key), &prng->h); /* configure the new prng key into the prng's instance of hmac */ (void) hmac_set_key (&prng->h, prng->key, sizeof (prng->key)); /* use the new key to compute a new state variable v */ (void) hmac_init (&prng->h); (void) hmac_update (&prng->h, prng->v, sizeof (prng->v)); (void) hmac_final (prng->v, sizeof(prng->v), &prng->h); /* use current state, e and separator 1 to compute a new prng key: */ (void) hmac_init (&prng->h); (void) hmac_update (&prng->h, prng->v, sizeof (prng->v)); (void) hmac_update (&prng->h, &separator1, sizeof (separator1)); (void) hmac_update (&prng->h, e, len); (void) hmac_final (prng->key, sizeof(prng->key), &prng->h); /* configure the new prng key into the prng's instance of hmac */ (void) hmac_set_key (&prng->h, prng->key, sizeof (prng->key)); /* use the new key to compute a new state variable v */ (void) hmac_init (&prng->h); (void) hmac_update (&prng->h, prng->v, sizeof (prng->v)); (void) hmac_final (prng->v, sizeof(prng->v), &prng->h); }
int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac){ HMACCTX ctx; unsigned char hmacbuf[EVP_MAX_MD_SIZE]; unsigned int len; u32 seq=htonl(session->recv_seq); ctx=hmac_init(session->current_crypto->decryptMAC,20,HMAC_SHA1); hmac_update(ctx,(unsigned char *)&seq,sizeof(u32)); hmac_update(ctx,buffer_get(buffer),buffer_get_len(buffer)); hmac_final(ctx,hmacbuf,&len); #ifdef DEBUG_CRYPTO ssh_print_hexa("received mac",mac,len); ssh_print_hexa("Computed mac",hmacbuf,len); ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(u32)); #endif return memcmp(mac,hmacbuf,len); }
/** * Report server passphrase test result * * @v test Content information segment test * @v info Content information * @v pass Server passphrase * @v pass_len Length of server passphrase * @v file Test code file * @v line Test code line */ static void peerdist_info_passphrase_okx ( struct peerdist_info_segment_test *test, const struct peerdist_info *info, uint8_t *pass, size_t pass_len, const char *file, unsigned int line ) { struct digest_algorithm *digest = info->digest; uint8_t ctx[digest->ctxsize]; uint8_t secret[digest->digestsize]; uint8_t expected[digest->digestsize]; size_t digestsize = info->digestsize; size_t secretsize = digestsize; /* Calculate server secret */ digest_init ( digest, ctx ); digest_update ( digest, ctx, pass, pass_len ); digest_final ( digest, ctx, secret ); /* Calculate expected segment secret */ hmac_init ( digest, ctx, secret, &secretsize ); assert ( secretsize == digestsize ); hmac_update ( digest, ctx, test->expected_hash, digestsize ); hmac_final ( digest, ctx, secret, &secretsize, expected ); assert ( secretsize == digestsize ); /* Verify segment secret */ okx ( memcmp ( test->expected_secret, expected, digestsize ) == 0, file, line ); }
static bool verify_credentials(struct cram_auth_request *request, const unsigned char *credentials, size_t size) { unsigned char digest[MD5_RESULTLEN]; struct hmac_context ctx; const char *response_hex; if (size != CRAM_MD5_CONTEXTLEN) { auth_request_log_error(&request->auth_request, AUTH_SUBSYS_MECH, "invalid credentials length"); return FALSE; } hmac_init(&ctx, NULL, 0, &hash_method_md5); hmac_md5_set_cram_context(&ctx, credentials); hmac_update(&ctx, request->challenge, strlen(request->challenge)); hmac_final(&ctx, digest); response_hex = binary_to_hex(digest, sizeof(digest)); if (memcmp(response_hex, request->response, sizeof(digest)*2) != 0) { auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH, "password mismatch"); return FALSE; } return TRUE; }
const char *auth_token_get(const char *service, const char *session_pid, const char *username, const char *session_id) { struct hmac_context ctx; unsigned char result[SHA1_RESULTLEN]; hmac_init(&ctx, (const unsigned char*)username, strlen(username), &hash_method_sha1); hmac_update(&ctx, session_pid, strlen(session_pid)); if (session_id != NULL && *session_id != '\0') hmac_update(&ctx, session_id, strlen(session_id)); hmac_update(&ctx, service, strlen(service)); hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret)); hmac_final(&ctx, result); return binary_to_hex(result, sizeof(result)); }
/** * Generate secure pseudo-random data using a single hash function * * @v tls TLS session * @v digest Hash function to use * @v secret Secret * @v secret_len Length of secret * @v out Output buffer * @v out_len Length of output buffer * @v seeds ( data, len ) pairs of seed data, terminated by NULL */ static void tls_p_hash_va ( struct tls_session *tls, struct digest_algorithm *digest, void *secret, size_t secret_len, void *out, size_t out_len, va_list seeds ) { uint8_t secret_copy[secret_len]; uint8_t digest_ctx[digest->ctxsize]; uint8_t digest_ctx_partial[digest->ctxsize]; uint8_t a[digest->digestsize]; uint8_t out_tmp[digest->digestsize]; size_t frag_len = digest->digestsize; va_list tmp; /* Copy the secret, in case HMAC modifies it */ memcpy ( secret_copy, secret, secret_len ); secret = secret_copy; DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name ); DBGC2_HD ( tls, secret, secret_len ); /* Calculate A(1) */ hmac_init ( digest, digest_ctx, secret, &secret_len ); va_copy ( tmp, seeds ); tls_hmac_update_va ( digest, digest_ctx, tmp ); va_end ( tmp ); hmac_final ( digest, digest_ctx, secret, &secret_len, a ); DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name ); DBGC2_HD ( tls, &a, sizeof ( a ) ); /* Generate as much data as required */ while ( out_len ) { /* Calculate output portion */ hmac_init ( digest, digest_ctx, secret, &secret_len ); hmac_update ( digest, digest_ctx, a, sizeof ( a ) ); memcpy ( digest_ctx_partial, digest_ctx, digest->ctxsize ); va_copy ( tmp, seeds ); tls_hmac_update_va ( digest, digest_ctx, tmp ); va_end ( tmp ); hmac_final ( digest, digest_ctx, secret, &secret_len, out_tmp ); /* Copy output */ if ( frag_len > out_len ) frag_len = out_len; memcpy ( out, out_tmp, frag_len ); DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name ); DBGC2_HD ( tls, out, frag_len ); /* Calculate A(i) */ hmac_final ( digest, digest_ctx_partial, secret, &secret_len, a ); DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name ); DBGC2_HD ( tls, &a, sizeof ( a ) ); out += frag_len; out_len -= frag_len; } }
/**************************************************************************** * * Open an OSAP session * Object Specific Authorization Protocol, returned handle must manipulate * a single object given as a parameter (can introduce AuthData). * * ****************************************************************************/ uint32_t TSS_OSAPopen(struct tss_osapsess *sess, const uint8_t *key, uint16_t etype, uint32_t evalue) { struct s_tpm_osap_open_cmd cmd; uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; uint32_t nonceSize; uint32_t result; debug("TPM: TSS_OSAPopen\n"); /* check input arguments */ if (key == NULL || sess == NULL) { return TPM_E_NULL_ARG; } TlclGetRandom(sess->ononceOSAP, TPM_NONCE_SIZE, &nonceSize); memcpy(&cmd, &tpm_osap_open_cmd, sizeof(cmd)); ToTpmUint16(cmd.buffer + tpm_osap_open_cmd.type, etype); ToTpmUint32(cmd.buffer + tpm_osap_open_cmd.value, evalue); memcpy(cmd.buffer + tpm_osap_open_cmd.nonce, sess->ononceOSAP, TPM_NONCE_SIZE); result = TlclSendReceive(cmd.buffer, response, sizeof(response)); if (result == TPM_SUCCESS) { FromTpmUint32(response + kTpmResponseHeaderLength, &(sess->handle)); memcpy(sess->enonce, response + kTpmResponseHeaderLength + sizeof(uint32_t), TPM_NONCE_SIZE); memcpy(sess->enonceOSAP, response + kTpmResponseHeaderLength + sizeof(uint32_t) + TPM_NONCE_SIZE, TPM_NONCE_SIZE); debug("TPM: TSS_OSAPopen success, calculating HMAC\n"); /*DATA_DEBUG("key", key, TPM_HASH_SIZE); DATA_DEBUG("enonceOSAP", sess->enonceOSAP, TPM_NONCE_SIZE); DATA_DEBUG("ononceOSAP", sess->ononceOSAP, TPM_NONCE_SIZE);*/ /* not implemented */ SHA1_CTX hmac; hmac_starts(&hmac, key, TPM_HASH_SIZE); hmac_update(&hmac, sess->enonceOSAP, TPM_NONCE_SIZE); hmac_update(&hmac, sess->ononceOSAP, TPM_NONCE_SIZE); hmac_finish(&hmac, key, TPM_HASH_SIZE, sess->ssecret); } return result; }
/** * Update HMAC with a list of ( data, len ) pairs * * @v digest Hash function to use * @v digest_ctx Digest context * @v args ( data, len ) pairs of data, terminated by NULL */ static void tls_hmac_update_va ( struct digest_algorithm *digest, void *digest_ctx, va_list args ) { void *data; size_t len; while ( ( data = va_arg ( args, void * ) ) ) { len = va_arg ( args, size_t ); hmac_update ( digest, digest_ctx, data, len ); } }
unsigned char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){ struct crypto_struct *crypto; HMACCTX ctx; char *out; unsigned int finallen; u32 seq=ntohl(session->send_seq); if(!session->current_crypto) return NULL; /* nothing to do here */ crypto= session->current_crypto->out_cipher; ssh_log(session,SSH_LOG_PACKET,"encrypting packet with seq num: %d, len: %d",session->send_seq,len); #ifdef HAVE_LIBGCRYPT crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey,session->current_crypto->encryptIV); #elif defined HAVE_LIBCRYPTO crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey); #endif out=malloc(len); if(session->version==2){ ctx=hmac_init(session->current_crypto->encryptMAC,20,HMAC_SHA1); hmac_update(ctx,(unsigned char *)&seq,sizeof(u32)); hmac_update(ctx,data,len); hmac_final(ctx,session->current_crypto->hmacbuf,&finallen); #ifdef DEBUG_CRYPTO ssh_print_hexa("mac :",data,len); if(finallen!=20) printf("Final len is %d\n",finallen); ssh_print_hexa("packet hmac",session->current_crypto->hmacbuf,20); #endif } #ifdef HAVE_LIBGCRYPT crypto->cbc_encrypt(crypto,data,out,len); #elif defined HAVE_LIBCRYPTO crypto->cbc_encrypt(crypto,data,out,len,session->current_crypto->encryptIV); #endif memcpy(data,out,len); memset(out,0,len); free(out); if(session->version==2) return session->current_crypto->hmacbuf; else return NULL; }
static int pkcs5_pbkdf2(const struct hash_method *hash, const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len, unsigned int iter, uint32_t length, buffer_t *result) { if (length < 1 || iter < 1) return -1; size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */ unsigned char dk[l * hash->digest_size]; unsigned char *block; struct hmac_context hctx; unsigned int c,i,t; unsigned char U_c[hash->digest_size]; for(t = 0; t < l; t++) { block = &(dk[t*hash->digest_size]); /* U_1 = PRF(Password, Salt|| INT_BE32(Block_Number)) */ c = htonl(t+1); hmac_init(&hctx, password, password_len, hash); hmac_update(&hctx, salt, salt_len); hmac_update(&hctx, &c, sizeof(c)); hmac_final(&hctx, U_c); /* block = U_1 ^ .. ^ U_iter */ memcpy(block, U_c, hash->digest_size); /* U_c = PRF(Password, U_c-1) */ for(c = 1; c < iter; c++) { hmac_init(&hctx, password, password_len, hash); hmac_update(&hctx, U_c, hash->digest_size); hmac_final(&hctx, U_c); for(i = 0; i < hash->digest_size; i++) block[i] ^= U_c[i]; } } buffer_append(result, dk, length); return 0; }
size_t hmac_sha(const hash_t *key, const hash_t *msg, hash_t *hash, const evp_md_t *md) { size_t len; hash_t buff[MAX_LEN]; hmac_ctx_t ctx; hmac_ctx_init(&ctx); hmac_init(&ctx, key, strlen((char *)key), md); hmac_update(&ctx, msg, strlen((char *)msg)); hmac_final(&ctx, buff, (unsigned int *)&len); hmac_ctx_cleanup(&ctx); memcpy(hash, buff, len); return len; }
void do_hmac_test ( HmacState_t h, uint32_t testnum, const uint8_t *data, size_t datalen, const uint8_t *expected, size_t expectedlen) { uint8_t digest[32]; (void) hmac_init (h); (void) hmac_update (h, data, datalen); (void) hmac_final (digest, SHA256_DIGEST_SIZE, h); check_result(testnum, expected, expectedlen, digest, sizeof(digest), 1); }
/** * @internal * * @brief Verify the hmac of a packet * * @param session The session to use. * @param buffer The buffer to verify the hmac from. * @param mac The mac to compare with the hmac. * * @return 0 if hmac and mac are equal, < 0 if not or an error * occurred. */ int ssh_packet_hmac_verify(ssh_session session, ssh_buffer buffer, uint8_t *mac, enum ssh_hmac_e type) { unsigned char hmacbuf[DIGEST_MAX_LEN] = {0}; HMACCTX ctx; unsigned int len; uint32_t seq; /* AEAD type have no mac checking */ if (type == SSH_HMAC_AEAD_POLY1305) { return SSH_OK; } ctx = hmac_init(session->current_crypto->decryptMAC, hmac_digest_len(type), type); if (ctx == NULL) { return -1; } seq = htonl(session->recv_seq); hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t)); hmac_update(ctx, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); hmac_final(ctx, hmacbuf, &len); #ifdef DEBUG_CRYPTO ssh_print_hexa("received mac",mac,len); ssh_print_hexa("Computed mac",hmacbuf,len); ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(uint32_t)); #endif if (secure_memcmp(mac, hmacbuf, len) == 0) { return 0; } return -1; }
/** * Calculate HMAC-SHA1 MIC for EAPOL-Key frame * * @v kck Key Confirmation Key, 16 bytes * @v msg Message to calculate MIC over * @v len Number of bytes to calculate MIC over * @ret mic Calculated MIC, 16 bytes long */ static void ccmp_kie_mic ( const void *kck, const void *msg, size_t len, void *mic ) { u8 sha1_ctx[SHA1_CTX_SIZE]; u8 kckb[16]; u8 hash[SHA1_SIZE]; size_t kck_len = 16; memcpy ( kckb, kck, kck_len ); hmac_init ( &sha1_algorithm, sha1_ctx, kckb, &kck_len ); hmac_update ( &sha1_algorithm, sha1_ctx, msg, len ); hmac_final ( &sha1_algorithm, sha1_ctx, kckb, &kck_len, hash ); memcpy ( mic, hash, 16 ); }
buffer_t *t_hmac_data(const struct hash_method *meth, const unsigned char *key, size_t key_len, const void *data, size_t data_len) { struct hmac_context ctx; i_assert(meth != NULL); i_assert(key != NULL && key_len > 0); i_assert(data != NULL || data_len == 0); buffer_t *res = buffer_create_dynamic(pool_datastack_create(), meth->digest_size); hmac_init(&ctx, key, key_len, meth); if (data_len > 0) hmac_update(&ctx, data, data_len); unsigned char *buf = buffer_get_space_unsafe(res, 0, meth->digest_size); hmac_final(&ctx, buf); return res; }
void v2prfplus(struct v2prf_stuff *vps) { struct hmac_ctx ctx; hmac_init_chunk(&ctx, vps->prf_hasher, *vps->skeyseed); hmac_update_chunk(&ctx, vps->t); hmac_update_chunk(&ctx, vps->ni); hmac_update_chunk(&ctx, vps->nr); hmac_update_chunk(&ctx, vps->spii); hmac_update_chunk(&ctx, vps->spir); hmac_update(&ctx, vps->counter, 1); hmac_final_chunk(vps->t, "skeyseed_t1", &ctx); DBG(DBG_CRYPT, { char b[20]; sprintf(b, "prf+[%u]:", vps->counter[0]); DBG_dump_chunk(b, vps->t); });
static const unsigned char * imap_urlauth_internal_generate(const char *rumpurl, const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN], size_t *token_len_r) { struct hmac_context hmac; unsigned char *token; token = t_new(unsigned char, SHA1_RESULTLEN + 1); token[0] = IMAP_URLAUTH_MECH_INTERNAL_VERSION; hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1); hmac_update(&hmac, rumpurl, strlen(rumpurl)); hmac_final(&hmac, token+1); *token_len_r = SHA1_RESULTLEN + 1; return token; }
err_status_t hmac_compute(hmac_ctx_t *state, const void *message, int msg_octets, int tag_len, uint8_t *result) { uint32_t hash_value[5]; uint32_t H[5]; int i; /* check tag length, return error if we can't provide the value expected */ if (tag_len > 20) return err_status_bad_param; /* hash message, copy output into H */ hmac_update(state, (const uint8_t*)message, msg_octets); sha1_final(&state->ctx, H); /* * note that we don't need to debug_print() the input, since the * function hmac_update() already did that for us */ debug_print(mod_hmac, "intermediate state: %s", octet_string_hex_string((uint8_t *)H, 20)); /* re-initialize hash context */ sha1_init(&state->ctx); /* hash opad ^ key */ sha1_update(&state->ctx, (uint8_t *)state->opad, 64); /* hash the result of the inner hash */ sha1_update(&state->ctx, (uint8_t *)H, 20); /* the result is returned in the array hash_value[] */ sha1_final(&state->ctx, hash_value); /* copy hash_value to *result */ for (i=0; i < tag_len; i++) result[i] = ((uint8_t *)hash_value)[i]; debug_print(mod_hmac, "output: %s", octet_string_hex_string((uint8_t *)hash_value, tag_len)); return err_status_ok; }
/** * Update the HMAC_DRBG value * * @v hash Underlying hash algorithm * @v state HMAC_DRBG internal state * @v data Provided data * @v len Length of provided data * @v single Single byte used in concatenation * * This function carries out the operation * * V = HMAC ( K, V ) * * as used by hmac_drbg_update() and hmac_drbg_generate() */ static void hmac_drbg_update_value ( struct digest_algorithm *hash, struct hmac_drbg_state *state ) { uint8_t context[ hash->ctxsize ]; size_t out_len = hash->digestsize; /* Sanity checks */ assert ( hash != NULL ); assert ( state != NULL ); /* V = HMAC ( K, V ) */ hmac_init ( hash, context, state->key, &out_len ); assert ( out_len == hash->digestsize ); hmac_update ( hash, context, state->value, out_len ); hmac_final ( hash, context, state->key, &out_len, state->value ); assert ( out_len == hash->digestsize ); DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n", hash->name, state ); DBGC_HDA ( state, 0, state->value, out_len ); }
int compute_context_digest(TPM_CONTEXT_BLOB *contextBlob, TPM_DIGEST *digest) { BYTE *buf, *ptr; UINT32 len; hmac_ctx_t hmac_ctx; len = sizeof_TPM_CONTEXT_BLOB((*contextBlob)); buf = ptr = tpm_malloc(len); if (buf == NULL) return -1; if (tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, contextBlob)) { tpm_free(buf); return -1; } memset(&buf[30], 0, 20); hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(tpmData.permanent.data.tpmProof.nonce)); hmac_update(&hmac_ctx, buf, sizeof_TPM_CONTEXT_BLOB((*contextBlob))); hmac_final(&hmac_ctx, digest->digest); tpm_free(buf); return 0; }
int32_t hmac_prng_generate ( uint8_t *out, /* IN/OUT -- buffer to receive output */ uint32_t outlen, /* IN -- size of out buffer in bytes */ HmacPrng_t prng) { /* IN/OUT -- the PRNG state */ uint32_t bufferlen; /* input sanity check: */ if (out == (uint8_t *) 0 || prng == (HmacPrng_t) 0 || outlen == 0 || outlen > MAX_OUT) { return 0; } else if (prng->countdown == 0) { return -1; } prng->countdown--; while (outlen != 0) { /* operate HMAC in OFB mode to create "random" outputs */ (void) hmac_init (&prng->h); (void) hmac_update (&prng->h, prng->v, sizeof (prng->v)); (void) hmac_final (prng->v, sizeof(prng->v), &prng->h); bufferlen = (SHA256_DIGEST_SIZE > outlen) ? outlen : SHA256_DIGEST_SIZE; (void) copy (out, bufferlen, prng->v, bufferlen); out += bufferlen; outlen = (outlen > SHA256_DIGEST_SIZE) ? (outlen - SHA256_DIGEST_SIZE) : 0; } /* block future PRNG compromises from revealing past state */ update (prng, prng->v, SHA256_DIGEST_SIZE); return 1; }
err_status_t aes_128_cbc_hmac_sha1_96_dec(void *key, const void *clear, unsigned clear_len, void *iv, void *opaque, unsigned *opaque_len) { aes_cbc_ctx_t aes_ctx; hmac_ctx_t hmac_ctx; unsigned char enc_key[ENC_KEY_LEN]; unsigned char mac_key[MAC_KEY_LEN]; unsigned char tmp_tag[TAG_LEN]; unsigned char *auth_tag; unsigned ciphertext_len; err_status_t status; int i; /* check if we're doing authentication only */ if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { /* perform authentication only */ } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { /* * bad parameter - we expect either all three pointers to be NULL, * or none of those pointers to be NULL */ return err_status_fail; } else { #if DEBUG printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN)); #endif /* derive encryption and authentication keys from the input key */ status = hmac_init(&hmac_ctx, key, KEY_LEN); if (status) return status; status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); if (status) return status; status = hmac_init(&hmac_ctx, key, KEY_LEN); if (status) return status; status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); if (status) return status; #if DEBUG printf("prot data len: %d\n", *opaque_len); printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len)); #endif /* * set the protected data length to that of the ciphertext, by * subtracting out the length of the authentication tag */ ciphertext_len = *opaque_len - TAG_LEN; #if DEBUG printf("ciphertext len: %d\n", ciphertext_len); #endif /* verify the authentication tag */ /* * compute the authentication tag for the clear and opaque data, * and write it to a temporary location */ status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); if (status) return status; status = hmac_start(&hmac_ctx); if (status) return status; status = hmac_update(&hmac_ctx, clear, clear_len); if (status) return status; #if DEBUG printf("hmac input: %s\n", octet_string_hex_string(clear, clear_len)); #endif status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag); if (status) return status; #if DEBUG printf("hmac input: %s\n", octet_string_hex_string(opaque, ciphertext_len)); #endif /* * compare the computed tag with the one provided as input (which * immediately follows the ciphertext) */ auth_tag = (unsigned char *)opaque; auth_tag += ciphertext_len; #if DEBUG printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN)); printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN)); #endif for (i=0; i < TAG_LEN; i++) { if (tmp_tag[i] != auth_tag[i]) return err_status_auth_fail; } /* bump down the opaque_len to reflect the authentication tag */ *opaque_len -= TAG_LEN; /* decrypt the confidential data */ status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt); if (status) return status; status = aes_cbc_set_iv(&aes_ctx, iv); if (status) return status; #if DEBUG printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len)); printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); #endif #if ENC status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len); if (status) return status; #endif #if DEBUG printf("plaintext len: %d\n", ciphertext_len); printf("plaintext: %s\n", octet_string_hex_string(opaque, ciphertext_len)); #endif /* indicate the length of the plaintext */ *opaque_len = ciphertext_len; } return err_status_ok; }
/** * @brief Check if a hostname matches a openssh-style hashed known host. * * @param[in] host The host to check. * * @param[in] hashed The hashed value. * * @returns 1 if it matches, 0 otherwise. */ static int match_hashed_host(ssh_session session, const char *host, const char *sourcehash) { /* Openssh hash structure : * |1|base64 encoded salt|base64 encoded hash * hash is produced that way : * hash := HMAC_SHA1(key=salt,data=host) */ unsigned char buffer[256] = {0}; ssh_buffer salt; ssh_buffer hash; HMACCTX mac; char *source; char *b64hash; int match; unsigned int size; enter_function(); if (strncmp(sourcehash, "|1|", 3) != 0) { leave_function(); return 0; } source = strdup(sourcehash + 3); if (source == NULL) { leave_function(); return 0; } b64hash = strchr(source, '|'); if (b64hash == NULL) { /* Invalid hash */ SAFE_FREE(source); leave_function(); return 0; } *b64hash = '\0'; b64hash++; salt = base64_to_bin(source); if (salt == NULL) { SAFE_FREE(source); leave_function(); return 0; } hash = base64_to_bin(b64hash); SAFE_FREE(source); if (hash == NULL) { ssh_buffer_free(salt); leave_function(); return 0; } mac = hmac_init(buffer_get_rest(salt), buffer_get_rest_len(salt), HMAC_SHA1); if (mac == NULL) { ssh_buffer_free(salt); ssh_buffer_free(hash); leave_function(); return 0; } size = sizeof(buffer); hmac_update(mac, host, strlen(host)); hmac_final(mac, buffer, &size); if (size == buffer_get_rest_len(hash) && memcmp(buffer, buffer_get_rest(hash), size) == 0) { match = 1; } else { match = 0; } ssh_buffer_free(salt); ssh_buffer_free(hash); ssh_log(session, SSH_LOG_PACKET, "Matching a hashed host: %s match=%d", host, match); leave_function(); return match; }
err_status_t aes_128_cbc_hmac_sha1_96_inv(void *key, void *clear, unsigned clear_len, void *iv, void *opaque, unsigned *opaque_len, void *auth_tag) { aes_cbc_ctx_t aes_ctx; hmac_ctx_t hmac_ctx; unsigned char enc_key[ENC_KEY_LEN]; unsigned char mac_key[MAC_KEY_LEN]; unsigned char tmp_tag[TAG_LEN]; unsigned char *tag = auth_tag; err_status_t status; int i; /* check if we're doing authentication only */ if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { /* perform authentication only */ } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { /* * bad parameter - we expect either all three pointers to be NULL, * or none of those pointers to be NULL */ return err_status_fail; } else { /* derive encryption and authentication keys from the input key */ status = hmac_init(&hmac_ctx, key, KEY_LEN); if (status) return status; status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); if (status) return status; status = hmac_init(&hmac_ctx, key, KEY_LEN); if (status) return status; status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); if (status) return status; /* perform encryption and authentication */ /* set aes key */ status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt); if (status) return status; /* set iv */ status = rand_source_get_octet_string(iv, IV_LEN); if (status) return status; status = aes_cbc_set_iv(&aes_ctx, iv); /* encrypt the opaque data */ status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len); if (status) return status; /* authenticate clear and opaque data */ status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); if (status) return status; status = hmac_start(&hmac_ctx); if (status) return status; status = hmac_update(&hmac_ctx, clear, clear_len); if (status) return status; status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag); if (status) return status; /* compare the computed tag with the one provided as input */ for (i=0; i < TAG_LEN; i++) if (tmp_tag[i] != tag[i]) return err_status_auth_fail; } return err_status_ok; }