Update snapshot(2017-11-23)
[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 #ifdef __TIZENRT__
28 #include "oic_malloc.h"
29 #endif
30
31 #define TAG "OIC_SRM_PKIX_INTERFACE"
32
33 static HWPkixContext_t gHwPkixCtx = {
34     .getHwKeyContext = NULL,
35     .freeHwKeyContext = NULL,
36     .getOwnCertCb = NULL,
37     .setupPkContextCb = NULL,
38     .hwKeyCtx = NULL
39 };
40
41 /*
42  * returns the number of removed zeros
43  */
44 static size_t remove_useless_leading_zeros(uint8_t *asn_integer_buf, uint32_t size)
45 {
46     /*
47     */
48     uint8_t buf[32 + 4];
49     uint8_t tag = asn_integer_buf[0];
50     uint8_t len = asn_integer_buf[1];
51     uint8_t *p = asn_integer_buf + 2;
52     uint32_t idx = 0;
53
54     if (size < 2)
55     {
56         return 0;
57     }
58
59     if (tag != MBEDTLS_ASN1_INTEGER)
60     {
61         return 0;
62     }
63
64     if ((uint32_t)len + 2 != size || sizeof(buf) < size)
65     {
66         return 0;
67     }
68
69     for (idx = 0; idx < (uint32_t)len - 1; idx++)
70     {
71         if (p[idx] != 0)
72         {
73             break;
74         }
75         if (p[idx] == 0 && ((p[idx + 1] & 0x80) != 0)) // 00000000 1XXXXXXXX (bit)
76         {
77             break;
78         }
79     }
80
81     if (idx == 0)
82     {
83         return 0;
84     }
85
86     len -= idx;
87     asn_integer_buf[1] = len;
88
89     memcpy(buf, p + idx, len);
90     memcpy(p, buf, len);
91
92     return idx;
93 }
94
95 void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
96 {
97     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
98     if (NULL == crtBuf)
99     {
100         OIC_LOG(ERROR, TAG, "Param buf is NULL");
101         return;
102     }
103     if (NULL == crtBufLen)
104     {
105         OIC_LOG(ERROR, TAG, "Param bufLen is NULL");
106         return;
107     }
108
109     OIC_LOG_V(INFO, TAG, "Cert Buf Length: %lu", *crtBufLen);
110     OIC_LOG(INFO, TAG, "[Cert Buf] : ");
111     OIC_LOG_BUFFER(INFO, TAG, crtBuf, *crtBufLen);
112
113     mbedtls_x509_crt deviceCert;
114     int ret = 0;
115
116     // check only first(i.e., device) certificate
117     if (crtBuf[0] == 0x30 && crtBuf[1] == 0x82)
118     {
119         uint8_t *sign_ptr = NULL;
120         /**
121         * structure of r_buf & s_buf
122         * +---------------+-------------+----------------------------+
123         * | tag (INTEGER) | length (1B) | value (r or s in integer)  |
124         * +---------------+-------------+----------------------------+
125         */
126         uint8_t r_buf[32 + 4]; // for ECC 256 sign
127         uint8_t s_buf[32 + 4];
128         uint32_t r_len = 0;
129         uint32_t s_len = 0;
130         size_t sign_len = 0;
131         uint32_t removed = 0;
132         uint32_t removed_total = 0;
133         size_t org_len = 0;
134
135         mbedtls_x509_crt_init(&deviceCert);
136
137         unsigned char * tmp = (unsigned char *)crtBuf + 1;
138         if ( 0 != mbedtls_asn1_get_len(&tmp, crtBuf + *crtBufLen, &org_len))
139         {
140             OIC_LOG(ERROR, TAG, "Invalid parsed length");
141             goto exit;
142         }
143
144         if (org_len < *crtBufLen)
145         {
146             ret = mbedtls_x509_crt_parse_der(&deviceCert, crtBuf, org_len + 4);
147             if (0 != ret)
148             {
149                 OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse_der returned -0x%04x", -(ret));
150                 goto exit;
151             }
152
153             if (NULL == deviceCert.sig.p)
154             {
155                 OIC_LOG(ERROR, TAG, "Cert's signature is NULL");
156                 goto exit;
157             }
158             sign_ptr = (uint8_t*)deviceCert.sig.p;
159             ret = mbedtls_asn1_get_tag(&sign_ptr, deviceCert.sig.p + deviceCert.sig.len, &sign_len,
160                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
161             if (0 != ret)
162             {
163                 OIC_LOG_V(ERROR, TAG, "mbedtls_asn1_get_tag error : %d", ret);
164                 goto exit;
165             }
166             if (sign_ptr)
167             {
168                 r_len = sign_ptr[1] + 2; // including header itself
169             }
170             if (r_len > deviceCert.sig.len)
171             {
172                 OIC_LOG_V(ERROR, TAG, "signature length check error #1 : %d", ret);
173                 goto exit;
174             }
175             OIC_LOG_V(DEBUG, TAG, "r_len = %d", r_len);
176             memcpy(r_buf, sign_ptr, r_len);
177             removed = remove_useless_leading_zeros(r_buf, r_len);
178
179             /* Do not change order */
180             sign_ptr += r_len;
181             r_len -= removed;
182             removed_total += removed;
183             if (sign_ptr)
184             {
185                 s_len = sign_ptr[1] + 2; // including header itself
186             }
187             if (s_len + r_len > deviceCert.sig.len)
188             {
189                 OIC_LOG_V(ERROR, TAG, "signature length check error #2 : %d", ret);
190                 goto exit;
191             }
192             OIC_LOG_V(DEBUG, TAG, "s_len = %d", s_len);
193             memcpy(s_buf, sign_ptr, s_len);
194             removed = remove_useless_leading_zeros(s_buf, s_len);
195             s_len -= removed;
196             removed_total += removed;
197
198             if (removed_total > 0)
199             {
200                 // if length of signature is incorrect.
201                 OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %lu", *crtBufLen);
202                 OIC_LOG(INFO, TAG, "Invalid length of signature is dectected.");
203                 OIC_LOG(INFO, TAG, "Update signature...");
204
205                 uint16_t crt_len = 0;
206                 /* change bitstring length */
207                 {
208                     uint8_t *sign_len_ptr = deviceCert.sig.p + 1;
209                     *sign_len_ptr -= removed_total;
210                 }
211                 /* change signature length */
212                 {
213                     uint8_t *sign_len_ptr = deviceCert.sig.p - 1;
214                     if (*sign_len_ptr == 0)
215                     {
216                         sign_len_ptr--;
217                     }
218                     *sign_len_ptr -= removed_total;
219                 }
220                 /* change signature */
221                 {
222                     memcpy(deviceCert.sig.p + 2, r_buf, r_len);
223                     memcpy(deviceCert.sig.p + 2 + r_len, s_buf, s_len);
224                 }
225                 /* change certificate length */
226                 {
227                     uint8_t *crt_len_ptr = deviceCert.raw.p + 2;
228                     crt_len = (crt_len_ptr[0] << 8) & 0x0000FF00;
229                     crt_len |= (crt_len_ptr[1] & 0x000000FF);
230                     crt_len -= removed_total;
231                     crt_len_ptr[0] = (uint8_t)(crt_len >> 8);
232                     crt_len_ptr[1] = (uint8_t)(crt_len);
233                 }
234                 crt_len += 4; // include header and length field
235                 /* change raw data and crt parse cert again */
236                 {
237                     mbedtls_x509_crt crt_cpy;
238                     mbedtls_x509_crt_init( &crt_cpy );
239                     if ((ret = mbedtls_x509_crt_parse_der(&crt_cpy, deviceCert.raw.p, (size_t)crt_len)) != 0)
240                     {
241                         OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse error : %d", ret);
242                         mbedtls_x509_crt_free(&crt_cpy);
243                         goto exit;
244                     }
245
246                     org_len += 4; // include header and length field
247                     size_t remained_len = (*crtBufLen - org_len);
248                     memcpy(crtBuf, deviceCert.raw.p, crt_len);
249                     memcpy(crtBuf + crt_len, crtBuf + org_len, remained_len);
250                     *crtBufLen = (size_t)crt_len + remained_len;
251
252                     mbedtls_x509_crt_free(&crt_cpy);
253                     OIC_LOG_V(INFO, TAG, "Dev cert : %lu -> %lu", org_len, crt_len);
254                     OIC_LOG_V(INFO, TAG, "Remained chain : %lu", remained_len);
255                     OIC_LOG_V(INFO, TAG, "Cert Length (After) : %lu", *crtBufLen);
256                 }
257             }
258             else
259             {
260                 // if length of signature is correct.
261                 OIC_LOG(INFO, TAG, "Don't need to update signature...");
262             }
263
264         }
265     }
266     else
267     {
268         OIC_LOG(ERROR, TAG, "PEM or invalid cert format detected. finish to check");
269     }
270
271 exit:
272     mbedtls_x509_crt_free(&deviceCert);
273     OIC_LOG_V(DEBUG, TAG, "Cert chain length = %d", *crtBufLen);
274     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
275 }
276
277 /**
278  * Internal API to load the key/cert from HW PKI
279  *
280  * @return true on HW PKI is available
281  */
282 static bool GetPkixInfoFromHw(PkiInfo_t * inf)
283 {
284     OIC_LOG_V(INFO, TAG, "In %s", __func__);
285
286     if (!gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getHwKeyContext)
287     {
288         gHwPkixCtx.hwKeyCtx = gHwPkixCtx.getHwKeyContext(
289                                                         HWKEY_SVC_IOTIVITY,
290                                                         HWKEY_USAGE_PRIMARY, NULL);
291         if (!gHwPkixCtx.hwKeyCtx)
292         {
293             OIC_LOG(WARNING, TAG, "gHwPkixCtx.getHwKeyContext return null");
294         }
295     }
296
297     if (gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getOwnCertCb)
298     {
299         int ret = gHwPkixCtx.getOwnCertCb(gHwPkixCtx.hwKeyCtx, &inf->crt.data, &inf->crt.len);
300         if (0 != ret)
301         {
302             OIC_LOG_V(ERROR, TAG, "gHwPkixCtx.getOwnCertCb error : %d", ret);
303             OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
304             return false;
305         }
306
307         // check and fix invalid cert signature
308         CheckInvalidDERSignature(inf->crt.data, &inf->crt.len);
309
310         OIC_LOG_V(INFO, TAG, "Cert chain length = %d", inf->crt.len);
311         OIC_LOG_V(INFO, TAG, "Out %s", __func__);
312         return true;
313     }
314     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
315     return false;
316 }
317
318 void GetPkixInfo(PkiInfo_t * inf)
319 {
320     OIC_LOG_V(INFO, TAG, "In %s", __func__);
321     if (NULL == inf)
322     {
323         OIC_LOG(ERROR, TAG, "NULL passed");
324         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
325         return;
326     }
327
328     if (GetPkixInfoFromHw(inf))
329     {
330         OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
331     }
332     else
333     {
334         GetDerOwnCert(&inf->crt, PRIMARY_CERT);
335         GetDerKey(&inf->key, PRIMARY_CERT);
336     }
337     GetDerCaCert(&inf->ca, TRUST_CA);
338     GetDerCrl(&inf->crl);
339
340     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
341 }
342
343 void GetManufacturerPkixInfo(PkiInfo_t * inf)
344 {
345     OIC_LOG_V(INFO, TAG, "In %s", __func__);
346     if (NULL == inf)
347     {
348         OIC_LOG(ERROR, TAG, "NULL passed");
349         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
350         return;
351     }
352
353     if (GetPkixInfoFromHw(inf))
354     {
355         OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
356     }
357     else
358     {
359         GetDerOwnCert(&inf->crt, MF_PRIMARY_CERT);
360         GetDerKey(&inf->key, MF_PRIMARY_CERT);
361     }
362     GetDerCaCert(&inf->ca, MF_TRUST_CA);
363     // CRL not provided
364 #ifdef __TIZENRT__
365     OICFree(inf->crl.data);
366 #endif
367     inf->crl.data = NULL;
368     inf->crl.len = 0;
369     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
370 }
371
372 void InitCipherSuiteList(bool * list)
373 {
374     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
375     if (NULL == list)
376     {
377         OIC_LOG(ERROR, TAG, "NULL passed");
378         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
379         return;
380     }
381     InitCipherSuiteListInternal(list, TRUST_CA);
382     if (gHwPkixCtx.getOwnCertCb)
383     {
384         list[1] = true;
385     }
386     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
387 }
388
389 void InitManufacturerCipherSuiteList(bool * list)
390 {
391     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
392     if (NULL == list)
393     {
394         OIC_LOG(ERROR, TAG, "NULL passed");
395         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
396         return;
397     }
398     InitCipherSuiteListInternal(list, MF_TRUST_CA);
399     if (gHwPkixCtx.getOwnCertCb)
400     {
401         list[1] = true;
402     }
403     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
404 }
405
406 int SetupHwPkContext(mbedtls_pk_context* pkCtx)
407 {
408     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
409     if (NULL == pkCtx)
410     {
411         OIC_LOG(ERROR, TAG, "NULL passed");
412         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
413         return -1;
414     }
415
416     if (gHwPkixCtx.setupPkContextCb)
417     {
418         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
419         return gHwPkixCtx.setupPkContextCb(pkCtx, gHwPkixCtx.hwKeyCtx);
420     }
421     else
422     {
423         OIC_LOG(ERROR, TAG, "gHwPkixCallbacks.setupPkContextCb is NULL");
424     }
425
426     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
427
428     return -1;
429 }
430
431 int SetHwPkixCallbacks(GetHwKeyContext getHwKeyContext,
432                         FreeHwKeyContext freeHwKeyContext,
433                         GetOwnCertFromHwCallback getOwnCertCb,
434                         SetupPkContextFromHwCallback setupPkContextCb)
435 {
436     OIC_LOG_V(INFO, TAG, "In %s", __func__);
437
438     if (NULL == getHwKeyContext && NULL == freeHwKeyContext
439         && NULL == getOwnCertCb && NULL == setupPkContextCb)
440     {
441         OIC_LOG(INFO, TAG, "Unregistering callbacks");
442     }
443     else if (NULL == getHwKeyContext || NULL == freeHwKeyContext
444              || NULL == getOwnCertCb || NULL == setupPkContextCb)
445     {
446         OIC_LOG(ERROR, TAG, "NULL Passed");
447         OIC_LOG(ERROR, TAG, "Callback function parameters can not be null");
448         return -1;
449     }
450
451     gHwPkixCtx.getHwKeyContext = getHwKeyContext;
452     gHwPkixCtx.freeHwKeyContext = freeHwKeyContext;
453     gHwPkixCtx.getOwnCertCb = getOwnCertCb;
454     gHwPkixCtx.setupPkContextCb = setupPkContextCb;
455
456     if (gHwPkixCtx.hwKeyCtx && NULL != freeHwKeyContext)
457     {
458         gHwPkixCtx.freeHwKeyContext(gHwPkixCtx.hwKeyCtx);
459     }
460     gHwPkixCtx.hwKeyCtx = NULL;
461
462     // setup pkcontext handler
463     CAregisterSetupPkContextHandler(SetupHwPkContext);
464
465     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
466     return 0;
467 }
468