Add FFC param/key generation
[oweals/openssl.git] / crypto / dsa / dsa_key.c
1 /*
2  * Copyright 1995-2016 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 <stdio.h>
11 #include <time.h>
12 #include "internal/cryptlib.h"
13 #include <openssl/bn.h>
14 #include "crypto/dsa.h"
15 #include "dsa_local.h"
16
17 static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa);
18
19 int DSA_generate_key(DSA *dsa)
20 {
21     if (dsa->meth->dsa_keygen != NULL)
22         return dsa->meth->dsa_keygen(dsa);
23     return dsa_builtin_keygen(NULL, dsa);
24 }
25
26 int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa)
27 {
28 #ifndef FIPS_MODE
29     if (dsa->meth->dsa_keygen != NULL)
30         return dsa->meth->dsa_keygen(dsa);
31 #endif
32     return dsa_builtin_keygen(libctx, dsa);
33 }
34
35 static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa)
36 {
37     int ok = 0;
38     BN_CTX *ctx = NULL;
39     BIGNUM *pub_key = NULL, *priv_key = NULL;
40
41     if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
42         goto err;
43
44     if (dsa->priv_key == NULL) {
45         if ((priv_key = BN_secure_new()) == NULL)
46             goto err;
47     } else {
48         priv_key = dsa->priv_key;
49     }
50
51     if (!ffc_generate_private_key(ctx, &dsa->params, BN_num_bits(dsa->params.q),
52                                   112, priv_key))
53         goto err;
54
55     if (dsa->pub_key == NULL) {
56         if ((pub_key = BN_new()) == NULL)
57             goto err;
58     } else {
59         pub_key = dsa->pub_key;
60     }
61
62     {
63         BIGNUM *prk = BN_new();
64
65         if (prk == NULL)
66             goto err;
67         BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
68
69         /* pub_key = g ^ priv_key mod p */
70         if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) {
71             BN_free(prk);
72             goto err;
73         }
74         /* We MUST free prk before any further use of priv_key */
75         BN_free(prk);
76     }
77
78     dsa->priv_key = priv_key;
79     dsa->pub_key = pub_key;
80     dsa->dirty_cnt++;
81     ok = 1;
82
83  err:
84     if (pub_key != dsa->pub_key)
85         BN_free(pub_key);
86     if (priv_key != dsa->priv_key)
87         BN_free(priv_key);
88     BN_CTX_free(ctx);
89     return ok;
90 }