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