int pk_hash_data(gnutls_pk_algorithm_t pk, const mac_entry_st * hash, gnutls_pk_params_st * params, const gnutls_datum_t * data, gnutls_datum_t * digest) { int ret; digest->size = _gnutls_hash_get_algo_len(hash); digest->data = gnutls_malloc(digest->size); if (digest->data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)hash->id, data->data, data->size, digest->data); if (ret < 0) { gnutls_assert(); goto cleanup; } return 0; cleanup: gnutls_free(digest->data); return ret; }
/** * gnutls_fingerprint: * @algo: is a digest algorithm * @data: is the data * @result: is the place where the result will be copied (may be null). * @result_size: should hold the size of the result. The actual size * of the returned result will also be copied there. * * This function will calculate a fingerprint (actually a hash), of * the given data. The result is not printable data. You should * convert it to hex, or to something else printable. * * This is the usual way to calculate a fingerprint of an X.509 DER * encoded certificate. Note however that the fingerprint of an * OpenPGP certificate is not just a hash and cannot be calculated with this * function. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_fingerprint(gnutls_digest_algorithm_t algo, const gnutls_datum_t * data, void *result, size_t * result_size) { int ret; int hash_len = _gnutls_hash_get_algo_len(hash_to_entry(algo)); if (hash_len < 0 || (unsigned) hash_len > *result_size || result == NULL) { *result_size = hash_len; return GNUTLS_E_SHORT_MEMORY_BUFFER; } *result_size = hash_len; if (result) { ret = _gnutls_hash_fast(algo, data->data, data->size, result); if (ret < 0) return gnutls_assert_val(ret); } return 0; }
unsigned char * RIPEMD160 (const unsigned char *buf, unsigned long len, unsigned char *md) { if (!md) return NULL; _gnutls_hash_fast (GNUTLS_DIG_RMD160, buf, len, md); return md; }
unsigned char * MD5 (const unsigned char *buf, unsigned long len, unsigned char *md) { if (!md) return NULL; _gnutls_hash_fast (GNUTLS_DIG_MD5, buf, len, md); return md; }
/* This calculates the SHA1(A | B) * A and B will be left-padded with zeros to fill n_size. */ bigint_t _gnutls_calc_srp_u(bigint_t A, bigint_t B, bigint_t n) { size_t b_size, a_size; uint8_t *holder, hd[MAX_HASH_SIZE]; size_t holder_size, hash_size, n_size; int ret; bigint_t res; /* get the size of n in bytes */ _gnutls_mpi_print(n, NULL, &n_size); _gnutls_mpi_print(A, NULL, &a_size); _gnutls_mpi_print(B, NULL, &b_size); 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(A, &holder[n_size - a_size], &a_size); _gnutls_mpi_print(B, &holder[n_size + n_size - b_size], &b_size); ret = _gnutls_hash_fast(GNUTLS_DIG_SHA1, holder, holder_size, hd); if (ret < 0) { gnutls_free(holder); gnutls_assert(); return NULL; } /* convert the bytes of hd to integer */ hash_size = 20; /* SHA */ ret = _gnutls_mpi_init_scan_nz(&res, hd, hash_size); gnutls_free(holder); if (ret < 0) { gnutls_assert(); return NULL; } return res; }
/* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2 */ static int _gnutls_handshake_sign_crt_vrfy12(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]; gnutls_sign_algorithm_t sign_algo; const mac_entry_st *me; 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_client(session, sign_algo); me = hash_to_entry(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(me)); ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id, session->internals.handshake_hash_buffer. data, session->internals.handshake_hash_buffer. length, concat); if (ret < 0) return gnutls_assert_val(ret); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(me); ret = sign_tls_hash(session, me, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); return ret; } return sign_algo; }
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2 */ static int _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_datum_t * signature, gnutls_sign_algorithm_t sign_algo) { int ret; uint8_t concat[MAX_HASH_SIZE]; gnutls_datum_t dconcat; const version_entry_st *ver = get_version(session); gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); const mac_entry_st *me; ret = _gnutls_session_sign_algo_enabled(session, sign_algo); if (ret < 0) return gnutls_assert_val(ret); gnutls_sign_algorithm_set_client(session, sign_algo); me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo)); ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id, session->internals.handshake_hash_buffer. data, session->internals. handshake_hash_buffer_prev_len, concat); if (ret < 0) return gnutls_assert_val(ret); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(me); ret = verify_tls_hash(session, ver, cert, &dconcat, signature, 0, sign_algo, pk); if (ret < 0) { gnutls_assert(); return ret; } return ret; }
int pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash, bigint_t * params, const gnutls_datum_t * data, gnutls_datum_t * digest) { int ret; switch (pk) { case GNUTLS_PK_RSA: break; case GNUTLS_PK_DSA: if (params && hash != _gnutls_dsa_q_to_hash (params[1])) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } break; default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } digest->size = _gnutls_hash_get_algo_len (hash); digest->data = gnutls_malloc (digest->size); if (digest->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data); if (ret < 0) { gnutls_assert (); goto cleanup; } return 0; cleanup: gnutls_free (digest->data); return ret; }
/* 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; }
static int parse_commitment_line(char* line, const char* host, size_t host_len, const char* service, size_t service_len, time_t now, const gnutls_datum_t *skey) { char* p, *kp; char* savep = NULL; size_t kp_len, phash_size; time_t expiration; int ret; gnutls_digest_algorithm_t hash_algo; uint8_t phash[MAX_HASH_SIZE]; uint8_t hphash[MAX_HASH_SIZE*2+1]; /* read host */ p = strtok_r(line, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); if (p[0] != '*' && strcmp(p, host) != 0) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read service */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); if (p[0] != '*' && strcmp(p, service) != 0) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read expiration */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); expiration = (time_t)atol(p); if (expiration > 0 && now > expiration) return gnutls_assert_val(GNUTLS_E_EXPIRED); /* read hash algorithm */ p = strtok_r(NULL, "|", &savep); if (p == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); hash_algo = (time_t)atol(p); if (_gnutls_digest_get_name(hash_algo) == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); /* read hash */ kp = strtok_r(NULL, "|", &savep); if (kp == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); p = strpbrk(kp, "\n \r\t|"); if (p != NULL) *p = 0; /* hash and hex encode */ ret = _gnutls_hash_fast (hash_algo, skey->data, skey->size, phash); if (ret < 0) return gnutls_assert_val(ret); phash_size = _gnutls_hash_get_algo_len(hash_algo); p = _gnutls_bin2hex (phash, phash_size,(void*) hphash, sizeof(hphash), NULL); if (p == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); kp_len = strlen(kp); if (kp_len != phash_size*2) return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH); if (memcmp(kp, hphash, kp_len) != 0) return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH); /* key found and matches */ return 0; }