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