1/*
2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdlib.h>
11#include <openssl/core_names.h>
12#include <openssl/err.h>
13#include <openssl/dsa.h>
14#include <openssl/evp.h>
15#include "crypto/evp.h"
16
17static int dsa_paramgen_check(EVP_PKEY_CTX *ctx)
18{
19    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
20        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
21        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
22        return -2;
23    }
24    /* If key type not DSA return error */
25    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_DSA)
26        return -1;
27    return 1;
28}
29
30int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name)
31{
32    int ret;
33    OSSL_PARAM params[2], *p = params;
34
35    if ((ret = dsa_paramgen_check(ctx)) <= 0)
36        return ret;
37
38    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE,
39                                            (char *)name, 0);
40    *p++ = OSSL_PARAM_construct_end();
41
42    return EVP_PKEY_CTX_set_params(ctx, params);
43}
44
45int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
46{
47    int ret;
48    OSSL_PARAM params[2], *p = params;
49
50    if ((ret = dsa_paramgen_check(ctx)) <= 0)
51        return ret;
52
53    *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
54    *p++ = OSSL_PARAM_construct_end();
55
56    return EVP_PKEY_CTX_set_params(ctx, params);
57}
58
59int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
60                                       const unsigned char *seed,
61                                       size_t seedlen)
62{
63    int ret;
64    OSSL_PARAM params[2], *p = params;
65
66    if ((ret = dsa_paramgen_check(ctx)) <= 0)
67        return ret;
68
69    *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
70                                             (void *)seed, seedlen);
71    *p++ = OSSL_PARAM_construct_end();
72
73    return EVP_PKEY_CTX_set_params(ctx, params);
74}
75
76int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits)
77{
78    int ret;
79    OSSL_PARAM params[2], *p = params;
80    size_t bits = nbits;
81
82    if ((ret = dsa_paramgen_check(ctx)) <= 0)
83        return ret;
84
85    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
86    *p++ = OSSL_PARAM_construct_end();
87
88    return EVP_PKEY_CTX_set_params(ctx, params);
89}
90
91int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits)
92{
93    int ret;
94    OSSL_PARAM params[2], *p = params;
95    size_t bits2 = qbits;
96
97    if ((ret = dsa_paramgen_check(ctx)) <= 0)
98        return ret;
99
100    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
101    *p++ = OSSL_PARAM_construct_end();
102
103    return EVP_PKEY_CTX_set_params(ctx, params);
104}
105
106int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
107                                           const char *md_name,
108                                           const char *md_properties)
109{
110    int ret;
111    OSSL_PARAM params[3], *p = params;
112
113    if ((ret = dsa_paramgen_check(ctx)) <= 0)
114        return ret;
115
116    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST,
117                                            (char *)md_name, 0);
118    if (md_properties != NULL)
119        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
120                                                (char *)md_properties, 0);
121    *p++ = OSSL_PARAM_construct_end();
122
123    return EVP_PKEY_CTX_set_params(ctx, params);
124}
125
126#if !defined(FIPS_MODULE)
127int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
128{
129    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
130                             EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md));
131}
132#endif
133