1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8 #include "common_sb_ops.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdint.h>
14 #include <stdbool.h>
15
16 #include <openssl/objects.h>
17 #include <openssl/pem.h>
18 #include <openssl/evp.h>
19 #include <openssl/rand.h>
20 #include <openssl/bn.h>
21 #include <openssl/aes.h>
22 #include <openssl/err.h>
23 #include "common_rsa_keypair.h"
24 #include "common_rsa_keypair_util.h"
25 #include "common_crypto_asym.h"
26 #include "common_util_log.h"
27 #include "cc_crypto_defs.h"
28 #include "cc_pka_hw_plat_defs.h"
29
30 /**
31 * @brief The Sign_v15 generates RSA signature using PKCS#1 v1.5 algorithm.
32 *
33 * The function
34 * 1. Create RSA signature
35 * 2. Verify the signature correctness
36 * @param[in] pRsaPrivKey - the private key
37 * @param[in] DataIn_ptr - the data to sign on
38 * @param[in] DataInSize - the data size
39 * @param[in] Key_ptr - passphrase string
40 * @param[out] Signature_ptr - the RSA signature
41 *
42 */
43 /*********************************************************/
Sign_v15(RSA * pRsaPrivKey,char * DataIn_ptr,int DataInSize,char * Signature_ptr,char * Key_ptr)44 int Sign_v15(RSA *pRsaPrivKey, char *DataIn_ptr, // IG - merge with common implementation
45 int DataInSize, char *Signature_ptr,
46 char *Key_ptr)
47 {
48 RSA *pRsaPubKey = NULL;
49 BIO *bio = NULL;
50 int status = -1;
51 EVP_PKEY *pKey = NULL;
52 EVP_MD_CTX *md_ctx = NULL;
53 int SignatureSize = SB_CERT_RSA_KEY_SIZE_IN_BYTES;
54
55 /*EVP_PKEY_new() allocates an empty EVP_PKEY structure which
56 is used by OpenSSL to store private keys.*/
57 pKey = EVP_PKEY_new();
58 /*set the referenced key to key*/
59 if (!EVP_PKEY_assign_RSA(pKey, pRsaPrivKey))
60 SIGN_RELEASE("EVP_PKEY_assign_RSA Private key")
61
62 /* fill and sign on the HASH output */
63 md_ctx = EVP_MD_CTX_create();
64 /* initializes a signing context to use the default implementation of digest type.*/
65 if (!EVP_SignInit(md_ctx, EVP_sha256()))
66 SIGN_RELEASE("EVP_SignInit")
67 /*hash data into the signature */
68 if (!EVP_SignUpdate(md_ctx, DataIn_ptr, DataInSize))
69 SIGN_RELEASE("EVP_SignUpdate")
70 /*signs the data using the private key pkey and places the signature*/
71 if (!EVP_SignFinal(md_ctx, Signature_ptr, &SignatureSize, pKey))
72 SIGN_RELEASE("EVP_SignFinal")
73
74 // Create public key
75 bio = BIO_new(BIO_s_mem());
76 pRsaPubKey = RSA_new();
77 if (!PEM_write_bio_RSA_PUBKEY(bio, pRsaPrivKey))
78 SIGN_RELEASE("PEM_write_bio_RSA_PUBKEY")
79
80 if (PEM_read_bio_RSA_PUBKEY(bio,&pRsaPubKey,NULL,Key_ptr) == NULL)
81 SIGN_RELEASE("PEM_read_bio_RSA_PUBKEY")
82
83 if (!EVP_PKEY_assign_RSA(pKey, pRsaPubKey))
84 SIGN_RELEASE("EVP_PKEY_assign_RSA Public key")
85 /* initializes verification context ctx to use the default implementation of digest type*/
86 if (!EVP_VerifyInit(md_ctx, EVP_sha256()))
87 SIGN_RELEASE("EVP_VerifyInit")
88 /*hashes bytes of data into the verification context*/
89 if (!EVP_VerifyUpdate(md_ctx, DataIn_ptr, DataInSize))
90 SIGN_RELEASE("EVP_VerifyUpdate")
91 /*verifies the data in, using the public.*/
92 if (!EVP_VerifyFinal(md_ctx, Signature_ptr, SignatureSize, pKey))
93 SIGN_RELEASE("EVP_VerifyFinal")
94
95 status = 0;
96
97 SIGN_RELEASE("")
98 }
99
100
101 /**
102 * @brief The Sign_v21 generates RSA signature using PKCS#1 v2.1 algorithm.
103 *
104 * The function
105 * 1. Create RSA signature
106 * 2. Verify the signature correctness
107 * @param[in] pRsaPrivKey - the private key
108 * @param[in] DataIn_ptr - the data to sign on
109 * @param[in] DataInSize - the data size
110 * @param[out] Signature_ptr - the RSA signature
111 *
112 */
113 /*********************************************************/
Sign_v21(RSA * pRsaPrivKey,char * DataIn_ptr,int DataInSize,char * Signature_ptr)114 int Sign_v21(RSA *pRsaPrivKey, char *DataIn_ptr,
115 int DataInSize, char *Signature_ptr)
116 {
117 unsigned char pDigest[HASH_SHA256_DIGEST_SIZE_IN_BYTES];
118 unsigned int uDigestLen = HASH_SHA256_DIGEST_SIZE_IN_BYTES;
119 EVP_MD_CTX md_ctx;
120 unsigned char EM[SB_CERT_RSA_KEY_SIZE_IN_BYTES];
121 unsigned char pDecrypted[SB_CERT_RSA_KEY_SIZE_IN_BYTES];
122 int status = -1;
123
124 /* hash the message */
125 EVP_MD_CTX_init(&md_ctx);
126 EVP_DigestInit(&md_ctx, EVP_sha256());
127 EVP_DigestUpdate(&md_ctx, (const void*) DataIn_ptr, DataInSize);
128 EVP_DigestFinal(&md_ctx, pDigest, &uDigestLen);
129 EVP_MD_CTX_cleanup(&md_ctx);
130
131 /* compute the PSS padded data */
132 if (!RSA_padding_add_PKCS1_PSS(pRsaPrivKey, EM, pDigest, EVP_sha256(), RSA_SALT_LEN))
133 SIGN21_RELEASE("RSA_padding_add_PKCS1_PSS")
134
135 /* perform digital signature */
136 if (RSA_private_encrypt(SB_CERT_RSA_KEY_SIZE_IN_BYTES, EM, Signature_ptr, pRsaPrivKey, RSA_NO_PADDING) == -1)
137 SIGN21_RELEASE("RSA_private_encrypt")
138
139 /* verify the data */
140 if (RSA_public_decrypt(SB_CERT_RSA_KEY_SIZE_IN_BYTES, Signature_ptr, pDecrypted, pRsaPrivKey, RSA_NO_PADDING) == -1)
141 SIGN21_RELEASE("RSA_public_decrypt")
142
143 if (RSA_verify_PKCS1_PSS(pRsaPrivKey, pDigest, EVP_sha256(), pDecrypted, RSA_SALT_LEN) != 1)
144 SIGN21_RELEASE("RSA_verify_PKCS1_PSS")
145
146 status = 0;
147
148 SIGN21_RELEASE("")
149 }
150
151
reverseBuff(uint8_t * pBuff,uint32_t size)152 void reverseBuff( uint8_t *pBuff , uint32_t size )
153 {
154 uint32_t i;
155 uint32_t temp;
156
157 for( i = 0 ; i < (size / 2) ; i++ )
158 {
159 temp = pBuff[i];
160 pBuff[i] = pBuff[size - i - 1];
161 pBuff[size - i - 1] = temp;
162 }
163
164 return;
165
166 }/* END OF UTIL_ReverseBuff */
167
168
169 /**
170 * @brief The function SBU_GetNFromKeyPairAndCalcH Reads RSA key from the file using passphrase,
171 * and returns its decrypted value and its calculated Hash
172 *
173 * @param[in] PemEncryptedFileName_ptr - file name
174 * @param[in] pwdFileName - file name of the password
175 * @param[out] PemDecryted - N buffer
176 * @param[out] H_ptr - The H result. H size is N_SIZE_IN_BYTES*2 + 1
177 *
178 */
179 /*********************************************************/
SBU_GetNFromKeyPairAndCalcH(char * PemEncryptedFileName_ptr,char * pwdFileName,char * N_ptr,char * H_ptr)180 SBUEXPORT_C int SBU_GetNFromKeyPairAndCalcH(char* PemEncryptedFileName_ptr, char *pwdFileName, char *N_ptr, char *H_ptr)
181 {
182 char *H_res = NULL, *N_Temp = NULL, *H_resTemp = NULL;
183 int len, i;
184 int status = -1;
185 unsigned long s = SB_CERT_RSA_KEY_SIZE_IN_BITS + 2;
186 int rc = 0;
187 int nSize = SB_CERT_RSA_KEY_SIZE_IN_BYTES;
188 unsigned char *pwdPtr = NULL;
189
190 if( strlen(pwdFileName) )
191 pwdPtr = pwdFileName;
192 else
193 pwdPtr = Nullptr;
194
195 OpenSSL_add_all_algorithms ();
196
197 /* get N buffer */
198 rc = CC_CommonGetNbuffFromKeyPair(PemEncryptedFileName_ptr, pwdPtr, N_ptr, &nSize);
199 EVP_cleanup();
200 CRYPTO_cleanup_all_ex_data(); /* cleanup application specific data to avoid memory leaks.*/
201 if (rc != 0) {
202 printf( "failed to CC_CommonGetNbuffFromKeyPair %d \n", rc);
203 return rc;
204 }
205
206 BN_CTX *bn_ctx = BN_CTX_new();
207
208 BIGNUM *bn_two = BN_new();
209 BIGNUM *bn_twos = BN_new();
210 BIGNUM *bn_n = BN_new();
211 BIGNUM *bn_h = BN_new();
212
213 if ((NULL == N_ptr) || ( NULL == H_ptr))
214 CALCULATE_H_RELEASE("SBU_RSA_CalculateH: Illegal input parameters.")
215
216 /* Copy the N to temporary N, allocate temporary N in N size + 2 */
217 N_Temp= (char *)malloc ((SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 + 2) * sizeof (char));
218
219 /* If malloc failed return error */
220 if (NULL == N_Temp)
221 CALCULATE_H_RELEASE("Error during memory allocation.")
222
223 /* set the temporary N to 0 */
224 memset (N_Temp, 0, (SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 + 2));
225
226 /* Copy the N to temp N */
227 memcpy (N_Temp, N_ptr, SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2);
228
229 /* Allocate the output buffer */
230 if (NULL == (H_res = (char *)malloc ((SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 + 2) * sizeof (char))))
231 CALCULATE_H_RELEASE("Error during memory allocation.")
232
233 BN_set_word (bn_two, 2);
234 BN_set_word (bn_twos, 2 * s);
235
236 bn_n = BN_bin2bn(N_ptr, SB_CERT_RSA_KEY_SIZE_IN_BYTES, bn_n);
237 if (NULL == bn_n)
238 CALCULATE_H_RELEASE("BN_bin2bn failed.")
239
240 if (!BN_mod_exp (bn_h, bn_two, bn_twos, bn_n, bn_ctx))
241 CALCULATE_H_RELEASE("BN_mod_exp failed.")
242
243 H_resTemp = BN_bn2hex (bn_h);
244 if (H_resTemp == NULL)
245 CALCULATE_H_RELEASE("BN_bn2hex failed.")
246 if (H_resTemp[0] == '-'){
247 CALCULATE_H_RELEASE("BN_bn2hex failed.")
248 }
249
250 len = (int)strlen (H_resTemp);
251 memcpy(H_res, H_resTemp, len);
252
253 if (len < SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2)
254 {
255 memmove (H_res + (SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 - len), H_res, len + 1);
256 for (i = 0; i < (int)(SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 - len); i++)
257 H_res[i] = '0';
258 }
259
260 /* Set the output with 0 and than copy the result */
261 memset (H_ptr, 0, (SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 + 2));
262 memcpy ((char *)H_ptr, (char *)H_res, SB_CERT_RSA_KEY_SIZE_IN_BYTES * 2 + 2);
263
264 status = 0;
265
266 CALCULATE_H_RELEASE("")
267 }
268
269 /**
270 * @brief The SBU_RAND_Bytes reads RSA key from the file using passphrase
271 * and returns its decrypted value.
272 *
273 * @param[in] PemEncryptedFileName_ptr - file name
274 * @param[in] Key_ptr - passphrase
275 */
276 /*********************************************************/
SBU_RAND_Bytes(int numBytes,char * buf)277 SBUEXPORT_C int SBU_RAND_Bytes(int numBytes, char *buf)
278 {
279 int result = -1;
280
281 if (numBytes > 0)
282 {
283 result = RAND_bytes (buf, numBytes);
284 if (result <= 0)
285 printf ("\nSBU_RAND_Bytes - Internal error: Function RAND_bytes failed\n");
286 }
287 return result;
288 }
289
290
291 /**
292 * @brief Reads RSA key from the file using passphrase, and returns its decrypted value and its Np
293 *
294 * @param[in] PemEncryptedFileName_ptr - file name
295 * @param[in] pwdFileName - file name of the password
296 * @param[out] PemDecryted - N and Np buffer
297 */
298 /*********************************************************/
SBU_GetNAndNpFromKeyPair(char * PemEncryptedFileName_ptr,char * pwdFileName,char * PemDecryted)299 SBUEXPORT_C int SBU_GetNAndNpFromKeyPair(char* PemEncryptedFileName_ptr, char *pwdFileName, char *PemDecryted)
300 {
301 int rc = 0;
302 int nAndNpSize = SB_CERT_RSA_KEY_SIZE_IN_BYTES+NP_SIZE_IN_BYTES;
303 unsigned char *pwdPtr = NULL;
304
305 if( strlen(pwdFileName) )
306 pwdPtr = pwdFileName;
307 else
308 pwdPtr = Nullptr;
309
310 OpenSSL_add_all_algorithms ();
311
312 /* get N and Np buffer */
313 rc = CC_CommonGetNAndNpFromKeyPair(PemEncryptedFileName_ptr, pwdPtr, PemDecryted, &nAndNpSize);
314 if (rc != 0) {
315 printf( "failed to CC_CommonGetNAndNpFromKeyPair %d or ilegal size %d\n", rc, nAndNpSize);
316 }
317
318 EVP_cleanup();
319 CRYPTO_cleanup_all_ex_data(); /* cleanup application specific data to avoid memory leaks.*/
320
321 return rc;
322 }
323
324
325 /**
326 * @brief Reads RSA key from the file using passphrase, and returns its decrypted value and its Np
327 *
328 * @param[in] PemEncryptedFileName_ptr - public key file name
329 * @param[out] PemDecryted - N and Np buffer
330 */
331 /*********************************************************/
SBU_GetNAndNpFromPubKey(char * PemEncryptedFileName_ptr,char * PemDecryted)332 SBUEXPORT_C int SBU_GetNAndNpFromPubKey(char* PemEncryptedFileName_ptr, char *PemDecryted)
333 {
334 int rc = 0;
335 int nAndNpSize = SB_CERT_RSA_KEY_SIZE_IN_BYTES+NP_SIZE_IN_BYTES;
336
337 OpenSSL_add_all_algorithms ();
338
339 /* get N and Np buffer */
340 rc = CC_CommonGetNAndNpFromPubKey(PemEncryptedFileName_ptr, PemDecryted, &nAndNpSize);
341 if (rc != 0) {
342 printf( "failed to CC_CommonGetNAndNpFromPubKey %d or ilegal size %d\n", rc, nAndNpSize);
343 }
344
345 EVP_cleanup();
346 CRYPTO_cleanup_all_ex_data(); /* cleanup application specific data to avoid memory leaks.*/
347
348 return rc;
349 }
350
351
352 /**
353 * @brief Reads RSA public key from the file and returns its raw value and its Np
354 *
355 * @param[in] pPemFileName_ptr - file name
356 * @param[out] pNAndNp - N and Np buffer
357 */
358 /*********************************************************/
SBU_GetHashOfNAndNpFromPubKey(char * pPemFileName_ptr,char * pHash,int hashSize)359 SBUEXPORT_C int SBU_GetHashOfNAndNpFromPubKey(char* pPemFileName_ptr, char *pHash, int hashSize)
360 {
361 int rc = 0;
362
363 OpenSSL_add_all_algorithms ();
364
365 rc = CC_CommonCalcHBKFromFile(pPemFileName_ptr, pHash, hashSize);
366 if (rc != 0) {
367 printf( "failed to CC_CommonCalcHBKFromFile %d or ilegal size %d\n", rc, hashSize);
368 }
369
370 EVP_cleanup();
371 CRYPTO_cleanup_all_ex_data(); /* cleanup application specific data to avoid memory leaks.*/
372
373 return rc;
374 }
375
376