diff options
Diffstat (limited to 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa')
4 files changed, 1622 insertions, 0 deletions
diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/CMakeLists.txt b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/CMakeLists.txt new file mode 100644 index 000000000..d3c12f58f --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(../../include) + +add_library( + dsa + + OBJECT + + dsa.c + dsa_asn1.c +) diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa.c new file mode 100644 index 000000000..e2b6695e8 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa.c @@ -0,0 +1,956 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch <schoch@sheba.arc.nasa.gov>. */ + +#include <openssl/dsa.h> + +#include <string.h> + +#include <openssl/bn.h> +#include <openssl/dh.h> +#include <openssl/digest.h> +#include <openssl/engine.h> +#include <openssl/err.h> +#include <openssl/ex_data.h> +#include <openssl/mem.h> +#include <openssl/rand.h> +#include <openssl/sha.h> +#include <openssl/thread.h> + +#include "../bn/internal.h" +#include "../internal.h" + + +#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 + +/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of + * Rabin-Miller */ +#define DSS_prime_checks 50 + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +DSA *DSA_new(void) { + DSA *dsa = OPENSSL_malloc(sizeof(DSA)); + if (dsa == NULL) { + OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + OPENSSL_memset(dsa, 0, sizeof(DSA)); + + dsa->references = 1; + + CRYPTO_MUTEX_init(&dsa->method_mont_lock); + CRYPTO_new_ex_data(&dsa->ex_data); + + return dsa; +} + +void DSA_free(DSA *dsa) { + if (dsa == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&dsa->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); + + BN_clear_free(dsa->p); + BN_clear_free(dsa->q); + BN_clear_free(dsa->g); + BN_clear_free(dsa->pub_key); + BN_clear_free(dsa->priv_key); + BN_clear_free(dsa->kinv); + BN_clear_free(dsa->r); + BN_MONT_CTX_free(dsa->method_mont_p); + BN_MONT_CTX_free(dsa->method_mont_q); + CRYPTO_MUTEX_cleanup(&dsa->method_mont_lock); + OPENSSL_free(dsa); +} + +int DSA_up_ref(DSA *dsa) { + CRYPTO_refcount_inc(&dsa->references); + return 1; +} + +void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key, + const BIGNUM **out_priv_key) { + if (out_pub_key != NULL) { + *out_pub_key = dsa->pub_key; + } + if (out_priv_key != NULL) { + *out_priv_key = dsa->priv_key; + } +} + +void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p, const BIGNUM **out_q, + const BIGNUM **out_g) { + if (out_p != NULL) { + *out_p = dsa->p; + } + if (out_q != NULL) { + *out_q = dsa->q; + } + if (out_g != NULL) { + *out_g = dsa->g; + } +} + +int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, + size_t seed_len, int *out_counter, + unsigned long *out_h, BN_GENCB *cb) { + int ok = 0; + unsigned char seed[SHA256_DIGEST_LENGTH]; + unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; + BIGNUM *r0, *W, *X, *c, *test; + BIGNUM *g = NULL, *q = NULL, *p = NULL; + BN_MONT_CTX *mont = NULL; + int k, n = 0, m = 0; + unsigned i; + int counter = 0; + int r = 0; + BN_CTX *ctx = NULL; + unsigned int h = 2; + unsigned qsize; + const EVP_MD *evpmd; + + evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1(); + qsize = EVP_MD_size(evpmd); + + if (bits < 512) { + bits = 512; + } + + bits = (bits + 63) / 64 * 64; + + if (seed_in != NULL) { + if (seed_len < (size_t)qsize) { + return 0; + } + if (seed_len > (size_t)qsize) { + /* Only consume as much seed as is expected. */ + seed_len = qsize; + } + OPENSSL_memcpy(seed, seed_in, seed_len); + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + p = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + + if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) { + goto err; + } + + for (;;) { + /* Find q. */ + for (;;) { + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) { + goto err; + } + + int use_random_seed = (seed_in == NULL); + if (use_random_seed) { + if (!RAND_bytes(seed, qsize)) { + goto err; + } + } else { + /* If we come back through, use random seed next time. */ + seed_in = NULL; + } + OPENSSL_memcpy(buf, seed, qsize); + OPENSSL_memcpy(buf2, seed, qsize); + /* precompute "SEED + 1" for step 7: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + /* step 2 */ + if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) || + !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) { + goto err; + } + for (i = 0; i < qsize; i++) { + md[i] ^= buf2[i]; + } + + /* step 3 */ + md[0] |= 0x80; + md[qsize - 1] |= 0x01; + if (!BN_bin2bn(md, qsize, q)) { + goto err; + } + + /* step 4 */ + r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed, cb); + if (r > 0) { + break; + } + if (r != 0) { + goto err; + } + + /* do a callback call */ + /* step 5 */ + } + + if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) { + goto err; + } + + /* step 6 */ + counter = 0; + /* "offset = 2" */ + + n = (bits - 1) / 160; + + for (;;) { + if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) { + goto err; + } + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k = 0; k <= n; k++) { + /* obtain "SEED + offset + k" by incrementing: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) { + goto err; + } + + /* step 8 */ + if (!BN_bin2bn(md, qsize, r0) || + !BN_lshift(r0, r0, (qsize << 3) * k) || + !BN_add(W, W, r0)) { + goto err; + } + } + + /* more of step 8 */ + if (!BN_mask_bits(W, bits - 1) || + !BN_copy(X, W) || + !BN_add(X, X, test)) { + goto err; + } + + /* step 9 */ + if (!BN_lshift1(r0, q) || + !BN_mod(c, X, r0, ctx) || + !BN_sub(r0, c, BN_value_one()) || + !BN_sub(p, X, r0)) { + goto err; + } + + /* step 10 */ + if (BN_cmp(p, test) >= 0) { + /* step 11 */ + r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); + if (r > 0) { + goto end; /* found it */ + } + if (r != 0) { + goto err; + } + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= 4096) { + break; + } + } + } +end: + if (!BN_GENCB_call(cb, 2, 1)) { + goto err; + } + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + if (!BN_sub(test, p, BN_value_one()) || + !BN_div(r0, NULL, test, q, ctx)) { + goto err; + } + + if (!BN_set_word(test, h) || + !BN_MONT_CTX_set(mont, p, ctx)) { + goto err; + } + + for (;;) { + /* g=test^r0%p */ + if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) { + goto err; + } + if (!BN_is_one(g)) { + break; + } + if (!BN_add(test, test, BN_value_one())) { + goto err; + } + h++; + } + + if (!BN_GENCB_call(cb, 3, 1)) { + goto err; + } + + ok = 1; + +err: + if (ok) { + BN_free(dsa->p); + BN_free(dsa->q); + BN_free(dsa->g); + dsa->p = BN_dup(p); + dsa->q = BN_dup(q); + dsa->g = BN_dup(g); + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + ok = 0; + goto err; + } + if (out_counter != NULL) { + *out_counter = counter; + } + if (out_h != NULL) { + *out_h = h; + } + } + + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + BN_MONT_CTX_free(mont); + + return ok; +} + +DSA *DSAparams_dup(const DSA *dsa) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + ret->p = BN_dup(dsa->p); + ret->q = BN_dup(dsa->q); + ret->g = BN_dup(dsa->g); + if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_generate_key(DSA *dsa) { + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + priv_key = dsa->priv_key; + if (priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + } + + if (!BN_rand_range_ex(priv_key, 1, dsa->q)) { + goto err; + } + + pub_key = dsa->pub_key; + if (pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) { + goto err; + } + } + + if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock, + dsa->p, ctx) || + !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx, + dsa->method_mont_p)) { + goto err; + } + + dsa->priv_key = priv_key; + dsa->pub_key = pub_key; + ok = 1; + +err: + if (dsa->pub_key == NULL) { + BN_free(pub_key); + } + if (dsa->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + + return ok; +} + +DSA_SIG *DSA_SIG_new(void) { + DSA_SIG *sig; + sig = OPENSSL_malloc(sizeof(DSA_SIG)); + if (!sig) { + return NULL; + } + sig->r = NULL; + sig->s = NULL; + return sig; +} + +void DSA_SIG_free(DSA_SIG *sig) { + if (!sig) { + return; + } + + BN_free(sig->r); + BN_free(sig->s); + OPENSSL_free(sig); +} + +DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) { + BIGNUM *kinv = NULL, *r = NULL, *s = NULL; + BIGNUM m; + BIGNUM xr; + BN_CTX *ctx = NULL; + int reason = ERR_R_BN_LIB; + DSA_SIG *ret = NULL; + int noredo = 0; + + BN_init(&m); + BN_init(&xr); + + if (!dsa->p || !dsa->q || !dsa->g) { + reason = DSA_R_MISSING_PARAMETERS; + goto err; + } + + s = BN_new(); + if (s == NULL) { + goto err; + } + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + +redo: + if (dsa->kinv == NULL || dsa->r == NULL) { + if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) { + goto err; + } + } else { + kinv = dsa->kinv; + dsa->kinv = NULL; + r = dsa->r; + dsa->r = NULL; + noredo = 1; + } + + if (digest_len > BN_num_bytes(dsa->q)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = BN_num_bytes(dsa->q); + } + + if (BN_bin2bn(digest, digest_len, &m) == NULL) { + goto err; + } + + /* Compute s = inv(k) (m + xr) mod q */ + if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) { + goto err; /* s = xr */ + } + if (!BN_add(s, &xr, &m)) { + goto err; /* s = m + xr */ + } + if (BN_cmp(s, dsa->q) > 0) { + if (!BN_sub(s, s, dsa->q)) { + goto err; + } + } + if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) { + goto err; + } + + /* Redo if r or s is zero as required by FIPS 186-3: this is + * very unlikely. */ + if (BN_is_zero(r) || BN_is_zero(s)) { + if (noredo) { + reason = DSA_R_NEED_NEW_SETUP_VALUES; + goto err; + } + goto redo; + } + ret = DSA_SIG_new(); + if (ret == NULL) { + goto err; + } + ret->r = r; + ret->s = s; + +err: + if (ret == NULL) { + OPENSSL_PUT_ERROR(DSA, reason); + BN_free(r); + BN_free(s); + } + BN_CTX_free(ctx); + BN_clear_free(&m); + BN_clear_free(&xr); + BN_clear_free(kinv); + + return ret; +} + +int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig, + const DSA *dsa) { + int valid; + if (!DSA_do_check_signature(&valid, digest, digest_len, sig, dsa)) { + return -1; + } + return valid; +} + +int DSA_do_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, DSA_SIG *sig, const DSA *dsa) { + BN_CTX *ctx; + BIGNUM u1, u2, t1; + int ret = 0; + unsigned i; + + *out_valid = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; + } + + i = BN_num_bits(dsa->q); + /* fips 186-3 allows only different sizes for q */ + if (i != 160 && i != 224 && i != 256) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE); + return 0; + } + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE); + return 0; + } + + BN_init(&u1); + BN_init(&u2); + BN_init(&t1); + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || + BN_ucmp(sig->r, dsa->q) >= 0) { + ret = 1; + goto err; + } + if (BN_is_zero(sig->s) || BN_is_negative(sig->s) || + BN_ucmp(sig->s, dsa->q) >= 0) { + ret = 1; + goto err; + } + + /* Calculate W = inv(S) mod Q + * save W in u2 */ + if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) { + goto err; + } + + /* save M in u1 */ + if (digest_len > (i >> 3)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = (i >> 3); + } + + if (BN_bin2bn(digest, digest_len, &u1) == NULL) { + goto err; + } + + /* u1 = M * w mod q */ + if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) { + goto err; + } + + /* u2 = r * w mod q */ + if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) { + goto err; + } + + if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p, + ctx)) { + goto err; + } + + if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, + dsa->method_mont_p)) { + goto err; + } + + /* BN_copy(&u1,&t1); */ + /* let u1 = u1 mod q */ + if (!BN_mod(&u1, &t1, dsa->q, ctx)) { + goto err; + } + + /* V is now in u1. If the signature is correct, it will be + * equal to R. */ + *out_valid = BN_ucmp(&u1, sig->r) == 0; + ret = 1; + +err: + if (ret != 1) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + } + BN_CTX_free(ctx); + BN_free(&u1); + BN_free(&u2); + BN_free(&t1); + + return ret; +} + +int DSA_sign(int type, const uint8_t *digest, size_t digest_len, + uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) { + DSA_SIG *s; + + s = DSA_do_sign(digest, digest_len, dsa); + if (s == NULL) { + *out_siglen = 0; + return 0; + } + + *out_siglen = i2d_DSA_SIG(s, &out_sig); + DSA_SIG_free(s); + return 1; +} + +int DSA_verify(int type, const uint8_t *digest, size_t digest_len, + const uint8_t *sig, size_t sig_len, const DSA *dsa) { + int valid; + if (!DSA_check_signature(&valid, digest, digest_len, sig, sig_len, dsa)) { + return -1; + } + return valid; +} + +int DSA_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, size_t sig_len, + const DSA *dsa) { + DSA_SIG *s = NULL; + int ret = 0; + uint8_t *der = NULL; + + s = DSA_SIG_new(); + if (s == NULL) { + goto err; + } + + const uint8_t *sigp = sig; + if (d2i_DSA_SIG(&s, &sigp, sig_len) == NULL || sigp != sig + sig_len) { + goto err; + } + + /* Ensure that the signature uses DER and doesn't have trailing garbage. */ + int der_len = i2d_DSA_SIG(s, &der); + if (der_len < 0 || (size_t)der_len != sig_len || + OPENSSL_memcmp(sig, der, sig_len)) { + goto err; + } + + ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa); + +err: + OPENSSL_free(der); + DSA_SIG_free(s); + return ret; +} + +/* der_len_len returns the number of bytes needed to represent a length of |len| + * in DER. */ +static size_t der_len_len(size_t len) { + if (len < 0x80) { + return 1; + } + size_t ret = 1; + while (len > 0) { + ret++; + len >>= 8; + } + return ret; +} + +int DSA_size(const DSA *dsa) { + size_t order_len = BN_num_bytes(dsa->q); + /* Compute the maximum length of an |order_len| byte integer. Defensively + * assume that the leading 0x00 is included. */ + size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len; + if (integer_len < order_len) { + return 0; + } + /* A DSA signature is two INTEGERs. */ + size_t value_len = 2 * integer_len; + if (value_len < integer_len) { + return 0; + } + /* Add the header. */ + size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len; + if (ret < value_len) { + return 0; + } + return ret; +} + +int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, + BIGNUM **out_r) { + BN_CTX *ctx; + BIGNUM k, kq, *kinv = NULL, *r = NULL; + int ret = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; + } + + BN_init(&k); + BN_init(&kq); + + ctx = ctx_in; + if (ctx == NULL) { + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + r = BN_new(); + if (r == NULL) { + goto err; + } + + /* Get random k */ + if (!BN_rand_range_ex(&k, 1, dsa->q)) { + goto err; + } + + if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p, + ctx) || + !BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_q, + (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->q, + ctx)) { + goto err; + } + + /* Compute r = (g^k mod p) mod q */ + if (!BN_copy(&kq, &k)) { + goto err; + } + + /* We do not want timing information to leak the length of k, + * so we compute g^k using an equivalent exponent of fixed length. + * + * (This is a kludge that we need because the BN_mod_exp_mont() + * does not let us specify the desired timing behaviour.) */ + + if (!BN_add(&kq, &kq, dsa->q)) { + goto err; + } + if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) { + goto err; + } + + if (!BN_mod_exp_mont_consttime(r, dsa->g, &kq, dsa->p, ctx, + dsa->method_mont_p)) { + goto err; + } + if (!BN_mod(r, r, dsa->q, ctx)) { + goto err; + } + + /* Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little + * Theorem. */ + kinv = BN_new(); + if (kinv == NULL || + !bn_mod_inverse_prime(kinv, &k, dsa->q, ctx, dsa->method_mont_q)) { + goto err; + } + + BN_clear_free(*out_kinv); + *out_kinv = kinv; + kinv = NULL; + BN_clear_free(*out_r); + *out_r = r; + ret = 1; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + if (r != NULL) { + BN_clear_free(r); + } + } + + if (ctx_in == NULL) { + BN_CTX_free(ctx); + } + BN_clear_free(&k); + BN_clear_free(&kq); + BN_clear_free(kinv); + return ret; +} + +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int DSA_set_ex_data(DSA *d, int idx, void *arg) { + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DSA_get_ex_data(const DSA *d, int idx) { + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +DH *DSA_dup_DH(const DSA *r) { + DH *ret = NULL; + + if (r == NULL) { + goto err; + } + ret = DH_new(); + if (ret == NULL) { + goto err; + } + if (r->q != NULL) { + ret->priv_length = BN_num_bits(r->q); + if ((ret->q = BN_dup(r->q)) == NULL) { + goto err; + } + } + if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) || + (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) || + (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) || + (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) { + goto err; + } + + return ret; + +err: + DH_free(ret); + return NULL; +} diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_asn1.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_asn1.c new file mode 100644 index 000000000..ff5ee0039 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_asn1.c @@ -0,0 +1,339 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include <openssl/dsa.h> + +#include <assert.h> + +#include <openssl/bn.h> +#include <openssl/bytestring.h> +#include <openssl/err.h> +#include <openssl/mem.h> + +#include "../bytestring/internal.h" + + +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* A DSA object may be missing some components. */ + OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +DSA_SIG *DSA_SIG_parse(CBS *cbs) { + DSA_SIG *ret = DSA_SIG_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->r) || + !parse_integer(&child, &ret->s) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_SIG_free(ret); + return NULL; + } + return ret; +} + +int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, sig->r) || + !marshal_integer(&child, sig->s) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_public_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_parameters(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_private_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + + if (version != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION); + goto err; + } + + if (!parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->priv_key) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + return ret; + +err: + DSA_free(ret); + return NULL; +} + +int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, 0 /* version */) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->priv_key) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA_SIG *ret = DSA_SIG_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (out_sig != NULL) { + DSA_SIG_free(*out_sig); + *out_sig = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_SIG_marshal(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_public_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_private_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_parameters(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAparams(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_parameters(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_test.cc b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_test.cc new file mode 100644 index 000000000..63b78036e --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/dsa/dsa_test.cc @@ -0,0 +1,317 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch <schoch@sheba.arc.nasa.gov>. */ + +#include <openssl/dsa.h> + +#include <stdio.h> +#include <string.h> + +#include <gtest/gtest.h> + +#include <openssl/bn.h> +#include <openssl/crypto.h> +#include <openssl/err.h> + +#include "../internal.h" + + +/* The following values are taken from the updated Appendix 5 to FIPS PUB 186 + * and also appear in Appendix 5 to FIPS PUB 186-1. */ + +static const uint8_t seed[20] = { + 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b, + 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3, +}; + +static const uint8_t fips_p[] = { + 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75, + 0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, + 0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0, + 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac, + 0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, + 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91, +}; + +static const uint8_t fips_q[] = { + 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f, + 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f, +}; + +static const uint8_t fips_g[] = { + 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63, + 0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, + 0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71, + 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95, + 0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, + 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02, +}; + +static const uint8_t fips_x[] = { + 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f, + 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14, +}; + +static const uint8_t fips_y[] = { + 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2, + 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6, + 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d, + 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25, + 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06, + 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33, +}; + +static const uint8_t fips_digest[] = { + 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, + 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d, +}; + +/* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */ +static const uint8_t fips_sig[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, +}; + +/* fips_sig_negative is fips_sig with r encoded as a negative number. */ +static const uint8_t fips_sig_negative[] = { + 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43, + 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3, + 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf, + 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc, + 0xd8, 0xc8, +}; + +/* fip_sig_extra is fips_sig with trailing data. */ +static const uint8_t fips_sig_extra[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, 0x00, +}; + +/* fips_sig_lengths is fips_sig with a non-minimally encoded length. */ +static const uint8_t fips_sig_bad_length[] = { + 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, + 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, + 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, + 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, + 0xb6, 0xdc, 0xd8, 0xc8, 0x00, +}; + +/* fips_sig_bad_r is fips_sig with a bad r value. */ +static const uint8_t fips_sig_bad_r[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, +}; + +static bssl::UniquePtr<DSA> GetFIPSDSA(void) { + bssl::UniquePtr<DSA> dsa(DSA_new()); + if (!dsa) { + return nullptr; + } + dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), nullptr); + dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), nullptr); + dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), nullptr); + dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), nullptr); + dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), nullptr); + if (dsa->p == nullptr || dsa->q == nullptr || dsa->g == nullptr || + dsa->pub_key == nullptr || dsa->priv_key == nullptr) { + return nullptr; + } + return dsa; +} + +struct GenerateContext { + FILE *out = nullptr; + int ok = 0; + int num = 0; +}; + +static int GenerateCallback(int p, int n, BN_GENCB *arg) { + GenerateContext *ctx = reinterpret_cast<GenerateContext *>(arg->arg); + char c = '*'; + switch (p) { + case 0: + c = '.'; + ctx->num++; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + ctx->ok++; + break; + case 3: + c = '\n'; + } + fputc(c, ctx->out); + fflush(ctx->out); + if (!ctx->ok && p == 0 && ctx->num > 1) { + fprintf(stderr, "error in dsatest\n"); + return 0; + } + return 1; +} + +static int TestGenerate(FILE *out) { + BN_GENCB cb; + int counter, i, j; + uint8_t buf[256]; + unsigned long h; + uint8_t sig[256]; + unsigned int siglen; + + fprintf(out, "test generation of DSA parameters\n"); + + GenerateContext ctx; + ctx.out = out; + BN_GENCB_set(&cb, GenerateCallback, &ctx); + bssl::UniquePtr<DSA> dsa(DSA_new()); + if (!dsa || + !DSA_generate_parameters_ex(dsa.get(), 512, seed, 20, &counter, &h, + &cb)) { + return false; + } + + fprintf(out, "seed\n"); + for (i = 0; i < 20; i += 4) { + fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2], + seed[i + 3]); + } + fprintf(out, "\ncounter=%d h=%ld\n", counter, h); + + if (counter != 105) { + fprintf(stderr, "counter should be 105\n"); + return false; + } + if (h != 2) { + fprintf(stderr, "h should be 2\n"); + return false; + } + + i = BN_bn2bin(dsa->q, buf); + j = sizeof(fips_q); + if (i != j || OPENSSL_memcmp(buf, fips_q, i) != 0) { + fprintf(stderr, "q value is wrong\n"); + return false; + } + + i = BN_bn2bin(dsa->p, buf); + j = sizeof(fips_p); + if (i != j || OPENSSL_memcmp(buf, fips_p, i) != 0) { + fprintf(stderr, "p value is wrong\n"); + return false; + } + + i = BN_bn2bin(dsa->g, buf); + j = sizeof(fips_g); + if (i != j || OPENSSL_memcmp(buf, fips_g, i) != 0) { + fprintf(stderr, "g value is wrong\n"); + return false; + } + + if (!DSA_generate_key(dsa.get()) || + !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa.get())) { + return false; + } + if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa.get()) != + 1) { + fprintf(stderr, "verification failure\n"); + return false; + } + + return true; +} + +static bool TestVerify(const uint8_t *sig, size_t sig_len, int expect) { + bssl::UniquePtr<DSA> dsa = GetFIPSDSA(); + if (!dsa) { + return false; + } + + int ret = + DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa.get()); + if (ret != expect) { + fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect); + return false; + } + + /* Clear any errors from a test with expected failure. */ + ERR_clear_error(); + return true; +} + +// TODO(davidben): Convert this file to GTest properly. +TEST(DSATest, AllTests) { + if (!TestGenerate(stdout) || + !TestVerify(fips_sig, sizeof(fips_sig), 1) || + !TestVerify(fips_sig_negative, sizeof(fips_sig_negative), -1) || + !TestVerify(fips_sig_extra, sizeof(fips_sig_extra), -1) || + !TestVerify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) || + !TestVerify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) { + ADD_FAILURE() << "Tests failed"; + } +} |