static int wrap_padlock_hmac_fast (gnutls_mac_algorithm_t algo, const void *key, size_t key_size, const void *text, size_t text_size, void *digest) { if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) { unsigned char *pad; unsigned char pad2[SHA1_DATA_SIZE + MAX_SHA_DIGEST_SIZE]; unsigned char hkey[MAX_SHA_DIGEST_SIZE]; unsigned int digest_size = _gnutls_hmac_get_algo_len (algo); if (key_size > SHA1_DATA_SIZE) { wrap_padlock_hash_fast (algo, key, key_size, hkey); key = hkey; key_size = digest_size; } pad = gnutls_malloc (text_size + SHA1_DATA_SIZE); if (pad == NULL) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); memset (pad, IPAD, SHA1_DATA_SIZE); memxor (pad, key, key_size); memcpy (&pad[SHA1_DATA_SIZE], text, text_size); wrap_padlock_hash_fast (algo, pad, text_size + SHA1_DATA_SIZE, &pad2[SHA1_DATA_SIZE]); gnutls_free (pad); memset (pad2, OPAD, SHA1_DATA_SIZE); memxor (pad2, key, key_size); wrap_padlock_hash_fast (algo, pad2, digest_size + SHA1_DATA_SIZE, digest); } else { struct padlock_hmac_ctx ctx; int ret; ret = _hmac_ctx_init (algo, &ctx); if (ret < 0) return gnutls_assert_val (ret); ctx.algo = algo; wrap_padlock_hmac_setkey (&ctx, key, key_size); wrap_padlock_hmac_update (&ctx, text, text_size); wrap_padlock_hmac_output (&ctx, digest, ctx.length); } return 0; }
int _gnutls_epoch_set_keys (gnutls_session_t session, uint16_t epoch) { int hash_size; int IV_size; int key_size, export_flag; gnutls_cipher_algorithm_t cipher_algo; gnutls_mac_algorithm_t mac_algo; gnutls_compression_method_t comp_algo; record_parameters_st *params; int ret; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_epoch_get (session, epoch, ¶ms); if (ret < 0) return gnutls_assert_val (ret); if (params->initialized) return 0; _gnutls_record_log ("REC[%p]: Initializing epoch #%u\n", session, params->epoch); cipher_algo = params->cipher_algorithm; mac_algo = params->mac_algorithm; comp_algo = params->compression_algorithm; if (_gnutls_cipher_is_ok (cipher_algo) != 0 || _gnutls_mac_is_ok (mac_algo) != 0) return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR); if (_gnutls_compression_is_ok (comp_algo) != 0) return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM); IV_size = _gnutls_cipher_get_iv_size (cipher_algo); key_size = gnutls_cipher_get_key_size (cipher_algo); export_flag = _gnutls_cipher_get_export_flag (cipher_algo); hash_size = _gnutls_hmac_get_algo_len (mac_algo); ret = _gnutls_set_keys (session, params, hash_size, IV_size, key_size, export_flag); if (ret < 0) return gnutls_assert_val (ret); ret = _gnutls_init_record_state (params, ver, 1, ¶ms->read); if (ret < 0) return gnutls_assert_val (ret); ret = _gnutls_init_record_state (params, ver, 0, ¶ms->write); if (ret < 0) return gnutls_assert_val (ret); params->record_sw_size = 0; _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session, params->epoch); params->initialized = 1; return 0; }
/* returns overhead imposed by the record layer (encryption/compression) * etc. It does not include the record layer headers, since the caller * needs to cope with rounding to multiples of blocksize, and the header * is outside that. * * blocksize: will contain the block size when padding may be required or 1 * * It may return a negative error code on error. */ static int record_overhead_rt(gnutls_session_t session, unsigned int *blocksize) { record_parameters_st *params; int total = 0, ret, iv_size; if (session->internals.initial_negotiation_completed == 0) return GNUTLS_E_INVALID_REQUEST; ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, ¶ms); if (ret < 0) return gnutls_assert_val(ret); /* requires padding */ iv_size = _gnutls_cipher_get_iv_size(params->cipher_algorithm); if (_gnutls_cipher_is_block (params->cipher_algorithm) == CIPHER_BLOCK) { *blocksize = iv_size; total += iv_size; /* iv_size == block_size in DTLS */ /* We always pad with at least one byte; never 0. */ total++; } else { *blocksize = 1; } if (params->mac_algorithm == GNUTLS_MAC_AEAD) total += _gnutls_cipher_get_tag_size(params->cipher_algorithm); else { ret = _gnutls_hmac_get_algo_len(params->mac_algorithm); if (ret < 0) return gnutls_assert_val(ret); total+=ret; } if (params->compression_algorithm != GNUTLS_COMP_NULL) total += EXTRA_COMP_SIZE; return total; }