1 /* kcapi_dh.c
2  *
3  * Copyright (C) 2006-2020 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26 
27 #include <wolfssl/wolfcrypt/settings.h>
28 
29 #if defined(WOLFSSL_KCAPI_DH)
30 
31 #include <wolfssl/wolfcrypt/error-crypt.h>
32 #include <wolfssl/wolfcrypt/logging.h>
33 #include <wolfssl/wolfcrypt/port/kcapi/wc_kcapi.h>
34 #include <wolfssl/wolfcrypt/port/kcapi/kcapi_dh.h>
35 #include <wolfssl/wolfcrypt/dh.h>
36 #include <wolfssl/wolfcrypt/asn.h>
37 
38 static const char WC_NAME_DH[] = "dh";
39 
KcapiDh_Free(DhKey * key)40 void KcapiDh_Free(DhKey* key)
41 {
42     if (key->handle != NULL) {
43         kcapi_kpp_destroy(key->handle);
44         key->handle = NULL;
45     }
46 }
47 
KcapiDh_SetParams(DhKey * key)48 static int KcapiDh_SetParams(DhKey* key)
49 {
50 #if defined(HAVE_FIPS) && \
51         (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
52     int ret = 0;
53     unsigned char* pkcs3 = NULL;
54     word32 len = 0, idx = 0, len2;
55 
56     len  = MAX_SEQ_SZ;                  /* Sequence */
57     len += ASN_TAG_SZ + MAX_LENGTH_SZ;  /* Integer */
58     len += mp_leading_bit(&key->p) ? 1 : 0;
59     len += mp_unsigned_bin_size(&key->p);
60     len += ASN_TAG_SZ + MAX_LENGTH_SZ;  /* Integer */
61     len += mp_leading_bit(&key->g) ? 1 : 0;
62     len += mp_unsigned_bin_size(&key->g);
63 
64     pkcs3 = (unsigned char*)XMALLOC(len, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
65     if (pkcs3 == NULL) {
66         ret = MEMORY_E;
67     }
68 
69     if (ret == 0) {
70         idx = len;
71         len2 = mp_unsigned_bin_size(&key->g);
72         idx -= len2;
73         ret = mp_to_unsigned_bin(&key->g, pkcs3 + idx);
74     }
75     if (ret >= 0) {
76         if (mp_leading_bit(&key->g)) {
77             pkcs3[--idx] = 0x00;
78             len2++;
79         }
80         idx -= SetLength(len2, NULL);
81         SetLength(len2, pkcs3 + idx);
82         pkcs3[--idx] = ASN_INTEGER;
83 
84         len2 = mp_unsigned_bin_size(&key->p);
85         idx -= len2;
86         ret = mp_to_unsigned_bin(&key->p, pkcs3 + idx);
87     }
88     if (ret >= 0) {
89         if (mp_leading_bit(&key->p)) {
90             pkcs3[--idx] = 0x00;
91             len2++;
92         }
93         idx -= SetLength(len2, NULL);
94         SetLength(len2, pkcs3 + idx);
95         pkcs3[--idx] = ASN_INTEGER;
96 
97         len2 = len - idx;
98         idx -= SetSequence(len2, NULL);
99         SetSequence(len2, pkcs3 + idx);
100 
101         ret = kcapi_kpp_dh_setparam_pkcs3(key->handle, pkcs3 + idx, len - idx);
102         if (ret != 0) {
103             WOLFSSL_MSG("KcapiDh_SetParams: Failed to set");
104         }
105     }
106 
107     if (pkcs3 != NULL) {
108         XFREE(pkcs3, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
109     }
110     return ret;
111 #else
112     int ret;
113     unsigned char* pkcs3 = NULL;
114     word32 len;
115 
116     ret = wc_DhParamsToDer(key, NULL, &len);
117     if (ret == LENGTH_ONLY_E) {
118         ret = 0;
119         pkcs3 = (unsigned char*)XMALLOC(len, key->heap,
120                                                        DYNAMIC_TYPE_TMP_BUFFER);
121         if (pkcs3 == NULL) {
122             ret = MEMORY_E;
123         }
124     }
125     if (ret == 0) {
126         ret = wc_DhParamsToDer(key, pkcs3, &len);
127     }
128     if (ret == 0) {
129         ret = kcapi_kpp_dh_setparam_pkcs3(key->handle, pkcs3, len);
130         if (ret != 0) {
131             WOLFSSL_MSG("KcapiDh_SetParams: Failed to set");
132         }
133     }
134 
135     if (pkcs3 != NULL) {
136         XFREE(pkcs3, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
137     }
138     return ret;
139 #endif
140 }
141 
KcapiDh_MakeKey(DhKey * key,byte * pub,word32 * pubSz)142 int KcapiDh_MakeKey(DhKey* key, byte* pub, word32* pubSz)
143 {
144     int ret = 0;
145 
146     if (key->handle != NULL) {
147         kcapi_kpp_destroy(key->handle);
148         key->handle = NULL;
149     }
150     if (ret == 0) {
151         ret = kcapi_kpp_init(&key->handle, WC_NAME_DH, 0);
152         if (ret != 0) {
153             WOLFSSL_MSG("KcapiDh_MakeKey: Failed to initialization");
154         }
155     }
156 
157     if (ret == 0) {
158         ret = KcapiDh_SetParams(key);
159     }
160     if (ret == 0) {
161         ret = kcapi_kpp_keygen(key->handle, pub, *pubSz,
162                                KCAPI_ACCESS_HEURISTIC);
163     }
164 
165     return ret;
166 }
167 
KcapiDh_SharedSecret(DhKey * private_key,const byte * pub,word32 pubSz,byte * out,word32 * outlen)168 int KcapiDh_SharedSecret(DhKey* private_key, const byte* pub, word32 pubSz,
169                          byte* out, word32* outlen)
170 {
171     int ret;
172 
173     ret = kcapi_kpp_ssgen(private_key->handle, pub, pubSz, out, *outlen,
174                           KCAPI_ACCESS_HEURISTIC);
175     if (ret >= 0) {
176         *outlen = ret;
177         ret = 0;
178     }
179 
180     return ret;
181 }
182 
183 #endif /* WOLFSSL_KCAPI_DH */
184