2 * libcryptsvc - device unique key
4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <openssl/evp.h>
25 #include <openssl/err.h>
26 #include <openssl/rand.h>
27 #include <openssl/sha.h>
31 #include "SecCryptoSvc.h"
33 #define CS_API __attribute__((visibility("default")))
35 #define SYS_SECBOOT_DEV_ID_LEN 16
36 #define NAND_CID_NAME "/sys/block/mmcblk0/device/cid"
37 #define NAND_CID_SIZE 32
40 #ifdef CRYPTOSVC_TARGET
41 static int __AsciiToHex(const char AsciiHexUpper, const char AsciiHexLower)
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;
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;
64 static bool OemNandInfoUID(unsigned char *pUID, int nBufferSize)
67 char szCID[NAND_CID_SIZE + 1] = {0,};
68 memset(pUID, 0x00, nBufferSize);
69 fd = open(NAND_CID_NAME, O_RDONLY);
72 SLOGE("cid open error!");
76 if (read(fd, szCID, NAND_CID_SIZE) == -1) {
77 SLOGE("cid read fail!!");
83 pUID[0] = __AsciiToHex(szCID[0], szCID[1]);
85 pUID[4] = __AsciiToHex(szCID[4], szCID[5]);
87 pUID[8] = __AsciiToHex(szCID[18], szCID[19]);
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]);
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",
107 *(int *)(pUID + 12));
112 static void SysSecBootGetDeviceUniqueKey(unsigned char *pUniquekey)
114 if (!OemNandInfoUID(pUniquekey, SYS_SECBOOT_DEV_ID_LEN))
115 memset(pUniquekey, 0x00, SYS_SECBOOT_DEV_ID_LEN);
121 bool SecFrameGeneratePlatformUniqueKey(unsigned int uLen, unsigned char *pCek)
125 unsigned char Key[73] = {0};
126 unsigned char hashedValue[HASH_LEN] = {0};
127 int nTempLen = SEC_DUK_SIZE;
130 unsigned char *result = NULL;
131 #ifdef CRYPTOSVC_TARGET
132 SysSecBootGetDeviceUniqueKey(Key);
134 memset(Key, 0xFF, nTempLen);
136 memcpy(Key + nTempLen, SEC_FRAME_OSP_KEY, 9);
140 for (i = 0; i < uLen; i += HASH_LEN) {
141 result = SHA256(Key, nTempLen, hashedValue);
145 SLOGE("SecCryptoHash fail");
152 if (remain < HASH_LEN)
153 memcpy(pCek + i, hashedValue, remain);
155 memcpy(pCek + i, hashedValue, nHashLen);
158 memset(Key, 0, sizeof(Key));
159 memcpy(Key, hashedValue, nHashLen);
162 SLOGD("SecFrameGeneratePlatformUniqueKey Success.");
168 char *Base64Encoding(const char *data, int size)
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};
178 int sizeEncodedString = (4 * (size / 3)) + (size % 3 ? 4 : 0) + 1;
180 if (!(pEncodedBuf = (char *)calloc(sizeEncodedString, sizeof(char)))) {
181 SLOGE("Failed to allocate memory");
185 for (loopCnt = 0, pPointer = data; pPointer <= pLength; loopCnt++, pPointer++) {
187 pInput[index] = *pPointer;
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;
202 pEncodedBuf[stringCnt] = '\0';
207 char *GetDuid(int idSize)
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;
214 char *pKeyVersion = NULL;
217 SLOGE("Invalid Input [%d]", idSize);
221 if (!(pKey = (unsigned char *)malloc(idSize))) {
222 SLOGE("Failed to allocate memory for key");
226 if (!SecFrameGeneratePlatformUniqueKey(idSize, pKey)) {
227 SLOGE("Failed to get duid");
231 if (!(pDuid = (unsigned char *)malloc(idSize))) {
232 SLOGE("Failed to allocate memory");
236 PKCS5_PBKDF2_HMAC_SHA1(info, 8, pKey, idSize, 1, idSize, pDuid);
238 if (!(pId = Base64Encoding((char *)pDuid, idSize))) {
239 SLOGE("Failed to convert to base64 string");
243 if (!(pKeyVersion = (char *)calloc(strlen(pId) + strlen(version) + 1,
245 SLOGE("Failed to allocate memory");
249 unsigned int verLen = strlen(version);
251 memcpy(pKeyVersion, version, verLen + 1);
252 memcpy(pKeyVersion + verLen, pId, strlen(pId) + 1);
261 int cs_derive_key_with_pass(const char *pass, int passlen, int keylen,
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;
269 if (pass == NULL || key == NULL || keylen <= 0)
270 return CS_ERROR_INVALID_PARAM;
272 platform_key = (unsigned char *)malloc(sizeof(unsigned char) * keylen);
274 if (platform_key == NULL)
275 return CS_ERROR_BAD_ALLOC;
277 if (!SecFrameGeneratePlatformUniqueKey(keylen, platform_key)) {
278 retval = CS_ERROR_INTERNAL;
282 derived_key = (unsigned char *)malloc(sizeof(unsigned char) * keylen);
284 if (derived_key == NULL) {
285 retval = CS_ERROR_BAD_ALLOC;
289 retval = PKCS5_PBKDF2_HMAC(pass, passlen,
290 platform_key, keylen,
291 PBKDF_ITERATE_NUM, EVP_sha1(),
292 keylen, derived_key);
295 retval = CS_ERROR_INTERNAL;
301 return CS_ERROR_NONE;