44d5ce036a92a1909d7f1aeb1d8aa3df5c9bdfb4
[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 SYS_SECBOOT_DEV_ID_LEN  16
34 #define NAND_CID_NAME   "/sys/block/mmcblk0/device/cid"
35 #define NAND_CID_SIZE   32
36
37
38 #ifdef CRYPTOSVC_TARGET
39 static int __AsciiToHex(const char AsciiHexUpper,const char AsciiHexLower)
40 {
41         char hexReturn=0;
42
43         //First convert upper hex ascii value
44         if (AsciiHexUpper >= '0' && AsciiHexUpper <= '9')
45                 hexReturn = (AsciiHexUpper - '0') * 16;
46         else if (AsciiHexUpper >= 'A' && AsciiHexUpper <= 'F')
47                 hexReturn = ((AsciiHexUpper - 'A') + 10) * 16;
48         else if (AsciiHexUpper >= 'a' && AsciiHexUpper <= 'f')
49                 hexReturn = ((AsciiHexUpper - 'a') + 10) * 16;
50
51         //Convert lower hex ascii value
52         if (AsciiHexLower >= '0' && AsciiHexLower <= '9')
53                 hexReturn = hexReturn + (AsciiHexLower - '0');
54         else if (AsciiHexLower >= 'A' && AsciiHexLower <= 'F')
55                 hexReturn = hexReturn + (AsciiHexLower - 'A') + 10;
56         else if (AsciiHexLower >= 'a' && AsciiHexLower <= 'f')
57                 hexReturn = hexReturn + (AsciiHexLower - 'a') + 10;
58
59         return hexReturn;
60 }
61
62 bool OemNandInfoUID(unsigned char *pUID, int nBufferSize)
63 {
64         int fd = 0;
65         char szCID[NAND_CID_SIZE + 1] = {0,};
66
67         memset(pUID, 0x00, nBufferSize);
68
69         fd = open(NAND_CID_NAME, O_RDONLY);
70         if (fd < 0) {
71                 SLOGE("cid open error!");
72                 return false;
73         }
74
75         if (read(fd, szCID, NAND_CID_SIZE) == -1) {
76                 SLOGE("cid read fail!!");
77                 close(fd);
78                 return false;
79         }
80
81         //manufacturer_id
82         pUID[0] =  __AsciiToHex((const char)szCID[0], (const char)szCID[1]);
83         //oem_id
84         pUID[4] =  __AsciiToHex((const char)szCID[4], (const char)szCID[5]);
85         //prod_rev
86         pUID[8] =  __AsciiToHex((const char)szCID[18], (const char)szCID[19]);
87         //serial
88         pUID[15] = __AsciiToHex((const char)szCID[20], (const char)szCID[21]);
89         pUID[14] =  __AsciiToHex((const char)szCID[22], (const char)szCID[23]);
90         pUID[13] = __AsciiToHex((const char)szCID[24], (const char)szCID[25]);
91         pUID[12] =  __AsciiToHex((const char)szCID[26], (const char)szCID[27]);
92
93         // random permutation
94         pUID[1] = __AsciiToHex((const char)szCID[2], (const char)szCID[3]);
95         pUID[2] = __AsciiToHex((const char)szCID[6], (const char)szCID[7]);
96         pUID[3] = __AsciiToHex((const char)szCID[8], (const char)szCID[9]);
97
98         pUID[5] = __AsciiToHex((const char)szCID[10], (const char)szCID[11]);
99         pUID[6] = __AsciiToHex((const char)szCID[12], (const char)szCID[13]);
100         pUID[7] = __AsciiToHex((const char)szCID[14], (const char)szCID[15]);
101
102         pUID[9] = __AsciiToHex((const char)szCID[16], (const char)szCID[17]);
103         pUID[10] = __AsciiToHex((const char)szCID[28], (const char)szCID[29]);
104         pUID[11] = __AsciiToHex((const char)szCID[30], (const char)szCID[31]);
105
106         SLOGD(" UID : %8X %8X %8X %8X",
107                 *(int *)pUID,
108                 *(int *)(pUID + 4),
109                 *(int *)(pUID + 8),
110                 *(int *)(pUID + 12));
111
112         close(fd);
113         return true;
114 }
115
116 void SysSecBootGetDeviceUniqueKey(unsigned char *pUniquekey)
117 {
118         if (!OemNandInfoUID(pUniquekey, SYS_SECBOOT_DEV_ID_LEN))
119                 memset(pUniquekey, 0x00, SYS_SECBOOT_DEV_ID_LEN);
120 }
121 #endif
122
123
124 bool SecFrameGeneratePlatformUniqueKey(unsigned int uLen, unsigned char *pCek)
125 {
126         bool bResult = true;
127         unsigned int i = 0;
128         unsigned char Key[73] = {0};
129         unsigned char hashedValue[HASH_LEN] = {0};
130         int nTempLen = SEC_DUK_SIZE;
131         int nHashLen = 0;
132         int remain = 0;
133         unsigned char *result = NULL;
134
135 #ifdef CRYPTOSVC_TARGET
136         SysSecBootGetDeviceUniqueKey(Key);
137 #else
138         memset(Key, 0xFF, nTempLen);
139 #endif
140
141         memcpy(Key+nTempLen, SEC_FRAME_OSP_KEY, 9);
142         nTempLen += 9;
143
144         remain = uLen;
145
146         for (i = 0; i < uLen; i += HASH_LEN) {
147                 result = SHA1(Key, nTempLen, hashedValue);
148                 nHashLen = HASH_LEN;
149
150                 if (!result) {
151                         SLOGE("SecCryptoHash fail");
152                         bResult = false;
153                         goto ERR;
154                 }
155
156                 nTempLen = nHashLen;
157
158                 if (remain < HASH_LEN)
159                         memcpy(pCek + i, hashedValue, remain);
160                 else
161                         memcpy(pCek + i, hashedValue, nHashLen);
162
163                 remain -= HASH_LEN;
164                 memset(Key, 0, sizeof(Key));
165                 memcpy(Key, hashedValue, nHashLen);
166         }
167
168         SLOGD("SecFrameGeneratePlatformUniqueKey Success.");
169
170 ERR:
171         return bResult;
172 }
173
174 char *Base64Encoding(char *pData, int size)
175 {
176         char *pEncodedBuf = NULL;
177         char *pPointer = NULL;
178         char *pLength = pData + size - 1;
179         unsigned char pInput[3] = {0,0,0};
180         unsigned char poutput[4] = {0,0,0,0};
181         int index = 0;
182         int loopCnt = 0;
183         int stringCnt = 0;
184         int sizeEncodedString = (4 * (size / 3)) + (size % 3 ? 4 : 0) + 1;
185
186         if (!(pEncodedBuf = (char *)calloc(sizeEncodedString, sizeof(char)))) {
187                 SLOGE("Failed to allocate memory");
188                 return NULL;
189         }
190
191         for     (loopCnt = 0, pPointer = pData; pPointer <= pLength; loopCnt++, pPointer++) {
192                 index = loopCnt % 3;
193                 pInput[index] = *pPointer;
194
195                 if (index == 2 || pPointer == pLength) {
196                         poutput[0] = ((pInput[0] & 0xFC) >> 2);
197                         poutput[1] = ((pInput[0] & 0x3) << 4) | ((pInput[1] & 0xF0) >> 4);
198                         poutput[2] = ((pInput[1] & 0xF) << 2) | ((pInput[2] & 0xC0) >> 6);
199                         poutput[3] = (pInput[2] & 0x3F);
200
201                         pEncodedBuf[stringCnt++] = Base64EncodingTable[poutput[0]];
202                         pEncodedBuf[stringCnt++] = Base64EncodingTable[poutput[1]];
203                         pEncodedBuf[stringCnt++] = index == 0 ? '=' : Base64EncodingTable[poutput[2]];
204                         pEncodedBuf[stringCnt++] = index < 2 ? '=' : Base64EncodingTable[poutput[3]];
205
206                         pInput[0] = pInput[1] = pInput[2] = 0;
207                 }
208         }
209
210         pEncodedBuf[stringCnt] = '\0';
211
212         return pEncodedBuf;
213 }
214
215 char *GetDuid(int idSize)
216 {
217         const char *version = "1.0#";
218         char info[] = {0xca, 0xfe, 0xbe, 0xbe, 0x78, 0x07, 0x02, 0x03};
219
220         unsigned char *pKey = NULL;
221         unsigned char *pDuid = NULL;
222         char *pId = NULL;
223         char *pKeyVersion = NULL;
224
225         if (idSize <= 0) {
226                 SLOGE("Invalid Input [%d]", idSize);
227                 return NULL;
228         }
229
230         if (!(pKey = (unsigned char *)malloc(idSize))) {
231                 SLOGE("Failed to allocate memory for key");
232                 return NULL;
233         }
234
235         if (!SecFrameGeneratePlatformUniqueKey(idSize, pKey)) {
236                 SLOGE("Failed to get duid");
237                 goto exit;
238         }
239
240         if (!(pDuid = (unsigned char *)malloc(idSize))) {
241                 SLOGE("Failed to allocate memory");
242                 goto exit;
243         }
244
245         PKCS5_PBKDF2_HMAC_SHA1(info, 8, pKey, idSize, 1, idSize, pDuid);
246
247         if (!(pId = Base64Encoding((char *)pDuid, idSize))) {
248                 SLOGE("Failed to convert to base64 string");
249                 goto exit;
250         }
251
252         if (!(pKeyVersion = (char *)calloc(strlen(pId) + strlen(version) + 1, sizeof(char)))) {
253                 SLOGE("Failed to allocate memory");
254                 goto exit;
255         }
256         strncpy(pKeyVersion, version, strlen(version));
257         strncat(pKeyVersion, pId, strlen(pId));
258
259 exit:
260         free(pKey);
261         free(pDuid);
262         free(pId);
263
264         return pKeyVersion;
265 }
266