Update snapshot(2017-12-20)
[platform/upstream/iotivity.git] / resource / csdk / security / src / pkix_interface.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include "pkix_interface.h"
22 #include "credresource.h"
23 #include "crlresource.h"
24 #include "srmresourcestrings.h"
25 #include "casecurityinterface.h"
26 #include "logger.h"
27 #include "base64.h"
28 #include "oic_malloc.h"
29
30 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----"
31 #define PEM_END_CRT "-----END CERTIFICATE-----"
32
33 #define TAG "OIC_SRM_PKIX_INTERFACE"
34
35 static HWPkixContext_t gHwPkixCtx = {
36     .getHwKeyContext = NULL,
37     .freeHwKeyContext = NULL,
38     .getOwnCertCb = NULL,
39     .setupPkContextCb = NULL,
40     .hwKeyCtx = NULL
41 };
42
43 /*
44  * returns the number of removed zeros
45  */
46 static size_t remove_useless_leading_zeros(uint8_t *asn_integer_buf, uint32_t size)
47 {
48     /*
49     */
50     uint8_t buf[32 + 4];
51     uint8_t tag = asn_integer_buf[0];
52     uint8_t len = asn_integer_buf[1];
53     uint8_t *p = asn_integer_buf + 2;
54     uint32_t idx = 0;
55
56     if (size < 2)
57     {
58         return 0;
59     }
60
61     if (tag != MBEDTLS_ASN1_INTEGER)
62     {
63         return 0;
64     }
65
66     if ((uint32_t)len + 2 != size || sizeof(buf) < size)
67     {
68         return 0;
69     }
70
71     for (idx = 0; idx < (uint32_t)len - 1; idx++)
72     {
73         if (p[idx] != 0)
74         {
75             break;
76         }
77         if (p[idx] == 0 && ((p[idx + 1] & 0x80) != 0)) // 00000000 1XXXXXXXX (bit)
78         {
79             break;
80         }
81     }
82
83     if (idx == 0)
84     {
85         return 0;
86     }
87
88     len -= idx;
89     asn_integer_buf[1] = len;
90
91     memcpy(buf, p + idx, len);
92     memcpy(p, buf, len);
93
94     return idx;
95 }
96
97 void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
98 {
99     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
100     if (NULL == crtBuf)
101     {
102         OIC_LOG(ERROR, TAG, "Param buf is NULL");
103         return;
104     }
105     if (NULL == crtBufLen)
106     {
107         OIC_LOG(ERROR, TAG, "Param bufLen is NULL");
108         return;
109     }
110
111     OIC_LOG_V(INFO, TAG, "Cert Buf Length: %lu", *crtBufLen);
112     OIC_LOG(INFO, TAG, "[Cert Buf] : ");
113     OIC_LOG_BUFFER(INFO, TAG, crtBuf, *crtBufLen);
114
115     mbedtls_x509_crt deviceCert;
116     mbedtls_x509_crt_init(&deviceCert);
117     int ret = 0;
118
119     uint8_t *derCrtBuf = NULL;
120     size_t *derCrtBufLen = NULL;
121
122     uint8_t *derCrtBufTmp = NULL;
123     size_t derCrtBufLenTmp = 0;
124
125     // check only first(i.e., device) certificate
126     if (crtBuf[0] == 0x30 && crtBuf[1] == 0x82)
127     {
128         derCrtBuf = crtBuf;
129         derCrtBufLen = crtBufLen;
130     }
131     else
132     {
133         uint8_t * begin = (uint8_t *)memmem(crtBuf, *crtBufLen,
134                                             PEM_BEGIN_CRT, sizeof(PEM_BEGIN_CRT) - 1);
135         if (NULL != begin)
136         {
137             uint8_t * end = (uint8_t *)memmem(crtBuf, *crtBufLen,
138                                               PEM_END_CRT, sizeof(PEM_END_CRT) - 1);
139             if (NULL != end)
140             {
141                 uint32_t idx = 0;
142                 uint32_t count = 0;
143                 uint32_t decodedLen = 0;
144                 begin += sizeof(PEM_BEGIN_CRT) - 1;
145                 size_t certLen = (size_t)(end - begin);
146                 size_t outBufSize = B64DECODE_OUT_SAFESIZE(certLen + 1);
147
148                 uint8_t * certCopy = (uint8_t *)OICCalloc(certLen, 1);
149                 if(NULL == certCopy)
150                 {
151                     OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
152                     goto exit;
153                 }
154                 for (idx = 0; idx < certLen; idx++)
155                 {
156                     if (begin[idx] != '\r' && begin[idx] != '\n')
157                     {
158                         certCopy[count] = begin[idx];
159                         count++;
160                     }
161                 }
162                 certLen = count;
163
164                 derCrtBufTmp = (uint8_t *)OICCalloc(outBufSize, 1);
165                 if(NULL == derCrtBufTmp)
166                 {
167                     OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
168                     goto exit;
169                 }
170
171                 if (B64_OK != b64Decode((char *)certCopy, certLen, derCrtBufTmp, outBufSize, &decodedLen))
172                 {
173                     OICFree(certCopy);
174                     goto exit;
175                 }
176                 OICFree(certCopy);
177
178                 derCrtBuf = derCrtBufTmp;
179                 derCrtBufLenTmp = decodedLen;
180                 derCrtBufLen = &derCrtBufLenTmp;
181             }
182         }
183         else
184         {
185             goto exit;
186         }
187     }
188
189     if (NULL != derCrtBuf && NULL != derCrtBufLen && 0 != *derCrtBufLen)
190     {
191         uint8_t *sign_ptr = NULL;
192         /**
193         * structure of r_buf & s_buf
194         * +---------------+-------------+----------------------------+
195         * | tag (INTEGER) | length (1B) | value (r or s in integer)  |
196         * +---------------+-------------+----------------------------+
197         */
198         uint8_t r_buf[32 + 4]; // for ECC 256 sign
199         uint8_t s_buf[32 + 4];
200         uint32_t r_len = 0;
201         uint32_t s_len = 0;
202         size_t sign_len = 0;
203         uint32_t removed = 0;
204         uint32_t removed_total = 0;
205         size_t org_len = 0;
206
207         unsigned char * tmp = (unsigned char *)derCrtBuf + 1;
208         if ( 0 != mbedtls_asn1_get_len(&tmp, derCrtBuf + *derCrtBufLen, &org_len))
209         {
210             OIC_LOG(ERROR, TAG, "Invalid parsed length");
211             goto exit;
212         }
213
214         if (org_len < *derCrtBufLen)
215         {
216             ret = mbedtls_x509_crt_parse_der(&deviceCert, derCrtBuf, org_len + 4);
217             if (0 != ret)
218             {
219                 OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse_der returned -0x%04x", -(ret));
220                 goto exit;
221             }
222
223             if (NULL == deviceCert.sig.p)
224             {
225                 OIC_LOG(ERROR, TAG, "Cert's signature is NULL");
226                 goto exit;
227             }
228             sign_ptr = (uint8_t*)deviceCert.sig.p;
229             ret = mbedtls_asn1_get_tag(&sign_ptr, deviceCert.sig.p + deviceCert.sig.len, &sign_len,
230                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
231             if (0 != ret)
232             {
233                 OIC_LOG_V(ERROR, TAG, "mbedtls_asn1_get_tag error : %d", ret);
234                 goto exit;
235             }
236             if (sign_ptr)
237             {
238                 r_len = sign_ptr[1] + 2; // including header itself
239             }
240             if (r_len > deviceCert.sig.len)
241             {
242                 OIC_LOG_V(ERROR, TAG, "signature length check error #1 : %d", ret);
243                 goto exit;
244             }
245             OIC_LOG_V(DEBUG, TAG, "r_len = %d", r_len);
246             memcpy(r_buf, sign_ptr, r_len);
247             removed = remove_useless_leading_zeros(r_buf, r_len);
248
249             /* Do not change order */
250             sign_ptr += r_len;
251             r_len -= removed;
252             removed_total += removed;
253             if (sign_ptr)
254             {
255                 s_len = sign_ptr[1] + 2; // including header itself
256             }
257             if (s_len + r_len > deviceCert.sig.len)
258             {
259                 OIC_LOG_V(ERROR, TAG, "signature length check error #2 : %d", ret);
260                 goto exit;
261             }
262             OIC_LOG_V(DEBUG, TAG, "s_len = %d", s_len);
263             memcpy(s_buf, sign_ptr, s_len);
264             removed = remove_useless_leading_zeros(s_buf, s_len);
265             s_len -= removed;
266             removed_total += removed;
267
268             if (removed_total > 0)
269             {
270                 // if length of signature is incorrect.
271                 OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %lu", *derCrtBufLen);
272                 OIC_LOG(INFO, TAG, "Invalid length of signature is dectected.");
273                 OIC_LOG(INFO, TAG, "Update signature...");
274
275                 uint16_t crt_len = 0;
276                 /* change bitstring length */
277                 {
278                     uint8_t *sign_len_ptr = deviceCert.sig.p + 1;
279                     *sign_len_ptr -= removed_total;
280                 }
281                 /* change signature length */
282                 {
283                     uint8_t *sign_len_ptr = deviceCert.sig.p - 1;
284                     if (*sign_len_ptr == 0)
285                     {
286                         sign_len_ptr--;
287                     }
288                     *sign_len_ptr -= removed_total;
289                 }
290                 /* change signature */
291                 {
292                     memcpy(deviceCert.sig.p + 2, r_buf, r_len);
293                     memcpy(deviceCert.sig.p + 2 + r_len, s_buf, s_len);
294                 }
295                 /* change certificate length */
296                 {
297                     uint8_t *crt_len_ptr = deviceCert.raw.p + 2;
298                     crt_len = (crt_len_ptr[0] << 8) & 0x0000FF00;
299                     crt_len |= (crt_len_ptr[1] & 0x000000FF);
300                     crt_len -= removed_total;
301                     crt_len_ptr[0] = (uint8_t)(crt_len >> 8);
302                     crt_len_ptr[1] = (uint8_t)(crt_len);
303                 }
304                 crt_len += 4; // include header and length field
305                 /* change raw data and crt parse cert again */
306                 {
307                     mbedtls_x509_crt crt_cpy;
308                     mbedtls_x509_crt_init( &crt_cpy );
309                     if ((ret = mbedtls_x509_crt_parse_der(&crt_cpy, deviceCert.raw.p, (size_t)crt_len)) != 0)
310                     {
311                         OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse error : %d", ret);
312                         mbedtls_x509_crt_free(&crt_cpy);
313                         goto exit;
314                     }
315
316                     org_len += 4; // include header and length field
317                     size_t remained_len = (*derCrtBufLen - org_len);
318                     memcpy(derCrtBuf, deviceCert.raw.p, crt_len);
319                     memcpy(derCrtBuf + crt_len, derCrtBuf + org_len, remained_len);
320                     *derCrtBufLen = (size_t)crt_len + remained_len;
321
322                     mbedtls_x509_crt_free(&crt_cpy);
323                     OIC_LOG_V(INFO, TAG, "Dev cert : %lu -> %lu", org_len, crt_len);
324                     OIC_LOG_V(INFO, TAG, "Remained chain : %lu", remained_len);
325                     OIC_LOG_V(INFO, TAG, "Cert Length (After) : %lu", *crtBufLen);
326                 }
327             }
328             else
329             {
330                 // if length of signature is correct.
331                 OIC_LOG(INFO, TAG, "Don't need to update signature...");
332             }
333
334         }
335     }
336     else
337     {
338         OIC_LOG(ERROR, TAG, "PEM or invalid cert format detected. finish to check");
339     }
340
341 exit:
342     mbedtls_x509_crt_free(&deviceCert);
343     OICFree(derCrtBufTmp);
344     OIC_LOG_V(DEBUG, TAG, "Cert chain length = %d", *crtBufLen);
345     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
346 }
347
348 /**
349  * Internal API to load the key/cert from HW PKI
350  *
351  * @return true on HW PKI is available
352  */
353 static bool GetPkixInfoFromHw(PkiInfo_t * inf)
354 {
355     OIC_LOG_V(INFO, TAG, "In %s", __func__);
356
357     if (!gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getHwKeyContext)
358     {
359         gHwPkixCtx.hwKeyCtx = gHwPkixCtx.getHwKeyContext(
360                                                         HWKEY_SVC_IOTIVITY,
361                                                         HWKEY_USAGE_PRIMARY, NULL);
362         if (!gHwPkixCtx.hwKeyCtx)
363         {
364             OIC_LOG(WARNING, TAG, "gHwPkixCtx.getHwKeyContext return null");
365         }
366     }
367
368     if (gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getOwnCertCb)
369     {
370         int ret = gHwPkixCtx.getOwnCertCb(gHwPkixCtx.hwKeyCtx, &inf->crt.data, &inf->crt.len);
371         if (0 != ret)
372         {
373             OIC_LOG_V(ERROR, TAG, "gHwPkixCtx.getOwnCertCb error : %d", ret);
374             OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
375             return false;
376         }
377
378         // check and fix invalid cert signature
379         CheckInvalidDERSignature(inf->crt.data, &inf->crt.len);
380
381         OIC_LOG_V(INFO, TAG, "Cert chain length = %d", inf->crt.len);
382         OIC_LOG_V(INFO, TAG, "Out %s", __func__);
383         return true;
384     }
385     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
386     return false;
387 }
388
389 void GetPkixInfo(PkiInfo_t * inf)
390 {
391     OIC_LOG_V(INFO, TAG, "In %s", __func__);
392     if (NULL == inf)
393     {
394         OIC_LOG(ERROR, TAG, "NULL passed");
395         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
396         return;
397     }
398
399     if (GetPkixInfoFromHw(inf))
400     {
401         OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
402     }
403     else
404     {
405         GetDerOwnCert(&inf->crt, PRIMARY_CERT);
406         GetDerKey(&inf->key, PRIMARY_CERT);
407     }
408     GetDerCaCert(&inf->ca, TRUST_CA);
409     GetDerCrl(&inf->crl);
410
411     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
412 }
413
414 void GetManufacturerPkixInfo(PkiInfo_t * inf)
415 {
416     OIC_LOG_V(INFO, TAG, "In %s", __func__);
417     if (NULL == inf)
418     {
419         OIC_LOG(ERROR, TAG, "NULL passed");
420         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
421         return;
422     }
423
424     if (GetPkixInfoFromHw(inf))
425     {
426         OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
427     }
428     else
429     {
430         GetDerOwnCert(&inf->crt, MF_PRIMARY_CERT);
431         GetDerKey(&inf->key, MF_PRIMARY_CERT);
432     }
433     GetDerCaCert(&inf->ca, MF_TRUST_CA);
434     // CRL not provided
435 #ifdef __TIZENRT__
436     OICFree(inf->crl.data);
437 #endif
438     inf->crl.data = NULL;
439     inf->crl.len = 0;
440     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
441 }
442
443 void InitCipherSuiteList(bool * list)
444 {
445     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
446     if (NULL == list)
447     {
448         OIC_LOG(ERROR, TAG, "NULL passed");
449         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
450         return;
451     }
452     InitCipherSuiteListInternal(list, TRUST_CA);
453     if (gHwPkixCtx.getOwnCertCb)
454     {
455         list[1] = true;
456     }
457     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
458 }
459
460 void InitManufacturerCipherSuiteList(bool * list)
461 {
462     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
463     if (NULL == list)
464     {
465         OIC_LOG(ERROR, TAG, "NULL passed");
466         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
467         return;
468     }
469     InitCipherSuiteListInternal(list, MF_TRUST_CA);
470     if (gHwPkixCtx.getOwnCertCb)
471     {
472         list[1] = true;
473     }
474     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
475 }
476
477 int SetupHwPkContext(mbedtls_pk_context* pkCtx)
478 {
479     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
480     if (NULL == pkCtx)
481     {
482         OIC_LOG(ERROR, TAG, "NULL passed");
483         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
484         return -1;
485     }
486
487     if (gHwPkixCtx.setupPkContextCb)
488     {
489         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
490         return gHwPkixCtx.setupPkContextCb(pkCtx, gHwPkixCtx.hwKeyCtx);
491     }
492     else
493     {
494         OIC_LOG(ERROR, TAG, "gHwPkixCallbacks.setupPkContextCb is NULL");
495     }
496
497     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
498
499     return -1;
500 }
501
502 int SetHwPkixCallbacks(GetHwKeyContext getHwKeyContext,
503                         FreeHwKeyContext freeHwKeyContext,
504                         GetOwnCertFromHwCallback getOwnCertCb,
505                         SetupPkContextFromHwCallback setupPkContextCb)
506 {
507     OIC_LOG_V(INFO, TAG, "In %s", __func__);
508
509     if (NULL == getHwKeyContext && NULL == freeHwKeyContext
510         && NULL == getOwnCertCb && NULL == setupPkContextCb)
511     {
512         OIC_LOG(INFO, TAG, "Unregistering callbacks");
513     }
514     else if (NULL == getHwKeyContext || NULL == freeHwKeyContext
515              || NULL == getOwnCertCb || NULL == setupPkContextCb)
516     {
517         OIC_LOG(ERROR, TAG, "NULL Passed");
518         OIC_LOG(ERROR, TAG, "Callback function parameters can not be null");
519         return -1;
520     }
521
522     gHwPkixCtx.getHwKeyContext = getHwKeyContext;
523     gHwPkixCtx.freeHwKeyContext = freeHwKeyContext;
524     gHwPkixCtx.getOwnCertCb = getOwnCertCb;
525     gHwPkixCtx.setupPkContextCb = setupPkContextCb;
526
527     if (gHwPkixCtx.hwKeyCtx && NULL != freeHwKeyContext)
528     {
529         gHwPkixCtx.freeHwKeyContext(gHwPkixCtx.hwKeyCtx);
530     }
531     gHwPkixCtx.hwKeyCtx = NULL;
532
533     // setup pkcontext handler
534     CAregisterSetupPkContextHandler(SetupHwPkContext);
535
536     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
537     return 0;
538 }
539