static char * _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock, unsigned int sigblock_len, uint8_t* key, unsigned int keylen) { uint16_t exp_len = 0; size_t exp_offset = 0, mod_offset = 0; struct rsa_public_key pubkey; mpz_t signature; int res = 0; /* RSA pubkey parsing as per RFC 3110 sec. 2 */ if( keylen <= 1) { return "null RSA key"; } if (key[0] != 0) { /* 1-byte length */ exp_len = key[0]; exp_offset = 1; } else { /* 1-byte NUL + 2-bytes exponent length */ if (keylen < 3) { return "incorrect RSA key length"; } exp_len = READ_UINT16(key+1); if (exp_len == 0) return "null RSA exponent length"; exp_offset = 3; } /* Check that we are not over-running input length */ if (keylen < exp_offset + exp_len + 1) { return "RSA key content shorter than expected"; } mod_offset = exp_offset + exp_len; nettle_rsa_public_key_init(&pubkey); pubkey.size = keylen - mod_offset; nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]); nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]); /* Digest content of "buf" and verify its RSA signature in "sigblock"*/ nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock); switch (digest_size) { case SHA1_DIGEST_SIZE: { uint8_t digest[SHA1_DIGEST_SIZE]; res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); res &= rsa_sha1_verify_digest(&pubkey, digest, signature); break; } case SHA256_DIGEST_SIZE: { uint8_t digest[SHA256_DIGEST_SIZE]; res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); res &= rsa_sha256_verify_digest(&pubkey, digest, signature); break; } case SHA512_DIGEST_SIZE: { uint8_t digest[SHA512_DIGEST_SIZE]; res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); res &= rsa_sha512_verify_digest(&pubkey, digest, signature); break; } default: break; } /* Clear and return */ nettle_rsa_public_key_clear(&pubkey); mpz_clear(signature); if (!res) { return "RSA signature verification failed"; } else { return NULL; } }
int _dsa_validate_dss_pq(struct dsa_params *pub, struct dss_params_validation_seeds *cert) { int ret; unsigned p_bits, q_bits; struct dsa_params pub2; struct dss_params_validation_seeds cert2; mpz_t r, s; p_bits = mpz_sizeinbase(pub->p, 2); q_bits = mpz_sizeinbase(pub->q, 2); ret = _dsa_check_qp_sizes(q_bits, p_bits, 0); if (ret == 0) { return 0; } mpz_init(r); mpz_init(s); dsa_params_init(&pub2); nettle_mpz_set_str_256_u(s, cert->seed_length, cert->seed); /* firstseed < 2^(N-1) */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, q_bits - 1); if (mpz_cmp(s, r) < 0) { goto fail; } /* 2^N <= q */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, q_bits); if (mpz_cmp(r, pub->q) <= 0) { goto fail; } /* 2^L <= p */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, p_bits); if (mpz_cmp(r, pub->p) <= 0) { goto fail; } /* p-1 mod q != 0 */ mpz_set(r, pub->p); mpz_sub_ui(r, r, 1); mpz_mod(r, r, pub->q); if (mpz_cmp_ui(r, 0) != 0) { goto fail; } /* replay the construction */ ret = _dsa_generate_dss_pq(&pub2, &cert2, cert->seed_length, cert->seed, NULL, NULL, p_bits, q_bits); if (ret == 0) { goto fail; } if ((cert->pseed_length > 0 && cert->pseed_length != cert2.pseed_length) || (cert->qseed_length > 0 && cert->qseed_length != cert2.qseed_length) || (cert->pgen_counter > 0 && cert->pgen_counter != cert2.pgen_counter) || (cert->qgen_counter > 0 && cert->qgen_counter != cert2.qgen_counter) || (cert->qseed_length > 0 && memcmp(cert->qseed, cert2.qseed, cert2.qseed_length) != 0) || (cert->pseed_length > 0 && memcmp(cert->pseed, cert2.pseed, cert2.pseed_length) != 0)) { goto fail; } if (mpz_cmp(pub->q, pub2.q) != 0) { goto fail; } if (mpz_cmp(pub->p, pub2.p) != 0) { goto fail; } if (mpz_sizeinbase(s, 2) < q_bits - 1) { goto fail; } ret = 1; goto finish; fail: ret = 0; finish: dsa_params_clear(&pub2); mpz_clear(r); mpz_clear(s); return ret; }
static char * _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock, unsigned int sigblock_len, unsigned char* key, unsigned int keylen) { uint8_t digest[SHA1_DIGEST_SIZE]; uint8_t key_t; int res = 0; size_t offset; struct dsa_public_key pubkey; struct dsa_signature signature; unsigned int expected_len; /* Extract DSA signature from the record */ nettle_dsa_signature_init(&signature); /* Signature length: 41 bytes - RFC 2536 sec. 3 */ if(sigblock_len == 41) { if(key[0] != sigblock[0]) return "invalid T value in DSA signature or pubkey"; nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1); nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20); } else { /* DER encoded, decode the ASN1 notated R and S bignums */ /* SEQUENCE { r INTEGER, s INTEGER } */ struct asn1_der_iterator i, seq; if(asn1_der_iterator_first(&i, sigblock_len, (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED || i.type != ASN1_SEQUENCE) return "malformed DER encoded DSA signature"; /* decode this element of i using the seq iterator */ if(asn1_der_decode_constructed(&i, &seq) != ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) return "malformed DER encoded DSA signature"; if(!asn1_der_get_bignum(&seq, signature.r, 20*8)) return "malformed DER encoded DSA signature"; if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) return "malformed DER encoded DSA signature"; if(!asn1_der_get_bignum(&seq, signature.s, 20*8)) return "malformed DER encoded DSA signature"; if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) return "malformed DER encoded DSA signature"; } /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */ key_t = key[0]; if (key_t > 8) { return "invalid T value in DSA pubkey"; } /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */ if (keylen < 21) { return "DSA pubkey too short"; } expected_len = 1 + /* T */ 20 + /* Q */ (64 + key_t*8) + /* P */ (64 + key_t*8) + /* G */ (64 + key_t*8); /* Y */ if (keylen != expected_len ) { return "invalid DSA pubkey length"; } /* Extract DSA pubkey from the record */ nettle_dsa_public_key_init(&pubkey); offset = 1; nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset); offset += 20; nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset); offset += (64 + key_t*8); nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset); offset += (64 + key_t*8); nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset); /* Digest content of "buf" and verify its DSA signature in "sigblock"*/ res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); res &= dsa_sha1_verify_digest(&pubkey, digest, &signature); /* Clear and return */ nettle_dsa_signature_clear(&signature); nettle_dsa_public_key_clear(&pubkey); if (!res) return "DSA signature verification failed"; else return NULL; }
static void dsa_nist_gen(mpz_t p, mpz_t q, void *random_ctx, nettle_random_func random, void *progress_ctx, nettle_progress_func progress, unsigned L) { unsigned n; unsigned b; mpz_t s; mpz_t t; mpz_t c; /* For NIS keysizes, we should have L = 512 + 64 * l */ n = (L-1) / 160; b = (L-1) % 160; mpz_init(s); mpz_init(t); mpz_init(c); for (;;) { { /* Generate q */ uint8_t h1[SHA1_DIGEST_SIZE]; uint8_t h2[SHA1_DIGEST_SIZE]; if (progress) progress(progress_ctx, '.'); nettle_mpz_random_size(s, random_ctx, random, SEED_BITS); hash(s, h1); mpz_set(t, s); mpz_add_ui(t, t, 1); hash(t, h2); memxor(h1, h2, SHA1_DIGEST_SIZE); h1[0] |= 0x80; h1[SHA1_DIGEST_SIZE - 1] |= 1; nettle_mpz_set_str_256_u(q, SHA1_DIGEST_SIZE, h1); /* The spec says that we should use 18 iterations of * miller-rabin. For performance, we want to do some trial * divisions first. The curent version of mpz_probab_prime_p * does exactly that. */ if (!mpz_probab_prime_p(q, 18)) /* Try new seed. */ continue; } /* q is a prime, with overwhelming probability. */ if (progress) progress(progress_ctx, '\n'); { /* Official maximum key size: L = 1024 => n = 6 */ TMP_DECL(buffer, uint8_t, (6 + 1) * SHA1_DIGEST_SIZE); unsigned size = (n+1) * SHA1_DIGEST_SIZE; unsigned i, j; TMP_ALLOC(buffer, size); for (i = 0, j = 2; i<4096; i++, j+= n+1) { unsigned k; if (progress) progress(progress_ctx, ','); for (k = 0; k<=n ; k++) { mpz_set(t, s); mpz_add_ui(t, t, j + k); hash(t, buffer + ( (n-k) * SHA1_DIGEST_SIZE)); } nettle_mpz_set_str_256_u(p, size, buffer); mpz_fdiv_r_2exp(p, p, L); mpz_setbit(p, L-1); mpz_set(t, q); mpz_mul_2exp(t, t, 1); mpz_fdiv_r(c, p, t); mpz_sub_ui(c, c, 1); mpz_sub(p, p, c); if (mpz_probab_prime_p(p, 5)) { /* Done! */ if (progress) progress(progress_ctx, '\n'); mpz_clear(s); mpz_clear(t); mpz_clear(c); return; } } if (progress) progress(progress_ctx, '+'); } } }