static int ssl3_md5(int i, uint8_t * secret, int secret_len, uint8_t * rnd, int rnd_len, void *digest) { uint8_t tmp[MAX_HASH_SIZE]; digest_hd_st td; int ret; ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td, secret, secret_len); ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp); if (ret < 0) { gnutls_assert(); _gnutls_hash_deinit(&td, digest); return ret; } _gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT); _gnutls_hash_deinit(&td, digest); return 0; }
/* generate x = SHA(s | SHA(U | ":" | p)) * The output is exactly 20 bytes */ int _gnutls_calc_srp_sha (const char *username, const char *password, opaque * salt, int salt_size, size_t * size, void *digest) { GNUTLS_HASH_HANDLE td; opaque res[MAX_HASH_SIZE]; *size = 20; td = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (td == NULL) { return GNUTLS_E_MEMORY_ERROR; } _gnutls_hash (td, username, strlen (username)); _gnutls_hash (td, ":", 1); _gnutls_hash (td, password, strlen (password)); _gnutls_hash_deinit (td, res); td = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (td == NULL) { return GNUTLS_E_MEMORY_ERROR; } _gnutls_hash (td, salt, salt_size); _gnutls_hash (td, res, 20); /* 20 bytes is the output of sha1 */ _gnutls_hash_deinit (td, digest); return 0; }
/* generate x = SHA(s | SHA(U | ":" | p)) * The output is exactly 20 bytes */ static int _gnutls_calc_srp_sha(const char *username, const char *password, uint8_t * salt, int salt_size, size_t * size, void *digest) { digest_hd_st td; uint8_t res[MAX_HASH_SIZE]; int ret; const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1); *size = 20; ret = _gnutls_hash_init(&td, me); if (ret < 0) { return GNUTLS_E_MEMORY_ERROR; } _gnutls_hash(&td, username, strlen(username)); _gnutls_hash(&td, ":", 1); _gnutls_hash(&td, password, strlen(password)); _gnutls_hash_deinit(&td, res); ret = _gnutls_hash_init(&td, me); if (ret < 0) { return GNUTLS_E_MEMORY_ERROR; } _gnutls_hash(&td, salt, salt_size); _gnutls_hash(&td, res, 20); /* 20 bytes is the output of sha1 */ _gnutls_hash_deinit(&td, digest); return 0; }
static int openssl_hash_password(const char *pass, gnutls_datum_t * key, gnutls_datum_t * salt) { unsigned char md5[16]; digest_hd_st hd; unsigned int count = 0; int err; while (count < key->size) { err = _gnutls_hash_init(&hd, mac_to_entry(GNUTLS_MAC_MD5)); if (err) { gnutls_assert(); return err; } if (count) { err = _gnutls_hash(&hd, md5, sizeof(md5)); if (err) { hash_err: _gnutls_hash_deinit(&hd, NULL); gnutls_assert(); return err; } } if (pass) { err = _gnutls_hash(&hd, pass, strlen(pass)); if (err) { gnutls_assert(); goto hash_err; } } err = _gnutls_hash(&hd, salt->data, 8); if (err) { gnutls_assert(); goto hash_err; } _gnutls_hash_deinit(&hd, md5); if (key->size - count <= sizeof(md5)) { memcpy(&key->data[count], md5, key->size - count); break; } memcpy(&key->data[count], md5, sizeof(md5)); count += sizeof(md5); } return 0; }
int _gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle, void *digest, uint8_t * key, uint32_t key_size) { uint8_t ret[MAX_HASH_SIZE]; digest_hd_st td; uint8_t opad[48]; uint8_t ipad[48]; int padsize; int block, rc; padsize = get_padsize(handle->e->id); if (padsize == 0) { gnutls_assert(); rc = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } memset(opad, 0x5C, padsize); memset(ipad, 0x36, padsize); rc = _gnutls_hash_init(&td, handle->e); if (rc < 0) { gnutls_assert(); goto cleanup; } if (key_size > 0) _gnutls_hash(&td, key, key_size); _gnutls_hash(&td, opad, padsize); block = _gnutls_mac_get_algo_len(handle->e); if (key_size > 0) _gnutls_hash(handle, key, key_size); _gnutls_hash(handle, ipad, padsize); _gnutls_hash_deinit(handle, ret); /* get the previous hash */ _gnutls_hash(&td, ret, block); _gnutls_hash_deinit(&td, digest); return 0; cleanup: _gnutls_hash_deinit(handle, NULL); return rc; }
/* Hashes input data and verifies a DSA signature. */ static int dsa_verify_sig (const gnutls_datum_t * text, const gnutls_datum_t * hash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { int ret; opaque _digest[MAX_HASH_SIZE]; gnutls_datum_t digest; digest_hd_st hd; if (hash && hash->data && hash->size == 20) { digest = *hash; } else { ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, _digest); digest.data = _digest; digest.size = 20; } ret = _gnutls_dsa_verify (&digest, signature, params, params_len); return ret; }
static int dsa_sign (const gnutls_datum_t * text, bigint_t * params, int params_len, gnutls_datum_t * signature) { int ret; opaque _digest[MAX_HASH_SIZE]; digest_hd_st hd; gnutls_datum_t digest; gnutls_digest_algorithm_t hash = _gnutls_dsa_q_to_hash (params[1]); ret = _gnutls_hash_init (&hd, hash); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, _digest); digest.data = _digest; digest.size = _gnutls_hash_get_algo_len (hash); if ((ret = _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest, signature)) < 0) { gnutls_assert (); return ret; } return 0; }
static int ssl3_sha(int i, uint8_t * secret, int secret_len, uint8_t * rnd, int rnd_len, void *digest) { int j, ret; uint8_t text1[26]; digest_hd_st td; for (j = 0; j < i + 1; j++) { text1[j] = 65 + i; /* A==65 */ } ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td, text1, i + 1); _gnutls_hash(&td, secret, secret_len); _gnutls_hash(&td, rnd, rnd_len); _gnutls_hash_deinit(&td, digest); return 0; }
int _gnutls_ssl3_hash_md5(const void *first, int first_len, const void *second, int second_len, int ret_len, uint8_t * ret) { uint8_t digest[MAX_HASH_SIZE]; digest_hd_st td; int block = MD5_DIGEST_OUTPUT; int rc; rc = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5)); if (rc < 0) { gnutls_assert(); return rc; } _gnutls_hash(&td, first, first_len); _gnutls_hash(&td, second, second_len); _gnutls_hash_deinit(&td, digest); if (ret_len > block) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } memcpy(ret, digest, ret_len); return 0; }
/** * cdk_pk_get_fingerprint: * @pk: the public key * @fpr: the buffer to hold the fingerprint * * Return the fingerprint of the given public key. * The buffer must be at least 20 octets. * This function should be considered deprecated and * the new cdk_pk_to_fingerprint() should be used whenever * possible to avoid overflows. **/ cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr) { digest_hd_st hd; int md_algo; int dlen = 0; int err; if (!pk || !fpr) return CDK_Inv_Value; if (pk->version < 4 && is_RSA (pk->pubkey_algo)) md_algo = GNUTLS_DIG_MD5; /* special */ else md_algo = GNUTLS_DIG_SHA1; dlen = _gnutls_hash_get_algo_len (md_algo); err = _gnutls_hash_init (&hd, md_algo); if (err < 0) { gnutls_assert (); return map_gnutls_error (err); } _cdk_hash_pubkey (pk, &hd, 1); _gnutls_hash_deinit (&hd, fpr); if (dlen == 16) memset (fpr + 16, 0, 4); return 0; }
static int dsa_sign (const gnutls_datum_t * text, mpi_t * params, int params_len, gnutls_datum_t * signature) { int ret; opaque _digest[MAX_HASH_SIZE]; GNUTLS_HASH_HANDLE hd; gnutls_datum_t digest; hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (hd == NULL) { gnutls_assert (); return GNUTLS_E_HASH_FAILED; } _gnutls_hash (hd, text->data, text->size); _gnutls_hash_deinit (hd, _digest); digest.data = _digest; digest.size = 20; if ((ret = _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest, signature)) < 0) { gnutls_assert (); return ret; } return 0; }
/* this is _gnutls_handshake_verify_cert_vrfy for TLS 1.2 */ static int _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session, gnutls_pcert_st* cert, gnutls_datum_t * signature, gnutls_sign_algorithm_t sign_algo) { int ret; opaque concat[MAX_SIG_SIZE]; digest_hd_st td; gnutls_datum_t dconcat; gnutls_sign_algorithm_t _sign_algo; gnutls_digest_algorithm_t hash_algo; digest_hd_st *handshake_td; gnutls_protocol_t ver = gnutls_protocol_get_version (session); gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); handshake_td = &session->internals.handshake_mac_handle.tls12.sha1; hash_algo = handshake_td->algorithm; _sign_algo = _gnutls_x509_pk_to_sign (pk, hash_algo); if (_sign_algo != sign_algo) { handshake_td = &session->internals.handshake_mac_handle.tls12.sha256; hash_algo = handshake_td->algorithm; _sign_algo = _gnutls_x509_pk_to_sign (pk, hash_algo); if (sign_algo != _sign_algo) { gnutls_assert (); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } } ret = _gnutls_hash_copy (&td, handshake_td); if (ret < 0) { gnutls_assert (); return GNUTLS_E_HASH_FAILED; } _gnutls_hash_deinit (&td, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len (hash_algo); ret = verify_tls_hash (ver, cert, &dconcat, signature, 0, pk); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest) { int ret = 0; if (digest != NULL) ret = _gnutls_mac_output_ssl3(handle, digest); _gnutls_hash_deinit(handle, NULL); return ret; }
/* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2 */ static int _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session, gnutls_pcert_st* cert, gnutls_privkey_t pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; opaque concat[MAX_SIG_SIZE]; digest_hd_st td; gnutls_sign_algorithm_t sign_algo; gnutls_digest_algorithm_t hash_algo; digest_hd_st *handshake_td; sign_algo = _gnutls_session_get_sign_algo (session, cert); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo); _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n", gnutls_sign_algorithm_get_name (sign_algo), gnutls_mac_get_name (hash_algo)); if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm) handshake_td = &session->internals.handshake_mac_handle.tls12.sha1; else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm) handshake_td = &session->internals.handshake_mac_handle.tls12.sha256; else return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */ ret = _gnutls_hash_copy (&td, handshake_td); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash_deinit (&td, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len (hash_algo); ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); return ret; } return sign_algo; }
/* This calculates the SHA1(A | B) * A and B will be left-padded with zeros to fill n_size. */ mpi_t _gnutls_calc_srp_u (mpi_t A, mpi_t B, mpi_t n) { size_t b_size, a_size; opaque *holder, hd[MAX_HASH_SIZE]; size_t holder_size, hash_size, n_size; GNUTLS_HASH_HANDLE td; int ret; mpi_t res; /* get the size of n in bytes */ _gnutls_mpi_print (NULL, &n_size, n); _gnutls_mpi_print (NULL, &a_size, A); _gnutls_mpi_print (NULL, &b_size, B); if (a_size > n_size || b_size > n_size) { gnutls_assert (); return NULL; /* internal error */ } holder_size = n_size + n_size; holder = gnutls_calloc (1, holder_size); if (holder == NULL) return NULL; _gnutls_mpi_print (&holder[n_size - a_size], &a_size, A); _gnutls_mpi_print (&holder[n_size + n_size - b_size], &b_size, B); td = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (td == NULL) { gnutls_free (holder); gnutls_assert (); return NULL; } _gnutls_hash (td, holder, holder_size); _gnutls_hash_deinit (td, hd); /* convert the bytes of hd to integer */ hash_size = 20; /* SHA */ ret = _gnutls_mpi_scan_nz (&res, hd, &hash_size); gnutls_free (holder); if (ret < 0) { gnutls_assert (); return NULL; } return res; }
/* Hashes input data and verifies a DSA signature. */ static int dsa_verify_sig (const gnutls_datum_t * text, const gnutls_datum_t * hash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { int ret; opaque _digest[MAX_HASH_SIZE]; gnutls_datum_t digest; digest_hd_st hd; gnutls_digest_algorithm_t algo; unsigned int hash_len; algo = _gnutls_dsa_q_to_hash (params[1], &hash_len); if (hash) { /* SHA1 or better allowed */ if (!hash->data || hash->size < hash_len) { gnutls_assert(); _gnutls_debug_log("Hash size (%d) does not correspond to hash %s", (int)hash->size, gnutls_mac_get_name(algo)); if (hash->size != 20) return GNUTLS_E_PK_SIG_VERIFY_FAILED; } digest = *hash; } else { ret = _gnutls_hash_init (&hd, algo); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, _digest); digest.data = _digest; digest.size = _gnutls_hash_get_algo_len(algo); } ret = _gnutls_dsa_verify (&digest, signature, params, params_len); return ret; }
/* if hash==MD5 then we do RSA-MD5 * if hash==SHA then we do RSA-SHA * params[0] is modulus * params[1] is public key */ static int pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text, bigint_t * params, int params_len, gnutls_datum_t * signature) { int ret; opaque _digest[MAX_HASH_SIZE]; digest_hd_st hd; gnutls_datum_t digest, info; ret = _gnutls_hash_init (&hd, HASH2MAC (hash)); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, _digest); digest.data = _digest; digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash)); /* Encode the digest as a DigestInfo */ if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0) { gnutls_assert (); return ret; } if ((ret = _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info, signature)) < 0) { gnutls_assert (); _gnutls_free_datum (&info); return ret; } _gnutls_free_datum (&info); return 0; }
cdk_error_t _cdk_filter_hash (void *data, int ctl, FILE * in, FILE * out) { if (ctl == STREAMCTL_READ) return hash_encode (data, in, out); else if (ctl == STREAMCTL_FREE) { md_filter_t *mfx = data; if (mfx) { _cdk_log_debug ("free hash filter\n"); _gnutls_hash_deinit (&mfx->md, NULL); mfx->md_initialized = 0; return 0; } } gnutls_assert (); return CDK_Inv_Mode; }
int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest) { uint8_t ret[MAX_HASH_SIZE]; digest_hd_st td; uint8_t opad[48]; int padsize; int block, rc; padsize = get_padsize(handle->e->id); if (padsize == 0) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } memset(opad, 0x5C, padsize); rc = _gnutls_hash_init(&td, handle->e); if (rc < 0) { gnutls_assert(); return rc; } if (handle->keysize > 0) _gnutls_hash(&td, handle->key, handle->keysize); _gnutls_hash(&td, opad, padsize); block = _gnutls_mac_get_algo_len(handle->e); _gnutls_hash_output(handle, ret); /* get the previous hash */ _gnutls_hash(&td, ret, block); _gnutls_hash_deinit(&td, digest); /* reset handle */ memset(opad, 0x36, padsize); if (handle->keysize > 0) _gnutls_hash(handle, handle->key, handle->keysize); _gnutls_hash(handle, opad, padsize); return 0; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert, const gnutls_datum_t * params, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; digest_hd_st td_md5; digest_hd_st td_sha; opaque concat[36]; gnutls_protocol_t ver = gnutls_protocol_get_version (session); if (ver < GNUTLS_TLS1_2) { ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_md5, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, params->data, params->size); } ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1); if (ret < 0) { gnutls_assert (); if (ver < GNUTLS_TLS1_2) _gnutls_hash_deinit (&td_md5, NULL); return ret; } _gnutls_hash (&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, params->data, params->size); if (ver < GNUTLS_TLS1_2) { _gnutls_hash_deinit (&td_md5, concat); _gnutls_hash_deinit (&td_sha, &concat[16]); dconcat.size = 36; } else { #if 1 /* Use NULL parameters. */ memcpy (concat, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", 15); _gnutls_hash_deinit (&td_sha, &concat[15]); dconcat.size = 35; #else /* No parameters field. */ memcpy (concat, "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13); _gnutls_hash_deinit (&td_sha, &concat[13]); dconcat.size = 33; #endif } dconcat.data = concat; ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
/* Generates a signature of all the previous sent packets in the * handshake procedure. (20040227: now it works for SSL 3.0 as well) */ int _gnutls_tls_sign_hdata (gnutls_session_t session, gnutls_cert * cert, gnutls_privkey * pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; opaque concat[36]; digest_hd_st td_md5; digest_hd_st td_sha; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha); if (ret < 0) { gnutls_assert (); return ret; } if (ver == GNUTLS_SSL3) { ret = _gnutls_generate_master (session, 1); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16], session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); } else _gnutls_hash_deinit (&td_sha, &concat[16]); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: ret = _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5); if (ret < 0) { gnutls_assert (); return ret; } if (ver == GNUTLS_SSL3) _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat, session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); else _gnutls_hash_deinit (&td_md5, concat); dconcat.data = concat; dconcat.size = 36; break; case GNUTLS_PK_DSA: dconcat.data = &concat[16]; dconcat.size = 20; break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); } return ret; }
void RIPEMD160_Final (unsigned char *md, RIPEMD160_CTX * ctx) { _gnutls_hash_deinit (ctx->handle, md); gnutls_free (ctx->handle); }
void MD5_Final (unsigned char *md, MD5_CTX * ctx) { _gnutls_hash_deinit (ctx->handle, md); gnutls_free (ctx->handle); }
/** * gnutls_x509_privkey_get_key_id - Return unique ID of the key's parameters * @key: Holds the key * @flags: should be 0 for now * @output_data: will contain the key ID * @output_data_size: holds the size of output_data (and will be * replaced by the actual size of parameters) * * This function will return a unique ID the depends on the public key * parameters. This ID can be used in checking whether a certificate * corresponds to the given key. * * If the buffer provided is not long enough to hold the output, then * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will * be returned. The output will normally be a SHA-1 hash output, * which is 20 bytes. * * Return value: In case of failure a negative value will be * returned, and 0 on success. * **/ int gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key, unsigned int flags, unsigned char *output_data, size_t * output_data_size) { int result; GNUTLS_HASH_HANDLE hd; gnutls_datum_t der = { NULL, 0 }; if (key == NULL || key->crippled) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (*output_data_size < 20) { gnutls_assert (); *output_data_size = 20; return GNUTLS_E_SHORT_MEMORY_BUFFER; } if (key->pk_algorithm == GNUTLS_PK_RSA) { result = _gnutls_x509_write_rsa_params (key->params, key->params_size, &der); if (result < 0) { gnutls_assert (); goto cleanup; } } else if (key->pk_algorithm == GNUTLS_PK_DSA) { result = _gnutls_x509_write_dsa_public_key (key->params, key->params_size, &der); if (result < 0) { gnutls_assert (); goto cleanup; } } else return GNUTLS_E_INTERNAL_ERROR; hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (hd == GNUTLS_HASH_FAILED) { gnutls_assert (); result = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } _gnutls_hash (hd, der.data, der.size); _gnutls_hash_deinit (hd, output_data); *output_data_size = 20; result = 0; cleanup: _gnutls_free_datum (&der); return result; }
/* ID should be: * 3 for MAC * 2 for IV * 1 for encryption key * * Note that this function produces different key for the * NULL password, and for the password with zero length. */ int _gnutls_pkcs12_string_to_key(const mac_entry_st * me, unsigned int id, const uint8_t * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, uint8_t * keybuf) { int rc; unsigned int i, j; digest_hd_st md; bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN * 2 + 64], *p; uint8_t d[64]; size_t cur_keylen; size_t n, m, p_size, i_size; unsigned mac_len; const uint8_t buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; cur_keylen = 0; if (pw == NULL) pwlen = 0; else pwlen = strlen(pw); if (pwlen > MAX_PASS_LEN) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if ((rc = _pkcs12_check_pass(pw, pwlen)) < 0) { gnutls_assert(); return rc; } rc = _gnutls_mpi_init_scan(&mpi512, buf_512, sizeof(buf_512)); if (rc < 0) { gnutls_assert(); return rc; } /* Store salt and password in BUF_I */ p_size = ((pwlen / 64) * 64) + 64; if (p_size > sizeof(buf_i) - 64) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); p = buf_i; for (i = 0; i < 64; i++) *p++ = salt[i % salt_size]; if (pw) { for (i = j = 0; i < p_size; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing (0) */ j = 0; } } else memset(p, 0, p_size); i_size = 64 + p_size; mac_len = _gnutls_mac_get_algo_len(me); for (;;) { rc = _gnutls_hash_init(&md, me); if (rc < 0) { gnutls_assert(); goto cleanup; } memset(d, id & 0xff, 64); _gnutls_hash(&md, d, 64); _gnutls_hash(&md, buf_i, pw ? i_size : 64); _gnutls_hash_deinit(&md, hash); for (i = 1; i < iter; i++) { rc = _gnutls_hash_fast(me->id, hash, mac_len, hash); if (rc < 0) { gnutls_assert(); goto cleanup; } } for (i = 0; i < mac_len && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { rc = 0; /* ready */ goto cleanup; } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % mac_len]; n = 64; rc = _gnutls_mpi_init_scan(&num_b1, buf_b, n); if (rc < 0) { gnutls_assert(); goto cleanup; } rc = _gnutls_mpi_add_ui(num_b1, num_b1, 1); if (rc < 0) { gnutls_assert(); goto cleanup; } for (i = 0; i < 128; i += 64) { n = 64; rc = _gnutls_mpi_init_scan(&num_ij, buf_i + i, n); if (rc < 0) { gnutls_assert(); goto cleanup; } rc = _gnutls_mpi_addm(num_ij, num_ij, num_b1, mpi512); if (rc < 0) { gnutls_assert(); goto cleanup; } n = 64; #ifndef PKCS12_BROKEN_KEYGEN m = (_gnutls_mpi_get_nbits(num_ij) + 7) / 8; #else m = n; #endif memset(buf_i + i, 0, n - m); rc = _gnutls_mpi_print(num_ij, buf_i + i + n - m, &n); if (rc < 0) { gnutls_assert(); goto cleanup; } _gnutls_mpi_release(&num_ij); } } cleanup: _gnutls_mpi_release(&num_ij); _gnutls_mpi_release(&num_b1); _gnutls_mpi_release(&mpi512); return rc; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_tls_sign_params (gnutls_session_t session, gnutls_cert * cert, gnutls_privkey * pkey, gnutls_datum_t * params, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; opaque concat[36]; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_sha, params->data, params->size); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: if (ver < GNUTLS_TLS1_2) { digest_hd_st td_md5; ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&td_md5, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash (&td_md5, params->data, params->size); _gnutls_hash_deinit (&td_md5, concat); _gnutls_hash_deinit (&td_sha, &concat[16]); dconcat.size = 36; } else { #if 1 /* Use NULL parameters. */ memcpy (concat, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", 15); _gnutls_hash_deinit (&td_sha, &concat[15]); dconcat.size = 35; #else /* No parameters field. */ memcpy (concat, "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13); _gnutls_hash_deinit (&td_sha, &concat[13]); dconcat.size = 33; #endif } dconcat.data = concat; break; case GNUTLS_PK_DSA: _gnutls_hash_deinit (&td_sha, concat); dconcat.data = concat; dconcat.size = 20; break; default: gnutls_assert (); _gnutls_hash_deinit (&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert (); } return ret; }
/* if hash==MD5 then we do RSA-MD5 * if hash==SHA then we do RSA-SHA * params[0] is modulus * params[1] is public key */ static int _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, const gnutls_datum_t * prehash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN; int ret; opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp; int digest_size; digest_hd_st hd; gnutls_datum_t decrypted; ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1); if (ret < 0) { gnutls_assert (); return ret; } /* decrypted is a BER encoded data of type DigestInfo */ digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); return ret; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (hash)) { gnutls_assert (); return GNUTLS_E_ASN1_GENERIC_ERROR; } if (prehash && prehash->data && prehash->size == digest_size) { cmp = prehash->data; } else { if (!text) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_hash_init (&hd, hash); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, md); cmp = md; } if (memcmp (cmp, digest, digest_size) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } return 0; }
/* ID should be: * 3 for MAC * 2 for IV * 1 for encryption key */ int _gnutls_pkcs12_string_to_key (unsigned int id, const opaque * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, opaque * keybuf) { int rc; unsigned int i, j; digest_hd_st md; bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; opaque hash[20], buf_b[64], buf_i[128], *p; size_t cur_keylen; size_t n; const opaque buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; cur_keylen = 0; if (pw == NULL) pwlen = 0; else pwlen = strlen (pw); if (pwlen > 63 / 2) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0) { gnutls_assert (); return rc; } rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512)); if (rc < 0) { gnutls_assert (); return rc; } /* Store salt and password in BUF_I */ p = buf_i; for (i = 0; i < 64; i++) *p++ = salt[i % salt_size]; if (pw) { for (i = j = 0; i < 64; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing zero */ j = 0; } } else memset (p, 0, 64); for (;;) { rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1); if (rc < 0) { gnutls_assert (); goto cleanup; } for (i = 0; i < 64; i++) { unsigned char lid = id & 0xFF; _gnutls_hash (&md, &lid, 1); } _gnutls_hash (&md, buf_i, pw ? 128 : 64); _gnutls_hash_deinit (&md, hash); for (i = 1; i < iter; i++) { rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_hash (&md, hash, 20); _gnutls_hash_deinit (&md, hash); } for (i = 0; i < 20 && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { rc = 0; /* ready */ goto cleanup; } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % 20]; n = 64; rc = _gnutls_mpi_scan (&num_b1, buf_b, n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_add_ui (num_b1, num_b1, 1); for (i = 0; i < 128; i += 64) { n = 64; rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512); n = 64; rc = _gnutls_mpi_print (num_ij, buf_i + i, &n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_release (&num_ij); } } cleanup: _gnutls_mpi_release (&num_ij); _gnutls_mpi_release (&num_b1); _gnutls_mpi_release (&mpi512); return rc; }
/* Verifies a TLS signature (like the one in the client certificate * verify message). */ int _gnutls_verify_sig_hdata (gnutls_session_t session, gnutls_cert * cert, gnutls_datum_t * signature) { int ret; opaque concat[36]; digest_hd_st td_md5; digest_hd_st td_sha; gnutls_datum_t dconcat; gnutls_protocol_t ver = gnutls_protocol_get_version (session); ret = _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha); if (ret < 0) { gnutls_assert (); _gnutls_hash_deinit (&td_md5, NULL); return GNUTLS_E_HASH_FAILED; } if (ver == GNUTLS_SSL3) { ret = _gnutls_generate_master (session, 1); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat, session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16], session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); } else { _gnutls_hash_deinit (&td_md5, concat); _gnutls_hash_deinit (&td_sha, &concat[16]); } dconcat.data = concat; dconcat.size = 20 + 16; /* md5+ sha */ ret = _gnutls_verify_sig (cert, &dconcat, signature, 16); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
static cdk_error_t file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output) { cdk_stream_t inp = NULL, out = NULL, tmp = NULL; digest_hd_st md; char buf[512], chk[512]; const char *s; int i, is_signed = 0, nbytes; int digest_algo = 0; int err; cdk_error_t rc; memset(&md, 0, sizeof(md)); if (output) { rc = cdk_stream_create (output, &out); if (rc) return rc; } rc = cdk_stream_open (file, &inp); if (rc) { if (output) cdk_stream_close (out); return rc; } s = "-----BEGIN PGP SIGNED MESSAGE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) { is_signed = 1; break; } } if (cdk_stream_eof (inp) && !is_signed) { rc = CDK_Armor_Error; goto leave; } while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes == 1) /* Empty line */ break; else if (!strncmp (buf, "Hash: ", 6)) { for (i = 0; digest_table[i].name; i++) { if (!strcmp (buf + 6, digest_table[i].name)) { digest_algo = digest_table[i].algo; break; } } } } if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0) { rc = CDK_Inv_Algo; goto leave; } if (!digest_algo) digest_algo = GNUTLS_DIG_MD5; err = _gnutls_hash_init (&md, digest_algo); if (err < 0) { rc = map_gnutls_error (err); goto leave; } s = "-----BEGIN PGP SIGNATURE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) break; else { cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1); i = strncmp (chk, s, strlen (s)); if (strlen (buf) == 0 && i == 0) continue; /* skip last '\n' */ _cdk_trim_string (buf, i == 0 ? 0 : 1); _gnutls_hash (&md, buf, strlen (buf)); } if (!strncmp (buf, "- ", 2)) /* FIXME: handle it recursive. */ memmove (buf, buf + 2, nbytes - 2); if (out) { if (strstr (buf, "\r\n")) buf[strlen (buf) - 2] = '\0'; cdk_stream_write (out, buf, strlen (buf)); _cdk_stream_puts (out, _cdk_armor_get_lineend ()); } } /* We create a temporary stream object to store the signature data in there. */ rc = cdk_stream_tmp_new (&tmp); if (rc) goto leave; s = "-----BEGIN PGP SIGNATURE-----\n"; _cdk_stream_puts (tmp, s); while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes < (int) (DIM (buf) - 3)) { buf[nbytes - 1] = '\n'; buf[nbytes] = '\0'; } cdk_stream_write (tmp, buf, nbytes); } /* FIXME: This code is not very elegant. */ cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ); cdk_stream_seek (tmp, 0); cdk_stream_set_armor_flag (tmp, 0); cdk_stream_read (tmp, NULL, 0); /* the digest handle will be closed there. */ rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md); leave: _gnutls_hash_deinit (&md, NULL); cdk_stream_close (out); cdk_stream_close (tmp); cdk_stream_close (inp); return rc; }