1 /* psoc6_crypto.c
2  *
3  * Copyright (C) 2006-2021 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 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25 
26 #include <wolfssl/wolfcrypt/settings.h>
27 #ifdef NO_INLINE
28     #include <wolfssl/wolfcrypt/misc.h>
29 #else
30     #define WOLFSSL_MISC_INCLUDED
31     #include <wolfcrypt/src/misc.c>
32 #endif
33 
34 #if defined(WOLFSSL_PSOC6_CRYPTO)
35 #ifdef WOLFSSL_SP_MATH
36     struct sp_int;
37     #define MATH_INT_T struct sp_int
38 #elif defined(USE_FAST_MATH)
39     struct fp_int;
40     #define MATH_INT_T struct fp_int
41 #else
42     struct mp_int;
43 	#define MATH_INT_T struct mp_int
44 #endif
45 
46 #include <wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h>
47 #include <wolfssl/wolfcrypt/random.h>
48 #include <wolfssl/wolfcrypt/error-crypt.h>
49 #include <wolfssl/wolfcrypt/logging.h>
50 #include <stdint.h>
51 
52 static CRYPTO_Type *crypto_base = PSOC6_CRYPTO_BASE;
53 
54 /* Hook for device specific initialization */
psoc6_crypto_port_init(void)55 int psoc6_crypto_port_init(void)
56 {
57     Cy_Crypto_Core_Enable(crypto_base);
58     return 0;
59 }
60 
61 /* Sha-512 */
62 
63 #ifdef WOLFSSL_SHA512
wc_InitSha512(wc_Sha512 * sha)64 int wc_InitSha512(wc_Sha512* sha)
65 {
66     cy_en_crypto_status_t res;
67     if (!sha)
68         return BAD_FUNC_ARG;
69     Cy_Crypto_Core_MemSet(crypto_base, sha, 0, sizeof(sha));
70     res = Cy_Crypto_Core_Sha_Init(crypto_base, &sha->hash_state, CY_CRYPTO_MODE_SHA512, &sha->sha_buffers);
71     if (res != CY_CRYPTO_SUCCESS)
72        return (int)res;
73     return (int) Cy_Crypto_Core_Sha_Start(crypto_base, &sha->hash_state);
74 }
75 
wc_Sha512Update(wc_Sha512 * sha,const byte * in,word32 sz)76 int wc_Sha512Update(wc_Sha512* sha, const byte* in, word32 sz)
77 {
78     if ((!sha) || (!in))
79         return BAD_FUNC_ARG;
80     if (sz == 0)
81         return 0;
82 
83     return (int)Cy_Crypto_Core_Sha_Update(crypto_base, &sha->hash_state, in, sz);
84 }
85 
wc_Sha512Final(wc_Sha512 * sha,byte * hash)86 int wc_Sha512Final(wc_Sha512* sha, byte* hash)
87 {
88     if ((!sha) || (!hash))
89         return BAD_FUNC_ARG;
90     return (int)Cy_Crypto_Core_Sha_Finish(crypto_base, &sha->hash_state, hash);
91 }
92 
wc_Sha512GetHash(wc_Sha512 * sha,byte * hash)93 int wc_Sha512GetHash(wc_Sha512* sha, byte* hash)
94 {
95     if ((!sha) || (!hash))
96         return BAD_FUNC_ARG;
97     Cy_Crypto_Core_MemCpy(crypto_base, hash, sha->hash_state.hash, WC_SHA512_DIGEST_SIZE);
98     return 0;
99 }
100 
wc_Sha512Copy(wc_Sha512 * src,wc_Sha512 * dst)101 int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
102 {
103     cy_en_crypto_status_t res;
104     if ((!dst) || (!src))
105         return BAD_FUNC_ARG;
106     Cy_Crypto_Core_MemCpy(crypto_base, dst, src, sizeof(wc_Sha512));
107     return (int)Cy_Crypto_Core_Sha_Init(crypto_base, &dst->hash_state, CY_CRYPTO_MODE_SHA512, &dst->sha_buffers);
108 }
109 
wc_Sha512Free(wc_Sha512 * sha)110 void wc_Sha512Free(wc_Sha512* sha)
111 {
112     if (sha)
113         Cy_Crypto_Core_Sha_Free(crypto_base, &sha->hash_state);
114 }
115 
116 #endif
117 
118 /* Sha-256 */
119 
120 #ifndef NO_SHA256
wc_InitSha256(wc_Sha256 * sha)121 int wc_InitSha256(wc_Sha256* sha)
122 {
123     cy_en_crypto_status_t res;
124     if (!sha)
125         return BAD_FUNC_ARG;
126     Cy_Crypto_Core_MemSet(crypto_base, sha, 0, sizeof(sha));
127     res = Cy_Crypto_Core_Sha_Init(crypto_base, &sha->hash_state, CY_CRYPTO_MODE_SHA256, &sha->sha_buffers);
128     if (res != CY_CRYPTO_SUCCESS)
129        return (int)res;
130     return (int) Cy_Crypto_Core_Sha_Start(crypto_base, &sha->hash_state);
131 }
132 
wc_Sha256Update(wc_Sha256 * sha,const byte * in,word32 sz)133 int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
134 {
135     if ((!sha) || (!in))
136         return BAD_FUNC_ARG;
137     if (sz == 0)
138         return 0;
139 
140     return (int)Cy_Crypto_Core_Sha_Update(crypto_base, &sha->hash_state, in, sz);
141 }
142 
wc_Sha256Final(wc_Sha256 * sha,byte * hash)143 int wc_Sha256Final(wc_Sha256* sha, byte* hash)
144 {
145     if ((!sha) || (!hash))
146         return BAD_FUNC_ARG;
147     return (int)Cy_Crypto_Core_Sha_Finish(crypto_base, &sha->hash_state, hash);
148 }
149 
wc_Sha256GetHash(wc_Sha256 * sha,byte * hash)150 int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
151 {
152     if ((!sha) || (!hash))
153         return BAD_FUNC_ARG;
154     Cy_Crypto_Core_MemCpy(crypto_base, hash, sha->hash_state.hash, WC_SHA256_DIGEST_SIZE);
155     return 0;
156 }
157 
wc_Sha256Copy(wc_Sha256 * src,wc_Sha256 * dst)158 int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
159 {
160     cy_en_crypto_status_t res;
161     if ((!dst) || (!src))
162         return BAD_FUNC_ARG;
163     Cy_Crypto_Core_MemCpy(crypto_base, dst, src, sizeof(wc_Sha256));
164     return (int)Cy_Crypto_Core_Sha_Init(crypto_base, &dst->hash_state, CY_CRYPTO_MODE_SHA256, &dst->sha_buffers);
165 }
166 
wc_Sha256Free(wc_Sha256 * sha)167 void wc_Sha256Free(wc_Sha256* sha)
168 {
169     if (sha)
170         Cy_Crypto_Core_Sha_Free(crypto_base, &sha->hash_state);
171 }
172 #endif /* NO_SHA256 */
173 
174 /* ECDSA */
175 #ifdef HAVE_ECC
176 
177 #define MAX_ECC_KEYSIZE 66 /* Supports up to secp521r1 */
psoc6_get_curve_id(int size)178 static cy_en_crypto_ecc_curve_id_t psoc6_get_curve_id(int size)
179 {
180     switch(size) {
181         case 24:
182             return CY_CRYPTO_ECC_ECP_SECP192R1;
183         case 28:
184             return CY_CRYPTO_ECC_ECP_SECP224R1;
185         case 32:
186             return CY_CRYPTO_ECC_ECP_SECP256R1;
187         case 48:
188             return CY_CRYPTO_ECC_ECP_SECP384R1;
189         case 66:
190             return CY_CRYPTO_ECC_ECP_SECP521R1;
191         default:
192             return CY_CRYPTO_ECC_ECP_NONE;
193     }
194 }
195 
196 #include <wolfssl/wolfcrypt/ecc.h>
psoc6_ecc_verify_hash_ex(MATH_INT_T * r,MATH_INT_T * s,const byte * hash,word32 hashlen,int * verif_res,ecc_key * key)197 int psoc6_ecc_verify_hash_ex(MATH_INT_T *r, MATH_INT_T *s, const byte* hash,
198                     word32 hashlen, int* verif_res, ecc_key* key)
199 {
200     uint8_t signature_buf[MAX_ECC_KEYSIZE * 2];
201     cy_stc_crypto_ecc_key ecc_key;
202     uint8_t stat = 0;
203     int res = -1;
204     int szModulus;
205     int szkbin;
206     uint8_t x[MAX_ECC_KEYSIZE], y[MAX_ECC_KEYSIZE];
207 
208     if (!key || !verif_res || !r || !s || !hash)
209         return -BAD_FUNC_ARG;
210 
211     /* retrieve and check sizes */
212     szModulus = mp_unsigned_bin_size(key->pubkey.x);
213     szkbin = mp_unsigned_bin_size(r);
214     if (szModulus > MAX_ECC_KEYSIZE)
215         return -BAD_FUNC_ARG;
216 
217     /* Prepare ECC key */
218     ecc_key.type = PK_PUBLIC;
219     ecc_key.curveID = psoc6_get_curve_id(szModulus);
220     ecc_key.k = NULL;
221     ecc_key.pubkey.x = x;
222     ecc_key.pubkey.y = y;
223 
224     res = mp_to_unsigned_bin(key->pubkey.x, x);
225     if (res == MP_OKAY)
226         res = mp_to_unsigned_bin(key->pubkey.y, y);
227     Cy_Crypto_Core_InvertEndianness(x, szModulus);
228     Cy_Crypto_Core_InvertEndianness(y, szModulus);
229 
230     /* Prepare signature buffer */
231     if (res == MP_OKAY)
232         res = mp_to_unsigned_bin(r, signature_buf);
233     if (res == MP_OKAY)
234         res = mp_to_unsigned_bin(s, signature_buf + szkbin);
235     Cy_Crypto_Core_InvertEndianness(signature_buf, szkbin);
236     Cy_Crypto_Core_InvertEndianness(signature_buf + szkbin, szkbin);
237 
238     /* perform HW ECDSA */
239     if (res == MP_OKAY)
240         res = Cy_Crypto_Core_ECC_VerifyHash(crypto_base, signature_buf, hash, hashlen, &stat, &ecc_key);
241     if (res == 0) {
242         *verif_res = stat;
243     }
244     return res;
245 }
246 #endif /* HAVE_ECC */
247 
248 
249 
250 #endif /* defined(WOLFSSL_PSOC6_CRYPTO) */
251 
252