Support multi-prime RSA (RFC 8017)
[openssl.git] / crypto / rsa / rsa_mp.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright 2017 BaishanCloud. All rights reserved.
4  *
5  * Licensed under the OpenSSL license (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 #include <openssl/bn.h>
12 #include "rsa_locl.h"
13
14 void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo)
15 {
16     /* free pp and pinfo only */
17     BN_clear_free(pinfo->pp);
18     OPENSSL_free(pinfo);
19 }
20
21 void rsa_multip_info_free(RSA_PRIME_INFO *pinfo)
22 {
23     /* free a RSA_PRIME_INFO structure */
24     BN_clear_free(pinfo->r);
25     BN_clear_free(pinfo->d);
26     BN_clear_free(pinfo->t);
27     rsa_multip_info_free_ex(pinfo);
28 }
29
30 RSA_PRIME_INFO *rsa_multip_info_new(void)
31 {
32     RSA_PRIME_INFO *pinfo;
33
34     /* create a RSA_PRIME_INFO structure */
35     pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO));
36     if (pinfo == NULL)
37         return NULL;
38     if ((pinfo->r = BN_secure_new()) == NULL)
39         goto err;
40     if ((pinfo->d = BN_secure_new()) == NULL)
41         goto err;
42     if ((pinfo->t = BN_secure_new()) == NULL)
43         goto err;
44     if ((pinfo->pp = BN_secure_new()) == NULL)
45         goto err;
46
47     return pinfo;
48
49  err:
50     BN_free(pinfo->r);
51     BN_free(pinfo->d);
52     BN_free(pinfo->t);
53     BN_free(pinfo->pp);
54     return NULL;
55 }
56
57 /* Refill products of primes */
58 int rsa_multip_calc_product(RSA *rsa)
59 {
60     RSA_PRIME_INFO *pinfo;
61     BIGNUM *p1 = NULL, *p2 = NULL;
62     BN_CTX *ctx = NULL;
63     int i, rv = 0, ex_primes;
64
65     if ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0) {
66         /* invalid */
67         goto err;
68     }
69
70     if ((ctx = BN_CTX_new()) == NULL)
71         goto err;
72
73     /* calculate pinfo->pp = p * q for first 'extra' prime */
74     p1 = rsa->p;
75     p2 = rsa->q;
76
77     for (i = 0; i < ex_primes; i++) {
78         pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
79         if (pinfo->pp == NULL) {
80             pinfo->pp = BN_secure_new();
81             if (pinfo->pp == NULL)
82                 goto err;
83         }
84         if (!BN_mul(pinfo->pp, p1, p2, ctx))
85             goto err;
86         /* save previous one */
87         p1 = pinfo->pp;
88         p2 = pinfo->r;
89     }
90
91     rv = 1;
92  err:
93     BN_CTX_free(ctx);
94     return rv;
95 }