diff --git a/ChangeLog b/ChangeLog index 09fdbb020509c22ee4bb7fd792664857136d3710..55577db283c96d31960e6cbfc6c6ddc4d9d485bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2014-03-26 Niels Möller <nisse@lysator.liu.se> + * der2dsa.c (dsa_params_from_der_iterator): Converted to new DSA + interface. Allow q_size == 0, meaning any q < p is allowed. + Additional validity checks. + (dsa_public_key_from_der_iterator): Converted to new DSA + interface. Also check that the public value is in the correct + range. + (dsa_openssl_private_key_from_der_iterator): Converted + to new DSA interface. Additional validity checks. + (dsa_openssl_private_key_from_der): Converted to new DSA + interface. + * tools/pkcs1-conv.c (convert_dsa_private_key): Update to use + struct dsa_params, and adapt to the der decoding changes. + (convert_public_key): Likewise. + * examples/hogweed-benchmark.c: Update dsa benchmarking to use new DSA interface. diff --git a/der2dsa.c b/der2dsa.c index 9d439c3e8cff8966b4dca89138db7657374beb9e..ff6114e5428bcb00d65b27c71449b0bde9641b4d 100644 --- a/der2dsa.c +++ b/der2dsa.c @@ -6,6 +6,7 @@ /* nettle, low-level cryptographics library * * Copyright (C) 2005, 2009 Niels Möller, Magnus Holmgren + * Copyright (C) 2014 Niels Möller * * The nettle library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -38,9 +39,10 @@ && asn1_der_get_bignum((i), (x), (l)) \ && mpz_sgn((x)) > 0) +/* If q_bits > 0, q is required to be of exactly this size. */ int -dsa_params_from_der_iterator(struct dsa_public_key *pub, - unsigned p_max_bits, +dsa_params_from_der_iterator(struct dsa_params *params, + unsigned max_bits, unsigned q_bits, struct asn1_der_iterator *i) { /* Dss-Parms ::= SEQUENCE { @@ -49,30 +51,41 @@ dsa_params_from_der_iterator(struct dsa_public_key *pub, g INTEGER } */ - return (i->type == ASN1_INTEGER - && asn1_der_get_bignum(i, pub->p, p_max_bits) - && mpz_sgn(pub->p) > 0 - && GET(i, pub->q, DSA_SHA1_Q_BITS) - && GET(i, pub->g, p_max_bits) - && asn1_der_iterator_next(i) == ASN1_ITERATOR_END); + if (i->type == ASN1_INTEGER + && asn1_der_get_bignum(i, params->p, max_bits) + && mpz_sgn(params->p) > 0) + { + unsigned p_bits = mpz_sizeinbase (params->p, 2); + return (GET(i, params->q, q_bits ? q_bits : p_bits) + && (q_bits == 0 || mpz_sizeinbase(params->q, 2) == q_bits) + && mpz_cmp (params->q, params->p) < 0 + && GET(i, params->g, p_bits) + && mpz_cmp (params->g, params->p) < 0 + && asn1_der_iterator_next(i) == ASN1_ITERATOR_END); + } + else + return 0; } int -dsa_public_key_from_der_iterator(struct dsa_public_key *pub, - unsigned p_max_bits, +dsa_public_key_from_der_iterator(const struct dsa_params *params, + mpz_t pub, struct asn1_der_iterator *i) { /* DSAPublicKey ::= INTEGER */ return (i->type == ASN1_INTEGER - && asn1_der_get_bignum(i, pub->y, p_max_bits) - && mpz_sgn(pub->y) > 0); + && asn1_der_get_bignum(i, pub, + mpz_sizeinbase (params->p, 2)) + && mpz_sgn(pub) > 0 + && mpz_cmp(pub, params->p) < 0); } int -dsa_openssl_private_key_from_der_iterator(struct dsa_public_key *pub, - struct dsa_private_key *priv, +dsa_openssl_private_key_from_der_iterator(struct dsa_params *params, + mpz_t pub, + mpz_t priv, unsigned p_max_bits, struct asn1_der_iterator *i) { @@ -87,23 +100,31 @@ dsa_openssl_private_key_from_der_iterator(struct dsa_public_key *pub, */ uint32_t version; - - return (i->type == ASN1_SEQUENCE + + if (i->type == ASN1_SEQUENCE && asn1_der_decode_constructed_last(i) == ASN1_ITERATOR_PRIMITIVE && i->type == ASN1_INTEGER && asn1_der_get_uint32(i, &version) && version == 0 - && GET(i, pub->p, p_max_bits) - && GET(i, pub->q, DSA_SHA1_Q_BITS) - && GET(i, pub->g, p_max_bits) - && GET(i, pub->y, p_max_bits) - && GET(i, priv->x, DSA_SHA1_Q_BITS) - && asn1_der_iterator_next(i) == ASN1_ITERATOR_END); + && GET(i, params->p, p_max_bits)) + { + unsigned p_bits = mpz_sizeinbase (params->p, 2); + return (GET(i, params->q, DSA_SHA1_Q_BITS) + && GET(i, params->g, p_bits) + && mpz_cmp (params->g, params->p) < 0 + && GET(i, pub, p_bits) + && mpz_cmp (pub, params->p) < 0 + && GET(i, priv, DSA_SHA1_Q_BITS) + && asn1_der_iterator_next(i) == ASN1_ITERATOR_END); + } + else + return 0; } int -dsa_openssl_private_key_from_der(struct dsa_public_key *pub, - struct dsa_private_key *priv, +dsa_openssl_private_key_from_der(struct dsa_params *params, + mpz_t pub, + mpz_t priv, unsigned p_max_bits, size_t length, const uint8_t *data) { @@ -113,5 +134,6 @@ dsa_openssl_private_key_from_der(struct dsa_public_key *pub, res = asn1_der_iterator_first(&i, length, data); return (res == ASN1_ITERATOR_CONSTRUCTED - && dsa_openssl_private_key_from_der_iterator(pub, priv, p_max_bits, &i)); + && dsa_openssl_private_key_from_der_iterator(params, pub, priv, + p_max_bits, &i)); } diff --git a/dsa.h b/dsa.h index e66918ed95aecb5bc980648310eacfebaa06e6e3..33bd00b2a7dd9f59ff03208b0823c064bc4cb7fc 100644 --- a/dsa.h +++ b/dsa.h @@ -293,23 +293,26 @@ dsa_sha256_keypair_from_sexp(struct dsa_params *params, struct asn1_der_iterator; int -dsa_params_from_der_iterator(struct dsa_public_key *pub, - unsigned p_max_bits, - struct asn1_der_iterator *i); +dsa_params_from_der_iterator(struct dsa_params *params, + unsigned max_bits, unsigned q_bits, + struct asn1_der_iterator *i); + int -dsa_public_key_from_der_iterator(struct dsa_public_key *pub, - unsigned p_max_bits, +dsa_public_key_from_der_iterator(const struct dsa_params *params, + mpz_t pub, struct asn1_der_iterator *i); int -dsa_openssl_private_key_from_der_iterator(struct dsa_public_key *pub, - struct dsa_private_key *priv, +dsa_openssl_private_key_from_der_iterator(struct dsa_params *params, + mpz_t pub, + mpz_t priv, unsigned p_max_bits, struct asn1_der_iterator *i); int -dsa_openssl_private_key_from_der(struct dsa_public_key *pub, - struct dsa_private_key *priv, +dsa_openssl_private_key_from_der(struct dsa_params *params, + mpz_t pub, + mpz_t priv, unsigned p_max_bits, size_t length, const uint8_t *data); diff --git a/tools/pkcs1-conv.c b/tools/pkcs1-conv.c index 1c73a97cefc62bd47a0b259e1481d564deb010ad..811ddc203c3fbeb2fd7ce3e527f4af2191b84062 100644 --- a/tools/pkcs1-conv.c +++ b/tools/pkcs1-conv.c @@ -5,6 +5,7 @@ /* nettle, low-level cryptographics library * * Copyright (C) 2005, 2009 Niels Möller, Magnus Holmgren + * Copyright (C) 2014 Niels Möller * * The nettle library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -311,29 +312,30 @@ convert_rsa_private_key(struct nettle_buffer *buffer, size_t length, const uint8 static int convert_dsa_private_key(struct nettle_buffer *buffer, size_t length, const uint8_t *data) { - struct dsa_public_key pub; - struct dsa_private_key priv; + struct dsa_params params; + mpz_t pub; + mpz_t priv; int res; - - dsa_public_key_init(&pub); - dsa_private_key_init(&priv); - if (dsa_openssl_private_key_from_der(&pub, &priv, 0, + dsa_params_init (¶ms); + mpz_init (pub); + mpz_init (priv); + + if (dsa_openssl_private_key_from_der(¶ms, pub, priv, 0, length, data)) { /* Reuses the buffer */ nettle_buffer_reset(buffer); - res = dsa_keypair_to_sexp(buffer, NULL, - (const struct dsa_params *) &pub, - pub.y, priv.x); + res = dsa_keypair_to_sexp(buffer, NULL, ¶ms, pub, priv); } else { werror("Invalid OpenSSL private key.\n"); res = 0; } - dsa_public_key_clear(&pub); - dsa_private_key_clear(&priv); + dsa_params_clear (¶ms); + mpz_clear (pub); + mpz_clear (priv); return res; } @@ -407,19 +409,21 @@ convert_public_key(struct nettle_buffer *buffer, size_t length, const uint8_t *d if (asn1_der_iterator_next(&j) == ASN1_ITERATOR_CONSTRUCTED && asn1_der_decode_constructed_last(&j) == ASN1_ITERATOR_PRIMITIVE) { - struct dsa_public_key pub; + struct dsa_params params; + mpz_t pub; - dsa_public_key_init(&pub); + dsa_params_init (¶ms); + mpz_init (pub); - if (dsa_params_from_der_iterator(&pub, 0, &i) - && dsa_public_key_from_der_iterator(&pub, 0, &j)) + if (dsa_params_from_der_iterator(¶ms, 0, 0, &i) + && dsa_public_key_from_der_iterator(¶ms, pub, &j)) { nettle_buffer_reset(buffer); res = dsa_keypair_to_sexp(buffer, NULL, - (const struct dsa_params *) &pub, - pub.y, NULL) > 0; + ¶ms, pub, NULL) > 0; } - dsa_public_key_clear(&pub); + dsa_params_clear(¶ms); + mpz_clear(pub); } if (!res) werror("SubjectPublicKeyInfo: Invalid DSA key.\n");