Add fixes for gcc 9
[platform/core/security/libcryptsvc.git] / srcs / SecCryptoSvc.c
1 /*
2  * libcryptsvc - device unique key
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <string.h>
23
24 #include <openssl/evp.h>
25 #include <openssl/err.h>
26 #include <openssl/rand.h>
27 #include <openssl/sha.h>
28
29 #include <dlog.h>
30
31 #include "SecCryptoSvc.h"
32
33 #define CS_API __attribute__((visibility("default")))
34
35 #define SYS_SECBOOT_DEV_ID_LEN  16
36 #define NAND_CID_NAME   "/sys/block/mmcblk0/device/cid"
37 #define NAND_CID_SIZE   32
38
39
40 #ifdef CRYPTOSVC_TARGET
41 static int __AsciiToHex(const char AsciiHexUpper, const char AsciiHexLower)
42 {
43         char hexReturn = 0;
44
45         //First convert upper hex ascii value
46         if (AsciiHexUpper >= '0' && AsciiHexUpper <= '9')
47                 hexReturn = (AsciiHexUpper - '0') * 16;
48         else if (AsciiHexUpper >= 'A' && AsciiHexUpper <= 'F')
49                 hexReturn = ((AsciiHexUpper - 'A') + 10) * 16;
50         else if (AsciiHexUpper >= 'a' && AsciiHexUpper <= 'f')
51                 hexReturn = ((AsciiHexUpper - 'a') + 10) * 16;
52
53         //Convert lower hex ascii value
54         if (AsciiHexLower >= '0' && AsciiHexLower <= '9')
55                 hexReturn = hexReturn + (AsciiHexLower - '0');
56         else if (AsciiHexLower >= 'A' && AsciiHexLower <= 'F')
57                 hexReturn = hexReturn + (AsciiHexLower - 'A') + 10;
58         else if (AsciiHexLower >= 'a' && AsciiHexLower <= 'f')
59                 hexReturn = hexReturn + (AsciiHexLower - 'a') + 10;
60
61         return hexReturn;
62 }
63
64 static bool OemNandInfoUID(unsigned char *pUID, int nBufferSize)
65 {
66         int fd = 0;
67         char szCID[NAND_CID_SIZE + 1] = {0,};
68         memset(pUID, 0x00, nBufferSize);
69         fd = open(NAND_CID_NAME, O_RDONLY);
70
71         if (fd < 0) {
72                 SLOGE("cid open error!");
73                 return false;
74         }
75
76         if (read(fd, szCID, NAND_CID_SIZE) == -1) {
77                 SLOGE("cid read fail!!");
78                 close(fd);
79                 return false;
80         }
81
82         //manufacturer_id
83         pUID[0] =  __AsciiToHex(szCID[0], szCID[1]);
84         //oem_id
85         pUID[4] =  __AsciiToHex(szCID[4], szCID[5]);
86         //prod_rev
87         pUID[8] =  __AsciiToHex(szCID[18], szCID[19]);
88         //serial
89         pUID[15] = __AsciiToHex(szCID[20], szCID[21]);
90         pUID[14] =  __AsciiToHex(szCID[22], szCID[23]);
91         pUID[13] = __AsciiToHex(szCID[24], szCID[25]);
92         pUID[12] =  __AsciiToHex(szCID[26], szCID[27]);
93         // random permutation
94         pUID[1] = __AsciiToHex(szCID[2], szCID[3]);
95         pUID[2] = __AsciiToHex(szCID[6], szCID[7]);
96         pUID[3] = __AsciiToHex(szCID[8], szCID[9]);
97         pUID[5] = __AsciiToHex(szCID[10], szCID[11]);
98         pUID[6] = __AsciiToHex(szCID[12], szCID[13]);
99         pUID[7] = __AsciiToHex(szCID[14], szCID[15]);
100         pUID[9] = __AsciiToHex(szCID[16], szCID[17]);
101         pUID[10] = __AsciiToHex(szCID[28], szCID[29]);
102         pUID[11] = __AsciiToHex(szCID[30], szCID[31]);
103         SLOGD(" UID : %8X %8X %8X %8X",
104                   *(int *)pUID,
105                   *(int *)(pUID + 4),
106                   *(int *)(pUID + 8),
107                   *(int *)(pUID + 12));
108         close(fd);
109         return true;
110 }
111
112 static void SysSecBootGetDeviceUniqueKey(unsigned char *pUniquekey)
113 {
114         if (!OemNandInfoUID(pUniquekey, SYS_SECBOOT_DEV_ID_LEN))
115                 memset(pUniquekey, 0x00, SYS_SECBOOT_DEV_ID_LEN);
116 }
117 #endif
118
119
120 CS_API
121 bool SecFrameGeneratePlatformUniqueKey(unsigned int uLen, unsigned char *pCek)
122 {
123         bool bResult = true;
124         unsigned int i = 0;
125         unsigned char Key[73] = {0};
126         unsigned char hashedValue[HASH_LEN] = {0};
127         int nTempLen = SEC_DUK_SIZE;
128         int nHashLen = 0;
129         int remain = 0;
130         unsigned char *result = NULL;
131 #ifdef CRYPTOSVC_TARGET
132         SysSecBootGetDeviceUniqueKey(Key);
133 #else
134         memset(Key, 0xFF, nTempLen);
135 #endif
136         memcpy(Key + nTempLen, SEC_FRAME_OSP_KEY, 9);
137         nTempLen += 9;
138         remain = uLen;
139
140         for (i = 0; i < uLen; i += HASH_LEN) {
141                 result = SHA256(Key, nTempLen, hashedValue);
142                 nHashLen = HASH_LEN;
143
144                 if (!result) {
145                         SLOGE("SecCryptoHash fail");
146                         bResult = false;
147                         goto ERR;
148                 }
149
150                 nTempLen = nHashLen;
151
152                 if (remain < HASH_LEN)
153                         memcpy(pCek + i, hashedValue, remain);
154                 else
155                         memcpy(pCek + i, hashedValue, nHashLen);
156
157                 remain -= HASH_LEN;
158                 memset(Key, 0, sizeof(Key));
159                 memcpy(Key, hashedValue, nHashLen);
160         }
161
162         SLOGD("SecFrameGeneratePlatformUniqueKey Success.");
163 ERR:
164         return bResult;
165 }
166
167 CS_API
168 char *Base64Encoding(const char *data, int size)
169 {
170         char *pEncodedBuf = NULL;
171         const char *pPointer = NULL;
172         const char *pLength = data + size - 1;
173         unsigned char pInput[3] = {0, 0, 0};
174         unsigned char poutput[4] = {0, 0, 0, 0};
175         int index = 0;
176         int loopCnt = 0;
177         int stringCnt = 0;
178         int sizeEncodedString = (4 * (size / 3)) + (size % 3 ? 4 : 0) + 1;
179
180         if (!(pEncodedBuf = (char *)calloc(sizeEncodedString, sizeof(char)))) {
181                 SLOGE("Failed to allocate memory");
182                 return NULL;
183         }
184
185         for (loopCnt = 0, pPointer = data; pPointer <= pLength; loopCnt++, pPointer++) {
186                 index = loopCnt % 3;
187                 pInput[index] = *pPointer;
188
189                 if (index == 2 || pPointer == pLength) {
190                         poutput[0] = ((pInput[0] & 0xFC) >> 2);
191                         poutput[1] = ((pInput[0] & 0x3) << 4) | ((pInput[1] & 0xF0) >> 4);
192                         poutput[2] = ((pInput[1] & 0xF) << 2) | ((pInput[2] & 0xC0) >> 6);
193                         poutput[3] = (pInput[2] & 0x3F);
194                         pEncodedBuf[stringCnt++] = Base64EncodingTable[poutput[0]];
195                         pEncodedBuf[stringCnt++] = Base64EncodingTable[poutput[1]];
196                         pEncodedBuf[stringCnt++] = index == 0 ? '=' : Base64EncodingTable[poutput[2]];
197                         pEncodedBuf[stringCnt++] = index < 2 ? '=' : Base64EncodingTable[poutput[3]];
198                         pInput[0] = pInput[1] = pInput[2] = 0;
199                 }
200         }
201
202         pEncodedBuf[stringCnt] = '\0';
203         return pEncodedBuf;
204 }
205
206 CS_API
207 char *GetDuid(int idSize)
208 {
209         const char *version = "1.0#";
210         char info[] = {0xca, 0xfe, 0xbe, 0xbe, 0x78, 0x07, 0x02, 0x03};
211         unsigned char *pKey = NULL;
212         unsigned char *pDuid = NULL;
213         char *pId = NULL;
214         char *pKeyVersion = NULL;
215
216         if (idSize <= 0) {
217                 SLOGE("Invalid Input [%d]", idSize);
218                 return NULL;
219         }
220
221         if (!(pKey = (unsigned char *)malloc(idSize))) {
222                 SLOGE("Failed to allocate memory for key");
223                 return NULL;
224         }
225
226         if (!SecFrameGeneratePlatformUniqueKey(idSize, pKey)) {
227                 SLOGE("Failed to get duid");
228                 goto exit;
229         }
230
231         if (!(pDuid = (unsigned char *)malloc(idSize))) {
232                 SLOGE("Failed to allocate memory");
233                 goto exit;
234         }
235
236         PKCS5_PBKDF2_HMAC_SHA1(info, 8, pKey, idSize, 1, idSize, pDuid);
237
238         if (!(pId = Base64Encoding((char *)pDuid, idSize))) {
239                 SLOGE("Failed to convert to base64 string");
240                 goto exit;
241         }
242
243         if (!(pKeyVersion = (char *)calloc(strlen(pId) + strlen(version) + 1,
244                                                                            sizeof(char)))) {
245                 SLOGE("Failed to allocate memory");
246                 goto exit;
247         }
248
249         unsigned int verLen = strlen(version);
250
251         memcpy(pKeyVersion, version, verLen + 1);
252         memcpy(pKeyVersion + verLen, pId, strlen(pId) + 1);
253 exit:
254         free(pKey);
255         free(pDuid);
256         free(pId);
257         return pKeyVersion;
258 }
259
260 CS_API
261 int cs_derive_key_with_pass(const char *pass, int passlen, int keylen,
262                                                         unsigned char **key)
263 {
264         const int PBKDF_ITERATE_NUM = 1;
265         unsigned char *platform_key = NULL;
266         unsigned char *derived_key = NULL;
267         int retval = CS_ERROR_NONE;
268
269         if (pass == NULL || key == NULL || keylen <= 0)
270                 return CS_ERROR_INVALID_PARAM;
271
272         platform_key = (unsigned char *)malloc(sizeof(unsigned char) * keylen);
273
274         if (platform_key == NULL)
275                 return CS_ERROR_BAD_ALLOC;
276
277         if (!SecFrameGeneratePlatformUniqueKey(keylen, platform_key)) {
278                 retval = CS_ERROR_INTERNAL;
279                 goto exit;
280         }
281
282         derived_key = (unsigned char *)malloc(sizeof(unsigned char) * keylen);
283
284         if (derived_key == NULL) {
285                 retval = CS_ERROR_BAD_ALLOC;
286                 goto exit;
287         }
288
289         retval = PKCS5_PBKDF2_HMAC(pass, passlen,
290                                                            platform_key, keylen,
291                                                            PBKDF_ITERATE_NUM, EVP_sha1(),
292                                                            keylen, derived_key);
293
294         if (retval != 1) {
295                 retval = CS_ERROR_INTERNAL;
296                 goto exit;
297         }
298
299         free(platform_key);
300         *key = derived_key;
301         return CS_ERROR_NONE;
302 exit:
303         free(platform_key);
304         free(derived_key);
305         return retval;
306 }