/* This will return the appropriate hash to verify the given signature. * If signature is NULL it will return an (or the) appropriate hash for * the given parameters. */ int _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash, const gnutls_datum_t * signature, gnutls_pk_algorithm pk, bigint_t * issuer_params, unsigned int issuer_params_size) { opaque digest[MAX_HASH_SIZE]; gnutls_datum_t decrypted; int digest_size; int ret; switch (pk) { case GNUTLS_PK_DSA: if (hash) *hash = _gnutls_dsa_q_to_hash (issuer_params[1], NULL); ret = 0; break; case GNUTLS_PK_RSA: if (signature == NULL) { /* return a sensible algorithm */ if (hash) *hash = GNUTLS_DIG_SHA256; return 0; } ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, issuer_params, issuer_params_size, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); goto cleanup; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (*hash)) { gnutls_assert (); ret = GNUTLS_E_ASN1_GENERIC_ERROR; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: 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; }
/* Given a signature and parameters, it should return * the hash algorithm used in the signature. This is a kludge * but until we deprecate gnutls_pubkey_get_verify_algorithm() * we depend on it. */ static int wrap_nettle_hash_algorithm (gnutls_pk_algorithm_t pk, const gnutls_datum_t * sig, gnutls_pk_params_st * issuer_params, gnutls_digest_algorithm_t* hash_algo) { uint8_t digest[MAX_HASH_SIZE]; uint8_t digest_info[MAX_HASH_SIZE*3]; gnutls_datum_t di; unsigned digest_size; mpz_t s; struct rsa_public_key pub; int ret; mpz_init(s); switch (pk) { case GNUTLS_PK_DSA: case GNUTLS_PK_EC: if (hash_algo) *hash_algo = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL); ret = 0; break; case GNUTLS_PK_RSA: if (sig == NULL) { /* return a sensible algorithm */ if (hash_algo) *hash_algo = GNUTLS_DIG_SHA256; return 0; } _rsa_params_to_pubkey (issuer_params, &pub); digest_size = sizeof(digest); nettle_mpz_set_str_256_u(s, sig->size, sig->data); digest_size = sizeof (digest_info); ret = extract_digest_info( &pub, &digest_size, digest_info, s); if (ret == 0) { ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; gnutls_assert (); goto cleanup; } di.data = digest_info; di.size = digest_size; digest_size = sizeof(digest); if ((ret = decode_ber_digest_info (&di, hash_algo, digest, &digest_size)) < 0) { gnutls_assert (); goto cleanup; } if (digest_size != _gnutls_hash_get_algo_len (*hash_algo)) { gnutls_assert (); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: mpz_clear(s); return ret; }
static int cng_sign(gnutls_privkey_t key, void *userdata, const gnutls_datum_t * raw_data, gnutls_datum_t * signature) { priv_st *priv = userdata; BCRYPT_PKCS1_PADDING_INFO _info; void *info = NULL; DWORD ret_sig = 0; int ret; DWORD flags = 0; gnutls_datum_t data = { raw_data->data, raw_data->size }; uint8_t digest[MAX_HASH_SIZE]; unsigned int digest_size; gnutls_digest_algorithm_t algo; SECURITY_STATUS r; signature->data = NULL; signature->size = 0; if (priv->pk == GNUTLS_PK_RSA) { flags = BCRYPT_PAD_PKCS1; info = &_info; if (raw_data->size == 36) { /* TLS 1.0 MD5+SHA1 */ _info.pszAlgId = NULL; } else { digest_size = sizeof(digest); ret = decode_ber_digest_info(raw_data, &algo, digest, &digest_size); if (ret < 0) return gnutls_assert_val(ret); switch (algo) { case GNUTLS_DIG_SHA1: _info.pszAlgId = NCRYPT_SHA1_ALGORITHM; break; #ifdef NCRYPT_SHA224_ALGORITHM case GNUTLS_DIG_SHA224: _info.pszAlgId = NCRYPT_SHA224_ALGORITHM; break; #endif case GNUTLS_DIG_SHA256: _info.pszAlgId = NCRYPT_SHA256_ALGORITHM; break; case GNUTLS_DIG_SHA384: _info.pszAlgId = NCRYPT_SHA384_ALGORITHM; break; case GNUTLS_DIG_SHA512: _info.pszAlgId = NCRYPT_SHA512_ALGORITHM; break; default: return gnutls_assert_val (GNUTLS_E_UNKNOWN_HASH_ALGORITHM); } data.data = digest; data.size = digest_size; } } r = pNCryptSignHash(priv->nc, info, data.data, data.size, NULL, 0, &ret_sig, flags); if (FAILED(r)) { gnutls_assert(); _gnutls_debug_log("error in pre-signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; signature->data = gnutls_malloc(signature->size); if (signature->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); r = pNCryptSignHash(priv->nc, info, data.data, data.size, signature->data, signature->size, &ret_sig, flags); if (FAILED(r)) { gnutls_assert(); _gnutls_debug_log("error in signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; return 0; fail: gnutls_free(signature->data); return ret; }
static int capi_sign(gnutls_privkey_t key, void *userdata, const gnutls_datum_t * raw_data, gnutls_datum_t * signature) { priv_st *priv = (priv_st *) userdata; ALG_ID Algid; HCRYPTHASH hHash = NULL; uint8_t digest[MAX_HASH_SIZE]; unsigned int digest_size; gnutls_digest_algorithm_t algo; DWORD size1 = 0, sizesize = sizeof(DWORD); DWORD ret_sig = 0; int ret; signature->data = NULL; signature->size = 0; digest_size = raw_data->size; switch (digest_size) { case 16: Algid = CALG_MD5; break; //case 35: size=20; // DigestInfo SHA1 case 20: Algid = CALG_SHA1; break; //case 51: size=32; // DigestInto SHA-256 case 32: Algid = CALG_SHA_256; break; case 36: Algid = CALG_SSL3_SHAMD5; break; case 48: Algid = CALG_SHA_384; break; case 64: Algid = CALG_SHA_512; break; default: digest_size = sizeof(digest); ret = decode_ber_digest_info(raw_data, &algo, digest, &digest_size); if (ret < 0) return gnutls_assert_val(ret); switch (algo) { case GNUTLS_DIG_SHA1: Algid = CALG_SHA1; break; #ifdef NCRYPT_SHA224_ALGORITHM case GNUTLS_DIG_SHA224: Algid = CALG_SHA_224; break; #endif case GNUTLS_DIG_SHA256: Algid = CALG_SHA_256; break; case GNUTLS_DIG_SHA384: Algid = CALG_SHA_384; break; case GNUTLS_DIG_SHA512: Algid = CALG_SHA_512; break; default: return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); } } if (!CryptCreateHash(priv->hCryptProv, Algid, 0, 0, &hHash)) { gnutls_assert(); _gnutls_debug_log("error in create hash: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptSetHashParam(hHash, HP_HASHVAL, digest, 0)) { gnutls_assert(); _gnutls_debug_log("error in set hash val: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptGetHashParam (hHash, HP_HASHSIZE, (BYTE *) & size1, &sizesize, 0) || digest_size != size1) { gnutls_assert(); _gnutls_debug_log("error in hash size: %d\n", (int)size1); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptSignHash(hHash, priv->dwKeySpec, NULL, 0, NULL, &ret_sig)) { gnutls_assert(); _gnutls_debug_log("error in pre-signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; signature->data = (unsigned char *)gnutls_malloc(signature->size); if (signature->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); if (!CryptSignHash (hHash, priv->dwKeySpec, NULL, 0, signature->data, &ret_sig)) { gnutls_assert(); _gnutls_debug_log("error in signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } memrev(signature->data, signature->size); CryptDestroyHash(hHash); signature->size = ret_sig; return 0; fail: if (hHash != 0) CryptDestroyHash(hHash); gnutls_free(signature->data); return ret; }
int _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash, const gnutls_datum_t * signature, const gnutls_x509_crt_t issuer) { bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE]; opaque digest[MAX_HASH_SIZE]; gnutls_datum_t decrypted; int issuer_params_size; int digest_size; int ret, i; issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; ret = _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size); if (ret < 0) { gnutls_assert (); return ret; } switch (gnutls_x509_crt_get_pk_algorithm (issuer, NULL)) { case GNUTLS_PK_DSA: if (hash) *hash = _gnutls_dsa_q_to_hash (issuer_params[1]); ret = 0; break; case GNUTLS_PK_RSA: ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, issuer_params, issuer_params_size, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); goto cleanup; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (*hash)) { gnutls_assert (); ret = GNUTLS_E_ASN1_GENERIC_ERROR; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: /* release allocated mpis */ for (i = 0; i < issuer_params_size; i++) { _gnutls_mpi_release (&issuer_params[i]); } return ret; }