Merge "Fix for SATIZENVUL-1655 & SATIZENVUL-1656 - error handling" into tizen
[platform/core/account/fido-asm.git] / common / cryptoutil / src / AsmCrypto.cpp
1
2 #include "asmcrypto.h"
3 #include <string>
4 #include <stdio.h>
5 #include <net_connection.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <vector>
11 #include "AsmHelper.h"
12 #include <openssl/sha.h>
13 #include <openssl/evp.h>
14 #include <openssl/rsa.h>
15 #include <openssl/pem.h>
16 #include <openssl/bio.h>
17 #include <openssl/err.h>
18 #include <openssl/rand.h>
19 #include <openssl/bio.h>
20 #include <openssl/aes.h>
21 #include <bluetooth.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <time.h>
25
26 #define ASM_CONFIG_FILE "/opt/usr/data/.asm.config"
27 #define FIDO_CLIENT_CALLER_ID "org.tizen.fido"
28 #define LOG_FILE_PATH "/tmp/"
29 #define uid 5001
30
31 #define EVP_SUCCESS 1
32 #define EVP_FAIL 0
33
34 typedef struct __der_cert {
35         unsigned char* raw_cert;
36         size_t cert_size;
37 } _der_cert_s;
38
39 void
40 AsmCrypto::logDataToFile(const char *file_name_prefix, const char *data, int data_len)
41 {
42         char fn[128] = {0, };
43         char *realpath_res = NULL;
44         snprintf(fn, 127, "%s%s", LOG_FILE_PATH, file_name_prefix);
45
46         realpath_res = realpath(fn, NULL);
47         if (realpath_res == NULL) {
48                 _ERR("realpath error");
49                 SAFE_DELETE(realpath_res);
50                 return;
51         }
52         FILE *fp = fopen(fn, "w+");
53         if (fp == NULL) {
54                 SAFE_DELETE(realpath_res);
55                 return;
56         }
57
58         int num = fwrite(data, sizeof(char), data_len, fp);
59
60         _INFO("[%d] bytes logged in [%s]", num, fn);
61
62         fclose(fp);
63         SAFE_DELETE(realpath_res);
64 }
65
66 void
67 AsmCrypto::logRawDataToFile(const char *file_name_prefix, const unsigned char *data, int data_len)
68 {
69         char fn[128] = {0, };
70         char *realpath_res = NULL;
71         snprintf(fn, 127, "%s%s", LOG_FILE_PATH, file_name_prefix);
72
73         realpath_res = realpath(fn, NULL);
74         if (realpath_res == NULL) {
75                 _ERR("realpath error");
76                 SAFE_DELETE(realpath_res);
77                 return;
78         }
79
80         FILE *fp = fopen(fn, "w+");
81         if (fp == NULL) {
82                 SAFE_DELETE(realpath_res);
83                 return;
84         }
85
86         int num = fwrite(data, sizeof(unsigned char), data_len, fp);
87
88         _INFO("[%d] bytes logged in [%s]", num, fn);
89
90         fclose(fp);
91         SAFE_DELETE(realpath_res);
92 }
93
94 static int
95 __der_cert_new(unsigned char *raw_cert, size_t cert_size, _der_cert_s **ppcert)
96 {
97         _INFO("__der_cert_new start");
98
99         _der_cert_s *pcert;
100
101         if (raw_cert == NULL || cert_size <= 0 || ppcert == NULL)
102                 return -1;
103
104         pcert = static_cast<_der_cert_s*>(malloc(sizeof(_der_cert_s)));
105         if (pcert == NULL)
106                 return -1;
107
108         pcert->raw_cert = reinterpret_cast<unsigned char*>(malloc(cert_size));
109         if (pcert->raw_cert == NULL) {
110                 free(pcert);
111                 return -1;
112         }
113         memcpy(pcert->raw_cert, raw_cert, cert_size);
114
115         pcert->cert_size = cert_size;
116
117         *ppcert = pcert;
118
119         _INFO("__der_cert_new end");
120         return 0;
121 }
122
123 static int
124 __load_cert_from_x509(X509 *xCert, _der_cert_s **cert)
125 {
126          _INFO("__load_cert_from_x509 start");
127
128         if (xCert == NULL)
129                 return -1;
130
131         BIO *bcert = BIO_new(BIO_s_mem());
132
133         i2d_X509_bio(bcert, xCert);
134
135         std::vector<unsigned char> output(8196);
136         int size = BIO_read(bcert, output.data(), output.size());
137         BIO_free_all(bcert);
138         if (size <= 0) {
139                 return -1;
140         }
141         output.resize(size);
142
143         return __der_cert_new(output.data(), output.size(), cert);
144 }
145
146 std::string
147 AsmCrypto::getDeviceId(void)
148 {
149         /*Find IoTCon logic to get device id*/
150         return getAsmToken();
151 }
152
153 /*TODO revisit*/
154 std::string
155 AsmCrypto::getAsmToken(void)
156 {
157         _BEGIN;
158
159         static char *asmTok = NULL;
160         if (asmTok != NULL)
161                 return asmTok;
162
163         char *mac = NULL;
164
165         bt_initialize();
166         bt_adapter_state_e btState;
167         bt_adapter_get_state(&btState);
168         if (btState == BT_ADAPTER_ENABLED) {
169                 bt_adapter_get_address(&mac);
170                 if (mac != NULL) {
171                         char *macClone = _SAFE_DUP(mac);
172                         _INFO("%s", macClone);
173                         std::string macStr(macClone);
174                         _INFO("%s", macStr.c_str());
175                         asmTok = strdup(macClone);
176                         SAFE_DELETE(macClone);
177                         SAFE_DELETE(mac);
178                         bt_deinitialize();
179                         return macStr;
180                 }
181         } else {
182                 /*TODO*/
183                 _ERR("Failed to get any NW ID, using rand");
184                 time_t t;
185                 srand((unsigned) time(&t));
186                 mac = (char*)calloc(128, sizeof(char));
187                 snprintf(mac, 128 - 1, "%d", (AsmCrypto::genRandomInt()%1000 + 1));
188
189                 char *macClone = _SAFE_DUP(mac);
190                 _INFO("%s", macClone);
191                 std::string macStr(macClone);
192                 _INFO("%s", macStr.c_str());
193                 asmTok = strdup(macClone);
194                 SAFE_DELETE(macClone);
195                 SAFE_DELETE(mac);
196                 bt_deinitialize();
197                 return macStr;
198         }
199
200         char *realpath_res = NULL;
201
202         realpath_res = realpath(ASM_CONFIG_FILE, NULL);
203         if (realpath_res == NULL) {
204                 _ERR("realpath error");
205                 SAFE_DELETE(realpath_res);
206                 return std::string();
207         }
208
209         FILE *file = fopen(ASM_CONFIG_FILE, "r");
210
211         if (file == NULL) {
212                 _INFO("AsmCrypto::getAsmToken:: asm_config file is NULL");
213
214                 connection_h conn = NULL;
215                 connection_create(&conn);
216
217                 char *mac = NULL;
218
219                 /*Try: Ethernet*/
220                 int ret = connection_get_mac_address(conn, CONNECTION_TYPE_ETHERNET, &mac);
221
222                 /*Try: Wifi*/
223                 if (ret != CONNECTION_ERROR_NONE)
224                         ret = connection_get_mac_address(conn, CONNECTION_TYPE_WIFI, &mac);
225
226                 /*Try: BT*/
227                 if (ret != CONNECTION_ERROR_NONE)
228                         ret = connection_get_mac_address(conn, CONNECTION_TYPE_BT, &mac);
229
230                 if (ret != CONNECTION_ERROR_NONE) {
231                         _ERR("Failed to get any NW ID, using rand");
232                         time_t t;
233                         srand((unsigned) time(&t));
234                         mac = (char*)calloc(128, sizeof(char));
235                         snprintf(mac, 128 - 1, "%d", (genRandomInt()%1000 + 1));
236                 }
237                 file = fopen(ASM_CONFIG_FILE, "w+");
238                 if (file != NULL) {
239                         fwrite(mac, sizeof(char), strlen(mac), file);
240                         fclose(file);
241                 }
242
243                 std::string tok(mac, strlen(mac));
244                 _END;
245                 asmTok = strdup(mac);
246                 SAFE_DELETE(mac);
247
248                 bt_deinitialize();
249                 SAFE_DELETE(realpath_res);
250                 return tok;
251         } else {
252                 fseek(file, 0, SEEK_END);
253                 long size = ftell(file);
254                 if (size <= 0) {
255                         fclose(file);
256                         _END;
257
258                         bt_deinitialize();
259                         SAFE_DELETE(realpath_res);
260                         return std::string();
261                 } else if (size > 1000) {
262                         _ERR("Too big config file, size=[%d], allowed=[1000]", (int)size);
263                         fclose(file);
264                         _END;
265
266                         bt_deinitialize();
267                         SAFE_DELETE(realpath_res);
268                         return std::string();
269                 }
270
271                 fseek(file, 0, SEEK_SET);
272
273                 char *config = (char*)(calloc(1, size + 1));
274                 int num_bytes = fread(config, size, 1, file);
275                 if (num_bytes <= 0) {
276                         free(config);
277                         fclose(file);
278                         _END;
279
280                         bt_deinitialize();
281                         SAFE_DELETE(realpath_res);
282                         return std::string();
283                 }
284
285                 config[size] = '\0';
286
287                 fclose(file);
288
289                 std::string tok(config, strlen(config));
290                 _END;
291                 asmTok = strdup(config);
292                 SAFE_DELETE(config);
293
294                 SAFE_DELETE(realpath_res);
295                 return tok;
296         }
297 }
298
299 std::string
300 AsmCrypto::getKHAccessToken(std::string appId, bool isBound)
301 {
302         _BEGIN;
303         std::string khA(appId);
304
305         if (isBound == true) {
306                 khA += getAsmToken();
307                 /*TODO: Replace with TLM/GUMD APIs to get the logged-in user id*/
308                 /*khA += getuid();*/
309                 khA += FIDO_CLIENT_CALLER_ID;
310         }
311
312         _INFO("AsmCrypto::getKHAccessToken:: KHA = [%s]", khA.c_str());
313
314         _END;
315         return khA;
316 }
317
318 int
319 AsmCrypto::genRandom(unsigned char *random, int num)
320 {
321         int ret;
322         ret = RAND_bytes(random, num);
323         if (ret != -1)
324                 return 0;
325         else
326                 return -1;
327 }
328
329 bool
330 AsmCrypto::genHash256(const void* input, unsigned long length, unsigned char* md)
331 {
332         SHA256_CTX context;
333         if (!SHA256_Init(&context))
334                 return false;
335
336         if (!SHA256_Update(&context, (unsigned char*)input, length))
337                 return false;
338
339         if (!SHA256_Final(md, &context))
340                 return false;
341
342         return true;
343 }
344
345 int
346 AsmCrypto::genRSAKeyPair(char *pubkey, char *prikey, const char *passwd, int keysize)
347 {
348         return -1;
349 }
350
351 int
352 AsmCrypto::genRSASignValue(const char *privkey, const char * passwd, const unsigned char * msg, unsigned int len, unsigned char *sign, unsigned int *signlen)
353 {
354         return -1;
355 }
356
357 int
358 AsmCrypto::genB64Encode(const unsigned char *input, int inlen, unsigned char * output, int *outlen)
359 {
360         BIO * bmem = NULL;
361         BIO * b64 = NULL;
362         BUF_MEM * bptr = NULL;
363         b64 = BIO_new(BIO_f_base64());
364         if (b64 == NULL) {
365                 _ERR("BIO_new failed \n");
366                 return -1;
367         }
368         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
369
370         bmem = BIO_new(BIO_s_mem());
371         b64 = BIO_push(b64, bmem);
372         BIO_write(b64, input, inlen);
373         BIO_flush(b64);
374         BIO_get_mem_ptr(b64, &bptr);
375
376         memcpy(output, bptr->data, bptr->length);
377         output[bptr->length] = 0;
378         *outlen = bptr->length;
379         if (b64)
380                 BIO_free_all(b64);
381
382         for (int i =0; i < *outlen ; i++) {
383                 if (output[i] == '+') {
384                         output[i] = '-';
385                 } else if (output[i] == '/') {
386                         output[i] = '_';
387                 } else if (output[i] == '=') {
388                         *outlen = i ;
389                         output[i] = '\0';
390                         break;
391                 }
392         }
393
394         _INFO("AsmCrypto::genB64Encode:: outlen = [%d]", *outlen);
395         return 0;
396 }
397
398 int
399 AsmCrypto::genB64Decodes(const unsigned char *input, int inlen, unsigned char * output, int *outlen)
400 {
401         _INFO("GenBase64Decode start");
402
403         _INFO("%s", input);
404         _INFO("input len = %d", inlen);
405
406         int npadChars = (inlen %4) == 0 ? 0 : (4 - (inlen%4));
407         unsigned char *base64 = (unsigned char *) malloc(inlen + npadChars);
408         if (base64 == NULL)
409         {
410                 _ERR("malloc failed \n");
411                 return -1;
412         }
413         memcpy(base64, input, inlen);
414         for (int i =0; i < inlen ; i++)
415         {
416                 if (base64[i] == '-') {
417                         base64[i] = '+';
418                 } else if (base64[i] == '_') {
419                         base64[i] = '/';
420                 }
421         }
422         if (npadChars != 0)
423         {
424                 memset(base64 + inlen, '=', npadChars);
425         }
426         //printf("in 2 is :%s. %d\n",base64, inlen);
427
428         BIO * b64 = NULL;
429         BIO * bmem = NULL;
430         b64 = BIO_new(BIO_f_base64());
431         if (b64 == NULL)
432         {
433                 free(base64);
434                 _ERR("BIO_new failed");
435                 return -1;
436         }
437         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
438         bmem = BIO_new_mem_buf(base64, inlen + npadChars);
439         if (bmem == NULL)
440         {
441                 _ERR("BIO_new_mem_buf failed");
442                 BIO_free(b64);
443                 free(base64);
444                 return -1;
445         }
446         bmem = BIO_push(b64, bmem);
447         *outlen = BIO_read(bmem, output, inlen + npadChars);
448         if (*outlen <=0)
449         {
450                 BIO_free(b64);
451                 free(base64);
452                 _ERR("BIO_read failed. size or data error");
453                 return -1;
454         }
455         if (b64) {
456                 BIO_free_all(b64);
457         }
458
459         SAFE_DELETE(base64);
460
461         _INFO("%s", output);
462         _INFO("outlen len = %d", *outlen);
463
464         return 0;
465 }
466
467 int
468 AsmCrypto::aesEncrypt(const unsigned char *plaintext, int plaintext_len, const unsigned char *key,
469                                                                          const unsigned char *iv, unsigned char *ciphertext)
470 {
471         EVP_CIPHER_CTX *ctx;
472
473         int len;
474
475         int ciphertext_len;
476
477
478         if (!(ctx = EVP_CIPHER_CTX_new()))
479         {
480           _ERR("EVP_CIPHER_CTX_new() failed");
481           return -1;
482         }
483
484         if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
485         {
486           _ERR("EVP_EncryptInit_ex() failed");
487           return -1;
488         }
489
490         if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
491         {
492           _ERR("EVP_EncryptUpdate() failed");
493           return -1;
494         }
495
496         ciphertext_len = len;
497
498         if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
499         {
500           _ERR("EVP_EncryptFinal_ex() failed");
501           return -1;
502         }
503
504         ciphertext_len += len;
505
506         EVP_CIPHER_CTX_free(ctx);
507
508         return ciphertext_len;
509 }
510
511 int
512 AsmCrypto::aesDecrypt(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key,
513                                                                          const unsigned char *iv, unsigned char *plaintext)
514 {
515         _BEGIN;
516
517         EVP_CIPHER_CTX *ctx;
518
519         int len;
520
521         int plaintext_len;
522
523         if (!(ctx = EVP_CIPHER_CTX_new()))
524         {
525           _ERR("EVP_CIPHER_CTX_new() failed");
526           return -1;
527         }
528
529         if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
530         {
531           _ERR("EVP_DecryptInit_ex() failed");
532           return -1;
533         }
534
535         if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
536         {
537           _ERR("EVP_DecryptUpdate() failed");
538           return -1;
539         }
540
541         plaintext_len = len;
542
543         if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
544         {
545           _ERR("EVP_DecryptFinal_ex() failed");
546           return -1;
547         }
548
549         plaintext_len += len;
550
551         EVP_CIPHER_CTX_free(ctx);
552
553         _END;
554         return plaintext_len;
555 }
556
557 int
558 AsmCrypto::createRSAKeyPair(int ksz, char **pubkey, int *pubkey_len, char **prikey, int *prikey_len)
559 {
560         _INFO("Modified CreateRSAKeyPair start");
561
562         EVP_PKEY_CTX *pctx = NULL;
563         EVP_PKEY *pkey = NULL;
564         RSA *rsa;
565
566         pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
567         if (!pctx)
568                 return -1;
569
570         _INFO("After EVP_PKEY_CTX_new_id");
571
572         if (EVP_PKEY_keygen_init(pctx) <= 0) {
573                 if (pctx) {
574                         EVP_PKEY_CTX_free(pctx);
575                 }
576                 _ERR(" Error in EVP_PKEY_keygen_init");
577         }
578         _INFO("After EVP_PKEY_keygen_init");
579         EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, ksz);
580
581         _INFO("After EVP_PKEY_CTX_set_rsa_keygen_bits");
582
583         if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
584                 if (pctx) {
585                         EVP_PKEY_CTX_free(pctx);
586                 }
587                 _ERR(" Error in EVP_PKEY_keygen");
588         }
589         _INFO("After EVP_PKEY_keygen");
590
591         rsa = EVP_PKEY_get1_RSA(pkey);
592         _INFO("After EVP_PKEY_get1_RSA");
593
594
595         /*Private Key*/
596         BIO *bio_priv = BIO_new(BIO_s_mem());
597         PEM_write_bio_RSAPrivateKey(bio_priv, rsa, NULL, NULL, 0, NULL, NULL);
598         int keylen_priv = BIO_pending(bio_priv);
599         char *pem_key_priv = (char *)calloc(keylen_priv + 1, 1); /* Null-terminate */
600         BIO_read(bio_priv, pem_key_priv, keylen_priv);
601         _INFO("After Private key");
602
603         /*Public Key*/
604         BIO *bio_pub = BIO_new(BIO_s_mem());
605         PEM_write_bio_RSAPublicKey(bio_pub, rsa);
606
607         int keylen_pub = BIO_pending(bio_pub);
608         char *pem_key_pub = (char *)calloc(keylen_pub + 1, 1); /* Null-terminate */
609         BIO_read(bio_pub, pem_key_pub, keylen_pub);
610         _INFO("After Public key");
611
612         *pubkey = pem_key_pub;
613         *prikey = pem_key_priv;
614
615         *pubkey_len = keylen_pub;
616         *prikey_len = keylen_priv;
617
618         _INFO("CreateRSAKeyPair end");
619
620         return 0;
621 }
622
623 unsigned char*
624 AsmCrypto::readDer(const char *der_file_name, int *len)
625 {
626         _INFO("ReadDERCertFile start");
627
628         FILE *fp = fopen(der_file_name, "r");
629         if (fp == NULL)
630                 return NULL;
631
632         X509 *pcert = NULL;
633         pcert = d2i_X509_fp(fp, NULL);
634         fclose(fp);
635
636         if (pcert == NULL)
637                 return NULL;
638
639         _der_cert_s *cert = (_der_cert_s*)(calloc(1, sizeof(_der_cert_s)));
640
641         int ret = __load_cert_from_x509(pcert, &cert);
642         if (ret != 0) {
643                 SAFE_DELETE(cert);
644                 return NULL;
645         }
646
647         *len = cert->cert_size;
648
649         _INFO("ReadDERCertFile end");
650
651         unsigned char *rawCert = cert->raw_cert;
652         SAFE_DELETE(cert);
653
654         return rawCert;
655 }
656
657
658
659 unsigned char*
660 AsmCrypto::ToBase64Url(const unsigned char *input, int inputLen)
661 {
662         _BEGIN;
663         if (input == NULL)
664                 return NULL;
665
666         int inputSz = inputLen; //input.size();
667
668         _INFO("AsmCrypto::ToBase64Url::input size = [%d]", inputSz);
669
670         unsigned char* output = NULL;
671         //MALLOC(output, unsigned char, inputSz*1.5);
672
673         output = (unsigned char*)calloc(1, inputSz*1.5);
674
675         int outputSz = 0;
676
677         if (0 != AsmCrypto::genB64Encode(input,
678                                                                                 inputSz,
679                                                                                 output,
680                                                                                 &outputSz))
681         {
682                 _ERR("Failed to encode base64.");
683                 free(output);
684                 return (unsigned char *)strdup("");
685         }
686
687         _INFO("AsmCrypto::ToBase64Url::output size = [%d]", outputSz);
688         _INFO("AsmCrypto::ToBase64Url::output = [%s]", output);
689
690         _END;
691         return output;
692 }
693
694 unsigned char*
695 AsmCrypto::FromBase64Url(const unsigned char *input, int inputLen)
696 {
697         _BEGIN;
698
699         int inputSz = inputLen;
700         unsigned char* output = NULL;
701
702         output = (unsigned char*)calloc(1, inputSz*1.5);
703         int outputSz = 0;
704
705         if (0 != AsmCrypto::genB64Decodes(input,
706                                                                                 inputSz,
707                                                                                 output,
708                                                                                 &outputSz))
709         {
710                 _ERR("Failed to decode base64.");
711                 free(output);
712                 return (unsigned char*)"";
713         }
714
715         _END;
716         return output;
717 }
718
719 #define RSA_MAX_MES_LENGTH      128
720 #define RSA_MAX_SIGN_SIZE       512
721 #define RSA_MAX_BITS            4096
722 #define RSA_MAX_DGST_SIZE       64
723
724 void hex2bin(const char *str, int str_len, void *mem)
725 {
726         int i;
727         int len = str_len;
728         char byte[3];
729         char *M = (char *) mem;
730         byte[2] = 0;
731
732         for (i = 0; i < len; i+=2)
733         {
734                 byte[0] = str[i];
735                 byte[1] = str[i+1];
736                 M[i/2] = strtoul(byte, NULL, 16);
737         }
738 }
739
740 int
741 AsmCrypto::digestSignRSAPSSMGF1(const char *message, int m_len,
742                                                                   const char *privKeyFile, const char *pwd,
743                                                                   unsigned char **signature, int *sig_len)
744 {
745         OpenSSL_add_all_algorithms();
746
747         FILE *fp;
748         EVP_PKEY *privKey = NULL;
749
750         fp = fopen(privKeyFile, "r");
751         if (fp == NULL)
752         {
753                 _ERR("Failed to open private key file");
754                 return -1;
755         }
756
757         privKey = PEM_read_PrivateKey(fp, &privKey, NULL, (void *)pwd);
758
759         fclose(fp);
760
761         if (privKey == NULL) {
762                 _ERR("PEM_read_PrivateKey failed");
763                 return -1;
764         }
765
766         EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
767
768         EVP_PKEY_CTX *pctx = NULL;
769
770         // Create the Message Digest Context
771
772         if (EVP_SUCCESS != EVP_DigestSignInit(mdctx, &pctx, EVP_sha256(), NULL, privKey)) {
773                  _ERR("EVP_DigestSignInit failed");
774                  return -1;
775         }
776
777         /* Set padding algorithm */
778         if (EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) {
779                 _ERR("EVP_PKEY_CTX_set_rsa_padding failed");
780                 return -1;
781         }
782         if (EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, 32)) {
783                 _ERR("EVP_PKEY_CTX_set_rsa_pss_saltlen failed");
784                 return -1;
785         }
786         _INFO("After EVP_PKEY_CTX_set_rsa_pss_saltlen with 32");
787
788         /* Set masking */
789         if (EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, EVP_sha256())) {
790                 _ERR("EVP_PKEY_CTX_set_rsa_padding failed");
791                 return -1;
792         }
793
794         /* Call update with the message */
795         if (EVP_SUCCESS != EVP_DigestSignUpdate(mdctx, message, m_len)) {
796                  _ERR("EVP_DigestSignUpdate failed");
797                  return -1;
798         }
799
800         /* Finalize the DigestSign operation */
801         /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
802         * signature. Length is returned in slen */
803         size_t slen;
804         if (EVP_SUCCESS != EVP_DigestSignFinal(mdctx, NULL, &slen)) {
805                  _ERR("EVP_DigestSignFinal failed");
806                  return -1;
807         }
808
809         /* Allocate memory for the signature based on size in slen */
810         unsigned char *sig = (unsigned char *)calloc(1, slen);
811         //int slen = 0;
812
813         /* Obtain the signature */
814         if (EVP_SUCCESS != EVP_DigestSignFinal(mdctx, sig, &slen)) {
815                  _ERR("EVP_DigestSignFinal failed");
816                  SAFE_DELETE(sig);
817                  return -1;
818         }
819
820         *signature = sig;
821         *sig_len = slen;
822         return 0;
823 }
824
825 typedef struct _certHandle
826 {
827         char *b64_hash_pubKey;
828         char *pkgId;
829 } certHandle;
830
831 static char*
832 __b64_encode(unsigned char *input, int ip_len)
833 {
834         RET_IF_FAIL(input != NULL, NULL);
835         RET_IF_FAIL(ip_len > 0, NULL);
836
837         unsigned char *output = (unsigned char*)calloc(ip_len * 1.5, sizeof(char));
838
839         BIO *bmem = NULL;
840         BIO *b64 = NULL;
841         BUF_MEM *bptr = NULL;
842         b64 = BIO_new(BIO_f_base64());
843         if (b64 == NULL) {
844                 _ERR("BIO_new failed \n");
845                 free(output);
846                 return NULL;
847         }
848
849         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
850
851         bmem = BIO_new(BIO_s_mem());
852         b64 = BIO_push(b64, bmem);
853         BIO_write(b64, input, ip_len);
854         BIO_flush(b64);
855         BIO_get_mem_ptr(b64, &bptr);
856
857         memcpy(output, bptr->data, bptr->length);
858         output[bptr->length] = 0;
859
860         if (b64)
861                 BIO_free_all(b64);
862
863         return (char*)output;
864 }
865
866 static int
867 __b64_decode(const char *encoded_data, int encoded_size, unsigned char **decoded_data, int *decoded_size)
868 {
869         RET_IF_FAIL(encoded_data != NULL, -1);
870
871         //_INFO("%s", encoded_data);
872
873         int len = 0;
874         *decoded_size = encoded_size;
875
876         (*decoded_data) = (unsigned char *) calloc((*decoded_size) * 1.5, sizeof(char));
877
878         BIO *bmem = BIO_new_mem_buf((void *) encoded_data, (*decoded_size));
879
880         BIO *bioCmd = BIO_new(BIO_f_base64());
881
882         BIO_set_flags(bioCmd, BIO_FLAGS_BASE64_NO_NL);
883
884         bmem = BIO_push(bioCmd, bmem);
885
886         len = BIO_read(bmem, (void *) (*decoded_data), (*decoded_size));
887         _INFO("%d", len);
888
889         *decoded_size = len;
890
891         BIO_free_all(bmem);
892
893         _INFO("");
894
895         return 0;
896 }
897
898 static char*
899 __get_pub_key_from_cert(const char *cert_b64)
900 {
901         RET_IF_FAIL(cert_b64 != NULL, NULL);
902
903         unsigned char pubkey_der_digest[SHA256_DIGEST_LENGTH] = {0, };
904
905         unsigned char* cert_raw = NULL;//calloc(strlen(cert_b64) * 1.5, sizeof(char));
906
907         int cert_raw_len = 0;
908
909         int ret = __b64_decode(cert_b64, strlen(cert_b64), &cert_raw, &cert_raw_len);
910         if (ret != 0) {
911                 _ERR("__b64_decode failed");
912                 free(cert_raw);
913
914                 return NULL;
915         }
916
917         X509 *x509 = d2i_X509(NULL, (const unsigned char **)(&cert_raw), cert_raw_len);
918         if (x509 == NULL) {
919                 _ERR("d2i_X509 failed");
920                 free(cert_raw);
921                 return NULL;
922         }
923
924         int der_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
925         if (der_len <= 0) {
926                 _ERR("i2d_X509_PUBKEY failed");
927                 free(cert_raw);
928                 return NULL;
929         }
930
931         unsigned char* der_pubkey  = NULL;
932
933         unsigned char* der_pubkey_temp = NULL;
934
935         int hashed_len = 0;
936
937         der_pubkey_temp = der_pubkey = (unsigned char*)OPENSSL_malloc(der_len);
938         if (der_pubkey_temp == NULL || der_pubkey == NULL) {
939                 _ERR("OPENSSL_malloc failed for der_pubkey");
940                 free(cert_raw);
941                 return NULL;
942         }
943
944         i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), (unsigned char **)&der_pubkey_temp);
945
946         ret = EVP_Digest(der_pubkey, der_len, pubkey_der_digest, (unsigned int*)&hashed_len, EVP_sha256(), NULL);
947
948         if (ret != 1) {
949                 _ERR("EVP_Digest failed");
950                 OPENSSL_free(der_pubkey);
951
952                 return NULL;
953         }
954
955         char *pub_key =  __b64_encode(pubkey_der_digest, (int)hashed_len);
956
957         OPENSSL_free(der_pubkey);
958
959         return pub_key;
960 }
961
962 int
963 AsmCrypto::onPkgList(pkgmgrinfo_pkginfo_h handle, void *user_data)
964 {
965         certHandle *certInfo = (certHandle*)user_data;
966         RET_IF_FAIL(certInfo != NULL, 0);
967
968         char *b64_hash_pubkey = NULL;
969         char *pkgid = NULL;
970         b64_hash_pubkey = certInfo->b64_hash_pubKey;
971
972         int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
973         if (ret != PMINFO_R_OK) {
974                 _ERR("pkgmgrinfo_pkginfo_get_pkgid failed [%d]", ret);
975                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
976                 return 0;
977         }
978
979         _INFO("pkgmgrinfo_pkginfo_get_pkgid success");
980
981         pkgmgrinfo_certinfo_h cert_handle = NULL;
982         const char *author_cert = NULL;
983         ret = pkgmgrinfo_pkginfo_create_certinfo(&cert_handle);
984         if (ret != PMINFO_R_OK) {
985                 _ERR("");
986                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
987                 return 0;
988         }
989
990         _INFO("pkgmgrinfo_pkginfo_create_certinfo success");
991
992         /*TODO implement getUid function*/
993         ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid, cert_handle, uid);
994
995
996         if (ret != PMINFO_R_OK) {
997                 _ERR("");
998                 pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
999                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1000                 return 0;
1001         }
1002
1003         _INFO("pkgmgrinfo_pkginfo_load_certinfo success");
1004
1005         ret = pkgmgrinfo_pkginfo_get_cert_value(cert_handle, PMINFO_AUTHOR_SIGNER_CERT, &author_cert);
1006         if (ret != PMINFO_R_OK) {
1007                 pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
1008                 _ERR("");
1009                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1010                 return 0;
1011         }
1012
1013         /*_INFO("Author Root Cert=%s", author_cert);*/
1014
1015         _INFO("pkgmgrinfo_pkginfo_get_cert_value success");
1016
1017         char *author_cert_hash = NULL;
1018         char *tz_facet_id = NULL;
1019         int tz_facet_id_max_len = -1;
1020
1021
1022         author_cert_hash = __get_pub_key_from_cert(author_cert);
1023         _INFO("");
1024         if (author_cert_hash == NULL) {
1025                 pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
1026                 return 0;
1027         }
1028
1029         tz_facet_id_max_len = strlen(author_cert_hash) + 128;
1030         tz_facet_id = (char*)(calloc(1, tz_facet_id_max_len));
1031         snprintf(tz_facet_id, tz_facet_id_max_len - 1, "%s:%s", "tizen:pkg-key-hash",
1032                          author_cert_hash);
1033         _INFO("");
1034         if (strcmp(b64_hash_pubkey, tz_facet_id) == 0) {
1035                 _INFO("[%s]", pkgid);
1036                 certInfo->pkgId = _SAFE_DUP(pkgid);
1037                 _INFO("return");
1038
1039                 pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
1040                 /*pkgmgrinfo_pkginfo_destroy_pkginfo(handle);*/
1041
1042                 SAFE_DELETE(tz_facet_id);
1043                 SAFE_DELETE(author_cert_hash);
1044                 return -1;
1045         } else {
1046                 pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
1047                 SAFE_DELETE(tz_facet_id);
1048                 SAFE_DELETE(author_cert_hash);
1049                 return 0;
1050         }
1051         /*_INFO("Before return");
1052         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1053         _INFO("");*/
1054 }
1055
1056 char*
1057 AsmCrypto::getAppId(const char *appIdPubKey)
1058 {
1059         int ret = -1;
1060
1061         certHandle *certInfo = (certHandle*)calloc(1, sizeof(certHandle));
1062         certInfo->b64_hash_pubKey = _SAFE_DUP(appIdPubKey);
1063
1064         /*TODO implement getUid function*/
1065         _INFO("");
1066         ret = pkgmgrinfo_pkginfo_get_list(AsmCrypto::onPkgList, (void *)certInfo);
1067         if (ret != PMINFO_R_OK) {
1068                 SAFE_DELETE(certInfo->b64_hash_pubKey);
1069                 SAFE_DELETE(certInfo);
1070                 _ERR("");
1071                 return NULL;
1072         }
1073
1074         if (certInfo->pkgId != NULL) {
1075                 _INFO("AsmCrypto::getAppId:: pkgId = [%s]", certInfo->pkgId);
1076         } else {
1077                 _INFO("AsmCrypto::getAppId:: pkgId NULL");
1078                 /*TODO For requests coming from remote device, we can not use pkgmgr to
1079                 * find out App-Id, instead Client Device's ASM must send it explicitly
1080                 */
1081                 char *appIdRemote = (char*)calloc(128, sizeof(char));
1082                 snprintf(appIdRemote, 127, "%s", "Remote Device");
1083                 return appIdRemote;
1084         }
1085         return certInfo->pkgId;
1086 }
1087
1088 unsigned char*
1089 AsmCrypto::fidoSignWithKey(const unsigned char *msg, int msg_len,
1090                                                                                   const unsigned char *private_key,
1091                                                    int priv_key_len, int *sig_len)
1092 {
1093         _INFO("fidoSignWithKey start");
1094         OpenSSL_add_all_algorithms();
1095
1096         _INFO("FIDO MGF1 PSS padding:");
1097
1098         BIO *bio = NULL;
1099         RSA *rsa = NULL;
1100
1101         _INFO("");
1102         bio = BIO_new_mem_buf((unsigned char *)private_key, priv_key_len);
1103         if (bio == NULL) {
1104                 _ERR("BIO_new_mem_buf failed");
1105                 return NULL;
1106         }
1107
1108         _INFO("");
1109         rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
1110         if (rsa == NULL) {
1111                 _ERR("BIO_new_mem_buf failed");
1112                 return NULL;
1113         }
1114
1115         _INFO("");
1116
1117         EVP_PKEY *pkey = EVP_PKEY_new();
1118
1119         _INFO("");
1120         int ret = EVP_PKEY_set1_RSA(pkey, rsa);
1121         _INFO("EVP_PKEY_set1_RSA = [%d]", ret);
1122         if (ret == 0) {
1123                 _ERR("EVP_PKEY_set1_RSA failed");
1124                 return NULL;
1125         }
1126
1127
1128
1129         EVP_MD_CTX *mdctx = NULL;
1130
1131         mdctx = EVP_MD_CTX_create();
1132         if (mdctx == NULL) {
1133                  _ERR("EVP_MD_CTX_create failed");
1134
1135                  return NULL;
1136         }
1137
1138         EVP_PKEY_CTX *pctx = NULL;
1139         ret = EVP_DigestSignInit(mdctx, &pctx, EVP_sha256(), NULL, pkey);
1140         _INFO("EVP_DigestSignInit=[%d]", ret);
1141
1142         ret = EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING);
1143         _INFO("EVP_PKEY_CTX_set_rsa_padding=[%d]", ret);
1144         EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, EVP_sha256());
1145         EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, 32);
1146
1147         EVP_DigestSignUpdate(mdctx, msg, msg_len);
1148
1149         size_t sig_len_loc = 0;
1150         EVP_DigestSignFinal(mdctx, NULL, &sig_len_loc);
1151
1152         unsigned char *sig = (unsigned char *)OPENSSL_malloc(sizeof(unsigned char) * (sig_len_loc));
1153         if (sig == NULL) {
1154                 _ERR("OPENSSL_malloc failed");
1155                 return NULL;
1156         }
1157
1158         EVP_DigestSignFinal(mdctx, sig, &sig_len_loc);
1159
1160         *sig_len = sig_len_loc;
1161         return sig;
1162 }
1163
1164 /*unsigned char*
1165 AsmCrypto::fidoSign(const unsigned char *msg, int msg_len, const char *private_key_file,
1166                                         const char *pwd, int *sig_len)
1167 {
1168         _INFO("SignWithPrivateKeyFile start [%s]", private_key_file);
1169         OpenSSL_add_all_algorithms();
1170
1171         FILE *fp;
1172         EVP_PKEY *pkey = NULL;
1173
1174         fp = fopen(private_key_file, "r");
1175         if (fp == NULL) {
1176                 _ERR("Failed to open private key file");
1177                 return NULL;
1178         }
1179
1180         pkey = PEM_read_PrivateKey(fp, &pkey, NULL, (void *)pwd);
1181
1182         fclose(fp);
1183
1184         if (pkey == NULL) {
1185                 return NULL;
1186         }
1187
1188         //RSA *pRsaKey = EVP_PKEY_get1_RSA(pkey);
1189
1190         _INFO("FIDO MGF1 PSS padding:");
1191
1192         EVP_MD_CTX *mdctx = NULL;
1193
1194         mdctx = EVP_MD_CTX_create();
1195         if (mdctx == NULL) {
1196                  _ERR("EVP_MD_CTX_create failed");
1197
1198                  return NULL;
1199         }
1200
1201         EVP_PKEY_CTX *pctx = NULL;
1202         int ret = EVP_DigestSignInit(mdctx, &pctx, EVP_sha256(), NULL, pkey);
1203         _INFO("EVP_DigestSignInit=[%d]", ret);
1204
1205         ret = EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING);
1206         _INFO("EVP_PKEY_CTX_set_rsa_padding=[%d]", ret);
1207         EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, EVP_sha256());
1208         EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, 32);
1209
1210         EVP_DigestSignUpdate(mdctx, msg, msg_len);
1211
1212         size_t sig_len_loc = 0;
1213         EVP_DigestSignFinal(mdctx, NULL, &sig_len_loc);
1214
1215         unsigned char *sig = (unsigned char *)OPENSSL_malloc(sizeof(unsigned char) * (sig_len_loc));
1216         if (sig == NULL) {
1217                 _ERR("OPENSSL_malloc failed");
1218                 return NULL;
1219         }
1220
1221         EVP_DigestSignFinal(mdctx, sig, &sig_len_loc);
1222
1223         *sig_len = sig_len_loc;
1224         return sig;
1225 }*/
1226
1227 int
1228 AsmCrypto::genRandomInt(void)
1229 {
1230         unsigned int seed = time(NULL);
1231         return rand_r(&seed);
1232 }