[IOT-1947][IOT-2761][IOT-3228] Rm PEM/DER convert
[iotivity.git] / resource / csdk / security / src / certhelpers.c
1 /* *****************************************************************
2  *
3  * Copyright 2017 Microsoft. 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 "iotivity_config.h"
22
23 #include "experimental/logger.h"
24 #include <stddef.h>
25 #include <string.h>
26 #include <assert.h>
27 #include "oic_malloc.h"
28 #include "oic_string.h"
29 #include "cacommon.h"
30 #include "experimental/ocrandom.h"
31 #include "cacommonutil.h"
32 #include "parsechain.h"
33
34 #include "ocpayload.h"
35 #include "experimental/payload_logging.h"
36 #include "pmutility.h"
37 #include "srmutility.h"
38
39 // headers required for mbed TLS
40 #include "mbedtls/config.h"
41 #include "mbedtls/platform.h"
42 #include "mbedtls/entropy.h"
43 #include "mbedtls/ctr_drbg.h"
44 #include "mbedtls/x509_csr.h"
45 #include "mbedtls/x509_crt.h"
46 #include "mbedtls/oid.h"
47
48 #ifndef NDEBUG
49 #include "mbedtls/debug.h"
50 #include "mbedtls/version.h"
51 #endif
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #include <fcntl.h>
57
58 #include "certhelpers.h"
59
60 #define TAG "OIC_CERTHELPERS"
61
62 /**
63  * @def PERSONALIZATION_STRING
64  * @brief Personalization string for the mbedtls RNG
65  */
66 #define PERSONALIZATION_STRING "IOTIVITY_RND"
67
68 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
69
70 #define MAX_STRING_LEN 254
71
72 #define MAX_ROLES_PER_CERT 10
73
74 /* OID for role certificates (1.3.6.1.4.1.44924.1.7) suitable for mbedTLS check */
75 static const char s_ekuRoleOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x06\x01\x04\x01\x82\xDE\x7C\x01\x07";
76
77 /**
78  * Generates elliptic curve keypair.
79  *
80  * @param[out]  pk    mbedtls public key container
81  *
82  * @return  0 on success or <0 on error
83  */
84 static int GenerateEccKeyPair(mbedtls_pk_context *pk)
85 {
86     int ret = 0;
87     mbedtls_entropy_context entropy;
88     mbedtls_ctr_drbg_context ctr_drbg;
89
90     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
91     VERIFY_NON_NULL_RET(pk, TAG, "Param pk is NULL", -1);
92
93     // Initialize the DRBG context
94     mbedtls_ctr_drbg_init(&ctr_drbg);
95     mbedtls_entropy_init(&entropy);
96     ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
97                                 &entropy, (const unsigned char *)PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING));
98
99     if (0 > ret)
100     {
101         OIC_LOG_V(ERROR, TAG, "Seed initialization failed! %d", ret);
102         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
103         goto exit;
104     }
105     mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
106     ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
107     if (0 > ret)
108     {
109         OIC_LOG_V(ERROR, TAG, "mbedtls_pk_setup error %d", ret);
110         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
111         goto exit;
112     }
113     ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*pk), mbedtls_ctr_drbg_random, &ctr_drbg);
114     if (0 > ret)
115     {
116         OIC_LOG(ERROR, TAG, "mbedtls_ecp_gen_keypair error");
117         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
118         goto exit;
119     }
120
121 exit:
122
123     mbedtls_ctr_drbg_free(&ctr_drbg);
124     mbedtls_entropy_free(&entropy);
125
126     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
127     return 0;
128 }
129
130 /**
131  * Generates certificate signing request for given key pair.
132  *
133  * @param[in]  subject        CSR Subject names should contain a comma-separated list of OID types and values:
134  *                            e.g. "C=UA,O=ABC,CN=uuid:32323232-3232-3232-3232-323232323232"
135  * @param[in]  key            Public/private key pair to generate for.
136  * @param[in]  encoding       Encoding to use; valid values are OIC_ENCODING_PEM and OIC_ENCODING_DER
137  * @param[out] csr            certificate signing request in the requested encoding
138  *
139  * @return  0 on success or <0 on error
140  */
141 static int GenerateCSRForKey(const char *subject, mbedtls_pk_context* key, OicEncodingType_t encoding, OCByteString *csr)
142 {
143     int ret = 0;
144     unsigned char buf[2048];
145     mbedtls_entropy_context entropy;
146     mbedtls_ctr_drbg_context ctr_drbg;
147     mbedtls_x509write_csr req;
148
149     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
150     VERIFY_NON_NULL_RET(subject, TAG, "Param subject is NULL", -1);
151     VERIFY_NON_NULL_RET(csr, TAG, "Param csr is NULL", -1);
152
153     if ((OIC_ENCODING_PEM != encoding) && (OIC_ENCODING_DER != encoding))
154     {
155         OIC_LOG(ERROR, TAG, "Unsupported encoding requested");
156         return -1;
157     }
158
159     // Initialize all data structures up front so the error path can always free them safely, no
160     // matter where the error exit point.
161     mbedtls_x509write_csr_init(&req);
162     mbedtls_ctr_drbg_init(&ctr_drbg);
163     mbedtls_entropy_init(&entropy);
164     csr->bytes = NULL;
165
166     // Initialize CSR context
167     // Set up MD algorithm, key and subject to CSR
168     mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
169     mbedtls_x509write_csr_set_key(&req, key);
170     ret = mbedtls_x509write_csr_set_subject_name(&req, subject);
171     if (0 > ret)
172     {
173         OIC_LOG_V(ERROR, TAG, "mbedtls_x509write_csr_set_subject_name error %d", ret);
174         goto exit;
175     }
176
177     // Initialize the DRBG context
178     ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
179                                 &entropy, (const unsigned char *)PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING));
180     if (0 > ret)
181     {
182         OIC_LOG_V(ERROR, TAG, "Seed initialization failed! %d", ret);
183         goto exit;
184     }
185     mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
186
187     // Create CSR
188     if (OIC_ENCODING_PEM == encoding)
189     {
190         ret = mbedtls_x509write_csr_pem(&req, buf, sizeof(buf),
191                                         mbedtls_ctr_drbg_random, &ctr_drbg);
192
193         // In the PEM case, success is always denoted by a zero return. We have to compute the length.
194         if (0 != ret)
195         {
196             OIC_LOG_V(ERROR, TAG, "mbedtls_x509write_csr_pem error %d", ret);
197             goto exit;
198         }
199         else
200         {
201             csr->len = strlen((const char *)buf) + 1;
202             csr->bytes = (uint8_t *)OICMalloc(csr->len);
203             if (NULL == csr->bytes)
204             {
205                 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on csr allocation");
206                 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
207                 goto exit;
208             }
209             memcpy(csr->bytes, buf, csr->len);
210         }
211     }
212     else // encoding == OIC_ENCODING_DER
213     {
214         ret = mbedtls_x509write_csr_der(&req, buf, sizeof(buf),
215                                         mbedtls_ctr_drbg_random, &ctr_drbg);
216
217         // In the DER case, ret is the number of bytes written.
218         if (0 > ret)
219         {
220             OIC_LOG_V(ERROR, TAG, "mbedtls_x509write_csr_der error %d", ret);
221             goto exit;
222         }
223         else
224         {
225             csr->len = ret;
226             csr->bytes = (uint8_t *)OICMalloc(csr->len);
227             if (NULL == csr->bytes)
228             {
229                 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on csr allocation");
230                 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
231                 goto exit;
232             }
233             // DER data gets written to the end of the buffer.
234             memcpy(csr->bytes, buf + sizeof(buf) - csr->len, csr->len);
235             ret = 0;
236         }
237     }
238
239
240
241 exit:
242
243     if (0 > ret)
244     {
245         OICFree(csr->bytes);
246         csr->bytes = NULL;
247         csr->len = 0;
248     }
249
250     mbedtls_entropy_free(&entropy);
251     mbedtls_ctr_drbg_free(&ctr_drbg);
252     mbedtls_x509write_csr_free(&req);
253
254     OICClearMemory(buf, sizeof(buf));
255
256     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
257     return ret;
258 }
259
260 int OCInternalCSRRequest(const char *subject, mbedtls_pk_context *keyPair, OicEncodingType_t encoding, OCByteString *csr)
261 {
262     return GenerateCSRForKey(subject, keyPair, encoding, csr);
263 }
264
265 int OCInternalGenerateKeyPair(mbedtls_pk_context *keyPair)
266 {
267     return GenerateEccKeyPair(keyPair);
268 }
269
270 OCStackResult OCInternalIsValidRoleCertificate(const uint8_t *buf, size_t bufLen,
271                                                uint8_t **pubKey, size_t *pubKeyLen)
272 {
273     OCStackResult res = OC_STACK_ERROR;
274     mbedtls_x509_crt parsedCert;
275
276     OIC_LOG(DEBUG, TAG, "OCInternalIsValidRoleCertificate IN");
277
278     mbedtls_x509_crt_init(&parsedCert);
279     int mbedRet = mbedtls_x509_crt_parse(&parsedCert, buf, bufLen);
280     if (0 > mbedRet)
281     {
282         OIC_LOG(ERROR, TAG, "Could not parse cert chain");
283         goto exit;
284     }
285
286     /* We opt to require an EKU extension to be present; all-purposes certs are not allowed.
287      * mbedtls_x509_crt_check_extended_key_usage will return success if the EKU extension is absent,
288      * so we check this separately first.
289      */
290     if ((parsedCert.ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0)
291     {
292         OIC_LOG(ERROR, TAG, "EKU extension is absent. We require it to be present.");
293         res = OC_STACK_INVALID_PARAM;
294         goto exit;
295     }
296
297     /* The subject alternative name extension must also be present. */
298     if ((parsedCert.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) == 0)
299     {
300         OIC_LOG(ERROR, TAG, "Subject alternative name is absent, and is required in a role certificate.");
301         res = OC_STACK_INVALID_PARAM;
302         goto exit;
303     }
304
305     mbedRet = mbedtls_x509_crt_check_extended_key_usage(&parsedCert, s_ekuRoleOid, MBEDTLS_OID_SIZE(s_ekuRoleOid));
306     if (0 > mbedRet)
307     {
308         OIC_LOG_V(ERROR, TAG, "Role EKU is absent: %d", mbedRet);
309         res = OC_STACK_INVALID_PARAM;
310         goto exit;
311     }
312
313     bool valid = false;
314     /* Check for at least one subjAltName with a role in it. */
315     for (const mbedtls_x509_general_names *nameCur = &parsedCert.subject_alt_names;
316             NULL != nameCur;
317             nameCur = nameCur->next)
318     {
319         if (MBEDTLS_X509_GENERALNAME_DIRECTORYNAME == nameCur->general_name.name_type)
320         {
321             /* Name must contain a CN component. OU is optional. Anything else is ignored
322              * but not grounds for rejection.
323              */
324             for (const mbedtls_x509_name *dirName = nameCur->general_name.directory_name;
325                     NULL != dirName;
326                     dirName = dirName->next)
327             {
328                 if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN) == dirName->oid.len) &&
329                     (0 == memcmp(MBEDTLS_OID_AT_CN, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN))))
330                 {
331                     if (dirName->val.len >= ROLEID_LENGTH)
332                     {
333                         OIC_LOG_V(ERROR, TAG, "Certificate has role id that is too long: %" PRIuPTR, dirName->val.len);
334                         res = OC_STACK_INVALID_PARAM;
335                         goto exit;
336                     }
337
338                     valid = true;
339                 }
340                 else if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT) == dirName->oid.len) &&
341                             (0 == memcmp(MBEDTLS_OID_AT_ORG_UNIT, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT))))
342                 {
343                     if (dirName->val.len >= ROLEAUTHORITY_LENGTH)
344                     {
345                         OIC_LOG_V(ERROR, TAG, "Certificate has role authority that is too long: %" PRIuPTR, dirName->val.len);
346                         res = OC_STACK_INVALID_PARAM;
347                         goto exit;
348                     }
349                     /* Presence of OU does not affect validity, so don't set valid flag. */
350                 }
351                 else
352                 {
353                     OIC_LOG(WARNING, TAG, "Directory name has attribute that isn't CN or OU; ignoring");
354                 }
355             }
356         }
357
358         if (valid)
359         {
360             break;
361         }
362     }
363
364     if (!valid)
365     {
366         OIC_LOG(ERROR, TAG, "Could not find valid role encoded in a subject alternative name");
367         res = OC_STACK_INVALID_PARAM;
368         goto exit;
369     }
370
371     /* If the public key is requested, extract it. */
372     if (NULL != pubKey)
373     {
374         unsigned char tmp[1024] = { 0 };
375         mbedRet = mbedtls_pk_write_pubkey_der(&parsedCert.pk, tmp, sizeof(tmp));
376         if (0 > mbedRet)
377         {
378             OIC_LOG_V(ERROR, TAG, "Could not write public key as DER: %d", mbedRet);
379             res = OC_STACK_ERROR;
380             goto exit;
381         }
382
383         /* mbedRet is the amount of data written, and it's written at the END of the buffer. */
384         *pubKey = (uint8_t *)OICCalloc(1, mbedRet);
385         if (NULL == *pubKey)
386         {
387             OIC_LOG(ERROR, TAG, "No memory allocating pubKey");
388             res = OC_STACK_NO_MEMORY;
389             goto exit;
390         }
391         memcpy(*pubKey, tmp + sizeof(tmp) - mbedRet, mbedRet);
392         *pubKeyLen = mbedRet;
393     }
394
395     res = OC_STACK_OK;
396
397 exit:
398
399     mbedtls_x509_crt_free(&parsedCert);
400
401     OIC_LOG_V(DEBUG, TAG, "OCInternalIsValidRoleCertificate OUT; returning %d", res);
402     return res;
403 }
404
405 OCStackResult OCInternalIsValidCertChain(const uint8_t *buf, size_t bufLen)
406 {
407     OCStackResult res = OC_STACK_ERROR;
408     int mbedRet;
409     mbedtls_x509_crt parsedCert;
410
411     OIC_LOG(DEBUG, TAG, "OCInternalIsValidCertChain IN");
412
413     mbedtls_x509_crt_init(&parsedCert);
414     mbedRet = mbedtls_x509_crt_parse(&parsedCert, buf, bufLen);
415     if (0 > mbedRet)
416     {
417         OIC_LOG_V(ERROR, TAG, "Failed to parse certificate chain: %d", mbedRet);
418         res = OC_STACK_INVALID_PARAM;
419     }
420     else
421     {
422         res = OC_STACK_OK;
423         if (0 < mbedRet)
424         {
425             OIC_LOG_V(WARNING, TAG, "Partly successful: mbedTLS returned %d", mbedRet);
426         }
427     }
428
429     mbedtls_x509_crt_free(&parsedCert);
430
431     OIC_LOG_V(DEBUG, TAG, "OCInternalIsValidCertChain OUT; returning %d", res);
432
433     return res;
434 }
435
436 static const mbedtls_x509_crt_profile s_certProfile = {
437     MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),            /* MD algorithms */
438     MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY) |            /* Allowed key types */
439     MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA),
440     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1),     /* EC curves */
441     0                                                   /* RSA minimum key length - not used because we only use EC key pairs */
442 };
443
444 OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChain,
445                                               const ByteArrayLL_t *trustedCaCerts,
446                                               OicSecRole_t **roles, size_t *rolesLength,
447                                               struct tm *notValidAfter)
448 {
449     bool freeData = false;
450     uint8_t *data = certificateChain->data;
451     size_t dataLength = certificateChain->len;
452
453     VERIFY_NOT_NULL_RETURN(TAG, certificateChain, ERROR, OC_STACK_INVALID_PARAM);
454     VERIFY_NOT_NULL_RETURN(TAG, trustedCaCerts, ERROR, OC_STACK_INVALID_PARAM);
455     VERIFY_NOT_NULL_RETURN(TAG, roles, ERROR, OC_STACK_INVALID_PARAM);
456     VERIFY_NOT_NULL_RETURN(TAG, rolesLength, ERROR, OC_STACK_INVALID_PARAM);
457     VERIFY_NOT_NULL_RETURN(TAG, notValidAfter, ERROR, OC_STACK_INVALID_PARAM);
458
459     OCStackResult res = OC_STACK_ERROR;
460     int mbedRet;
461     uint32_t flags = 0;
462     mbedtls_x509_crt certChain, trustedCas;
463
464     OicSecRole_t rolesTmp[MAX_ROLES_PER_CERT];
465     memset(rolesTmp, 0, sizeof(rolesTmp));
466     size_t rolesTmpCount = 0;
467
468     OIC_LOG(DEBUG, TAG, "OCInternalVerifyRoleCertificate IN");
469
470     if ((dataLength > 0) && (data[dataLength - 1] != 0))
471     {
472         /* mbedtls_x509_crt_parse requires null terminator */
473         data = OICMalloc(dataLength + 1);
474
475         if (data == NULL)
476         {
477             OIC_LOG_V(ERROR, TAG, "%s: OICMalloc failed", __func__);
478             res = OC_STACK_NO_MEMORY;
479             goto exit;
480         }
481
482         OIC_LOG(DEBUG, TAG, "Adding null terminator");
483         memcpy(data, certificateChain->data, dataLength);
484         data[dataLength] = 0;
485         dataLength++;
486         freeData = true;
487     }
488
489     mbedtls_x509_crt_init(&certChain);
490     mbedtls_x509_crt_init(&trustedCas);
491
492     res = OCInternalIsValidRoleCertificate(data, dataLength, NULL, NULL);
493     if (OC_STACK_OK != res)
494     {
495         OIC_LOG_V(ERROR, TAG, "Certificate is not valid as a role certificate: %d", res);
496         goto exit;
497     }
498
499     mbedRet = mbedtls_x509_crt_parse(&certChain, data, dataLength);
500     if (0 > mbedRet)
501     {
502         OIC_LOG_V(ERROR, TAG, "Could not parse certificates: %d", mbedRet);
503         res = OC_STACK_ERROR;
504         goto exit;
505     }
506
507     int errNum;
508     int count = ParseChain(&trustedCas, trustedCaCerts, &errNum);
509     if (0 >= count)
510     {
511         OIC_LOG(WARNING, TAG, "Could not parse trusted CA certs");
512         res = OC_STACK_ERROR;
513         goto exit;
514     }
515     if (0 != errNum)
516     {
517         OIC_LOG_V(WARNING, TAG, "Trusted CA certs parsing error: %d certs failed to parse", errNum);
518         res = OC_STACK_ERROR;
519         goto exit;
520     }
521
522     mbedRet = mbedtls_x509_crt_verify_with_profile(
523         &certChain,
524         &trustedCas,
525         NULL,
526         &s_certProfile,
527         NULL,
528         &flags,
529         NULL,
530         NULL);
531     if (0 > mbedRet)
532     {
533         OIC_LOG_V(ERROR, TAG, "Failed to verify certificate: ret = %d, flags = %u", mbedRet, flags);
534         res = OC_STACK_INVALID_PARAM;
535         goto exit;
536     }
537
538     /* Certificate is verified. If requested, extract the list of roles and return.
539      * The first certificate in the certChain list is the leaf, since we parsed it first.
540      */
541     if (NULL != roles)
542     {
543         for (const mbedtls_x509_general_names *nameCur = &certChain.subject_alt_names;
544              (NULL != nameCur) && (rolesTmpCount < MAX_ROLES_PER_CERT);
545              nameCur = nameCur->next)
546         {
547             if (MBEDTLS_X509_GENERALNAME_DIRECTORYNAME == nameCur->general_name.name_type)
548             {
549                 bool advanceCount = false;
550                 bool addAuthority = true;
551                 for (const mbedtls_x509_name *dirName = nameCur->general_name.directory_name;
552                      NULL != dirName;
553                      dirName = dirName->next)
554                 {
555                     if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN) == dirName->oid.len) &&
556                         (0 == memcmp(MBEDTLS_OID_AT_CN, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN))) &&
557                         (rolesTmp[rolesTmpCount].id[0] == '\0'))
558                     {
559                         /* When checking validity above, we made sure the role ID and authority were not too
560                          * long to fit in an OicSecRole_t. Here we only assert, but don't check again in release code.
561                          * id was also initialized as all zeroes, so the string will automatically be null-terminated.
562                          */
563                         assert(dirName->val.len < ROLEID_LENGTH);
564                         memcpy(rolesTmp[rolesTmpCount].id, dirName->val.p, dirName->val.len);
565                         advanceCount = true;
566                     }
567                     else if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT) == dirName->oid.len) &&
568                              (0 == memcmp(MBEDTLS_OID_AT_ORG_UNIT, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT)))&&
569                              (rolesTmp[rolesTmpCount].authority[0] == '\0'))
570                     {
571                         assert(dirName->val.len < ROLEID_LENGTH);
572                         memcpy(rolesTmp[rolesTmpCount].authority, dirName->val.p, dirName->val.len);
573                         addAuthority = false;
574                     }
575                 }
576
577                 if (advanceCount)
578                 {
579                     /* If the authority was absent in the subject alternative name we know that the certificate
580                      * issuer defined the role. We add the issuer as the authority here so that access checks
581                      * function properly when invoked.
582                      */
583                     if (addAuthority)
584                     {
585                         for (const mbedtls_x509_name *issuerName = &certChain.issuer;
586                              NULL != issuerName;
587                              issuerName = issuerName->next)
588                         {
589                             if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN) == issuerName->oid.len) &&
590                                 (0 == memcmp(MBEDTLS_OID_AT_CN, issuerName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN))))
591                             {
592                                 assert(issuerName->val.len < ROLEID_LENGTH);
593                                 memcpy(rolesTmp[rolesTmpCount].authority, issuerName->val.p, issuerName->val.len);
594                                 OIC_LOG_V(DEBUG, TAG, "Adding authority %s to role", rolesTmp[rolesTmpCount].authority);
595                             }
596                         }
597                     }
598
599                     rolesTmpCount++;
600                 }
601             }
602         }
603
604         if (MAX_ROLES_PER_CERT <= rolesTmpCount)
605         {
606             OIC_LOG(ERROR, TAG, "More roles than supported in a single certificate");
607             res = OC_STACK_ERROR;
608             goto exit;
609         }
610         else if (0 == rolesTmpCount)
611         {
612             OIC_LOG(ERROR, TAG, "No roles in the certificate");
613             res = OC_STACK_ERROR;
614             goto exit;
615         }
616
617         *roles = (OicSecRole_t *)OICCalloc(1, sizeof(OicSecRole_t) * rolesTmpCount);
618         if (NULL == *roles)
619         {
620             OIC_LOG(ERROR, TAG, "No memory allocating roles array");
621             res = OC_STACK_NO_MEMORY;
622             goto exit;
623         }
624
625         memcpy(*roles, rolesTmp, sizeof(rolesTmp[0]) * rolesTmpCount);
626         *rolesLength = rolesTmpCount;
627     }
628
629     memset(notValidAfter, 0, sizeof(*notValidAfter));
630
631     notValidAfter->tm_year = certChain.valid_to.year - 1900;
632     notValidAfter->tm_mon = certChain.valid_to.mon - 1;
633     notValidAfter->tm_mday = certChain.valid_to.day;
634     notValidAfter->tm_hour = certChain.valid_to.hour;
635     notValidAfter->tm_min = certChain.valid_to.min;
636     notValidAfter->tm_sec = certChain.valid_to.sec;
637
638     res = OC_STACK_OK;
639
640 exit:
641
642     mbedtls_x509_crt_free(&trustedCas);
643     mbedtls_x509_crt_free(&certChain);
644
645     if (freeData) {
646         OICFree(data);
647     }
648
649     OIC_LOG_V(DEBUG, TAG, "OCInternalVerifyRoleCertificate out: %d", res);
650
651     return res;
652 }