/* 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 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; }
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; }
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; }
/* 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; }
/* Hash all multi precision integers of the key PK with the given message digest context MD. */ static int hash_mpibuf (cdk_pubkey_t pk, digest_hd_st * md, int usefpr) { byte buf[MAX_MPI_BYTES]; /* FIXME: do not use hardcoded length. */ size_t nbytes; size_t i, npkey; int err; /* We have to differ between two modes for v3 keys. To form the fingerprint, we hash the MPI values without the length prefix. But if we calculate the hash for verifying/signing we use all data. */ npkey = cdk_pk_get_npkey (pk->pubkey_algo); for (i = 0; i < npkey; i++) { nbytes = MAX_MPI_BYTES; err = _gnutls_mpi_print_pgp (pk->mpi[i], buf, &nbytes); if (err < 0) return map_gnutls_error (err); if (!usefpr || pk->version == 4) _gnutls_hash (md, buf, nbytes); else /* without the prefix. */ _gnutls_hash (md, buf + 2, nbytes - 2); } return 0; }
int _gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e, void *key, int keylen) { uint8_t ipad[48]; int padsize, result; FAIL_IF_LIB_ERROR; padsize = get_padsize(e->id); if (padsize == 0) { gnutls_assert(); return GNUTLS_E_HASH_FAILED; } memset(ipad, 0x36, padsize); result = _gnutls_hash_init(ret, e); if (result < 0) { gnutls_assert(); return result; } ret->key = key; ret->keysize = keylen; if (keylen > 0) _gnutls_hash(ret, key, keylen); _gnutls_hash(ret, ipad, padsize); 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; }
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 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; }
/* 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; }
/* 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; }
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; }
static inline void mac_hash (digest_hd_st * td, void *data, int data_size, int ver) { if (ver == GNUTLS_SSL3) { /* SSL 3.0 */ _gnutls_hash (td, data, data_size); } else { _gnutls_hmac (td, data, data_size); } }
/* 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; }
static cdk_error_t hash_encode (void *data, FILE * in, FILE * out) { md_filter_t *mfx = data; byte buf[BUFSIZE]; int err; int nread; if (!mfx) { gnutls_assert (); return CDK_Inv_Value; } _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo); if (!mfx->md_initialized) { err = _gnutls_hash_init (&mfx->md, mfx->digest_algo); if (err < 0) { gnutls_assert (); return map_gnutls_error (err); } mfx->md_initialized = 1; } while (!feof (in)) { nread = fread (buf, 1, BUFSIZE, in); if (!nread) break; _gnutls_hash (&mfx->md, buf, nread); } wipemem (buf, sizeof (buf)); return 0; }
/* 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; }
void RIPEMD160_Update (RIPEMD160_CTX * ctx, const void *buf, int len) { _gnutls_hash (ctx->handle, buf, len); }
void MD5_Update (MD5_CTX * ctx, const void *buf, int len) { _gnutls_hash (ctx->handle, buf, len); }
/* 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; }
/** * 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 previous sent packets in the * handshake procedure. * 20040227: now it works for SSL 3.0 as well * 20091031: works for TLS 1.2 too! * * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success. * For TLS1.2 returns the signature algorithm used on success, or a negative error code; */ int _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; uint8_t concat[MAX_SIG_SIZE]; digest_hd_st td_md5; digest_hd_st td_sha; const version_entry_st *ver = get_version(session); gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL); if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); if (_gnutls_version_has_selectable_sighash(ver)) return _gnutls_handshake_sign_crt_vrfy12(session, cert, pkey, signature); ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length); if (ver->id == GNUTLS_SSL3) { ret = _gnutls_generate_master(session, 1); if (ret < 0) { gnutls_assert(); _gnutls_hash_deinit(&td_sha, NULL); return ret; } ret = _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16], session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); if (ret < 0) return gnutls_assert_val(ret); } else _gnutls_hash_deinit(&td_sha, &concat[16]); /* ensure 1024 bit DSA keys are used */ ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN); if (ret < 0) return gnutls_assert_val(ret); switch (pk) { case GNUTLS_PK_RSA: ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5)); if (ret < 0) return gnutls_assert_val(ret); _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer. length); if (ver->id == GNUTLS_SSL3) { ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat, session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); if (ret < 0) return gnutls_assert_val(ret); } else _gnutls_hash_deinit(&td_md5, concat); dconcat.data = concat; dconcat.size = 36; break; case GNUTLS_PK_DSA: case GNUTLS_PK_EC: dconcat.data = &concat[16]; dconcat.size = 20; break; default: return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); } ret = sign_tls_hash(session, NULL, 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; }
static cdk_error_t literal_decode (void *data, FILE * in, FILE * out) { literal_filter_t *pfx = data; cdk_stream_t si, so; cdk_packet_t pkt; cdk_pkt_literal_t pt; byte buf[BUFSIZE]; ssize_t nread; int bufsize; cdk_error_t rc; _cdk_log_debug ("literal filter: decode\n"); if (!pfx || !in || !out) return CDK_Inv_Value; rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); if (rc) return rc; cdk_pkt_new (&pkt); rc = cdk_pkt_read (si, pkt); if (rc || pkt->pkttype != CDK_PKT_LITERAL) { cdk_pkt_release (pkt); cdk_stream_close (si); return !rc ? CDK_Inv_Packet : rc; } rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so); if (rc) { cdk_pkt_release (pkt); cdk_stream_close (si); return rc; } pt = pkt->pkt.literal; pfx->mode = pt->mode; if (pfx->filename && pt->namelen > 0) { /* The name in the literal packet is more authorative. */ cdk_free (pfx->filename); pfx->filename = dup_trim_filename (pt->name); } else if (!pfx->filename && pt->namelen > 0) pfx->filename = dup_trim_filename (pt->name); else if (!pt->namelen && !pfx->filename && pfx->orig_filename) { /* In this case, we need to derrive the output file name from the original name and cut off the OpenPGP extension. If this is not possible, we return an error. */ if (!stristr (pfx->orig_filename, ".gpg") && !stristr (pfx->orig_filename, ".pgp") && !stristr (pfx->orig_filename, ".asc")) { cdk_pkt_release (pkt); cdk_stream_close (si); cdk_stream_close (so); _cdk_log_debug ("literal filter: no file name and no PGP extension\n"); return CDK_Inv_Mode; } _cdk_log_debug ("literal filter: derrive file name from original\n"); pfx->filename = dup_trim_filename (pfx->orig_filename); pfx->filename[strlen (pfx->filename) - 4] = '\0'; } while (!feof (in)) { _cdk_log_debug ("literal_decode: part on %d size %lu\n", (int) pfx->blkmode.on, (unsigned long)pfx->blkmode.size); if (pfx->blkmode.on) bufsize = pfx->blkmode.size; else bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf); nread = cdk_stream_read (pt->buf, buf, bufsize); if (nread == EOF) { rc = CDK_File_Error; break; } if (pfx->md_initialized) _gnutls_hash (&pfx->md, buf, nread); cdk_stream_write (so, buf, nread); pt->len -= nread; if (pfx->blkmode.on) { pfx->blkmode.size = _cdk_pkt_read_len (in, &pfx->blkmode.on); if ((ssize_t) pfx->blkmode.size == EOF) return CDK_Inv_Packet; } if (pt->len <= 0 && !pfx->blkmode.on) break; } cdk_stream_close (si); cdk_stream_close (so); cdk_pkt_release (pkt); return rc; }
/* 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; }
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; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_handshake_sign_data(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * params, gnutls_datum_t * signature, gnutls_sign_algorithm_t * sign_algo) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; uint8_t concat[MAX_SIG_SIZE]; const version_entry_st *ver = get_version(session); const mac_entry_st *hash_algo; *sign_algo = _gnutls_session_get_sign_algo(session, cert); if (*sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert(); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } gnutls_sign_algorithm_set_server(session, *sign_algo); hash_algo = hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo)); if (hash_algo == NULL) return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n", session, gnutls_sign_algorithm_get_name(*sign_algo)); ret = _gnutls_hash_init(&td_sha, hash_algo); 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 (gnutls_privkey_get_pk_algorithm(pkey, NULL)) { case GNUTLS_PK_RSA: if (!_gnutls_version_has_selectable_sighash(ver)) { digest_hd_st td_md5; ret = _gnutls_hash_init(&td_md5, hash_to_entry (GNUTLS_DIG_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.data = concat; dconcat.size = 36; } else { /* TLS 1.2 way */ _gnutls_hash_deinit(&td_sha, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); } break; case GNUTLS_PK_DSA: case GNUTLS_PK_EC: _gnutls_hash_deinit(&td_sha, concat); if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); break; default: gnutls_assert(); _gnutls_hash_deinit(&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = sign_tls_hash(session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); } return ret; }