Files
openssl/test/dsa_no_digest_size_test.c
openssl-machine c721580653 Copyright year updates
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
MergeDate: Tue Mar 10 14:37:54 2026
Release: yes
2026-03-10 14:37:52 +00:00

168 lines
4.2 KiB
C

/*
* Copyright 2018-2026 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <stdlib.h>
#include <string.h>
#include "testutil.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#include "helpers/predefined_dsaparams.h"
static DSA *dsakey;
static int genkeys(void)
{
if (!TEST_ptr(dsakey = load_dsa_params()))
return 0;
if (!TEST_int_eq(DSA_generate_key(dsakey), 1))
return 0;
return 1;
}
static int sign_and_verify(int len)
{
/*
* Per FIPS 186-4, the hash is recommended to be the same length as q.
* If the hash is longer than q, the leftmost N bits are used; if the hash
* is shorter, then we left-pad (see appendix C.2.1).
*/
size_t sigLength;
int digestlen = BN_num_bytes(DSA_get0_q(dsakey));
int ok = 0;
unsigned char *dataToSign = OPENSSL_malloc(len);
unsigned char *paddedData = OPENSSL_malloc(digestlen);
unsigned char *signature = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
if (!TEST_ptr(dataToSign) || !TEST_ptr(paddedData) || !TEST_int_eq(RAND_bytes(dataToSign, len), 1))
goto end;
memset(paddedData, 0, digestlen);
if (len > digestlen)
memcpy(paddedData, dataToSign, digestlen);
else
memcpy(paddedData + digestlen - len, dataToSign, len);
if (!TEST_ptr(pkey = EVP_PKEY_new()))
goto end;
EVP_PKEY_set1_DSA(pkey, dsakey);
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
goto end;
if (!TEST_int_eq(EVP_PKEY_sign_init(ctx), 1))
goto end;
if (EVP_PKEY_sign(ctx, NULL, &sigLength, dataToSign, len) != 1) {
TEST_error("Failed to get signature length, len=%d", len);
goto end;
}
if (!TEST_ptr(signature = OPENSSL_malloc(sigLength)))
goto end;
if (EVP_PKEY_sign(ctx, signature, &sigLength, dataToSign, len) != 1) {
TEST_error("Failed to sign, len=%d", len);
goto end;
}
/* Check that the signature is okay via the EVP interface */
if (!TEST_int_eq(EVP_PKEY_verify_init(ctx), 1))
goto end;
/* ... using the same data we just signed */
if (EVP_PKEY_verify(ctx, signature, sigLength, dataToSign, len) != 1) {
TEST_error("EVP verify with unpadded length %d failed\n", len);
goto end;
}
/* ... padding/truncating the data to the appropriate digest size */
if (EVP_PKEY_verify(ctx, signature, sigLength, paddedData, digestlen) != 1) {
TEST_error("EVP verify with length %d failed\n", len);
goto end;
}
/* Verify again using the raw DSA interface */
if (DSA_verify(0, dataToSign, len, signature, (int)sigLength, dsakey) != 1) {
TEST_error("Verification with unpadded data failed, len=%d", len);
goto end;
}
if (DSA_verify(0, paddedData, digestlen, signature, (int)sigLength, dsakey) != 1) {
TEST_error("verify with length %d failed\n", len);
goto end;
}
ok = 1;
end:
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
OPENSSL_free(signature);
OPENSSL_free(paddedData);
OPENSSL_free(dataToSign);
return ok;
}
static int dsa_exact_size_test(void)
{
/*
* For a 2048-bit p, q should be either 224 or 256 bits per the table in
* FIPS 186-4 4.2.
*/
return sign_and_verify(224 / 8) && sign_and_verify(256 / 8);
}
static int dsa_small_digest_test(void)
{
return sign_and_verify(16) && sign_and_verify(1);
}
static int dsa_large_digest_test(void)
{
return sign_and_verify(33) && sign_and_verify(64);
}
void cleanup_tests(void)
{
DSA_free(dsakey);
}
#endif /* OPENSSL_NO_DSA */
int setup_tests(void)
{
#ifndef OPENSSL_NO_DSA
if (!genkeys())
return 0;
ADD_TEST(dsa_exact_size_test);
ADD_TEST(dsa_small_digest_test);
ADD_TEST(dsa_large_digest_test);
#endif
return 1;
}