examples: Add notice about using experimental API
[iotivity.git] / resource / csdk / security / provisioning / sample / autoprovisioningclient.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 /*
22  * This file is derived from iotivity\resource\csdk\security\provisioning\sample\provisioningclient.c
23  * That program is interactive, and requires user input to perform provisioning
24  * steps, while this version takes input on the command line and executes a
25  * sequence of provisioning operations automatically, then exists, reporting
26  * whether the sequence succeeded.  This is so that we can script provisioning
27  * for testing.
28  */
29
30 #include "iotivity_config.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdint.h>
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include "utlist.h"
39 #include "oic_malloc.h"
40 #include "oic_string.h"
41 #include "ocprovisioningmanager.h"
42 #include "oxmjustworks.h"
43 #include "oxmrandompin.h"
44 #include "srmutility.h"
45 #include "pmtypes.h"
46 #include "oxmverifycommon.h"
47 #include "occertutility.h"
48 #include "ocsecurity.h"
49 #include "ocstackinternal.h"
50 #include "pmutility.h"
51
52 #ifdef _MSC_VER
53 #include <io.h>
54
55 #define F_OK 0
56 #define access _access_s
57 #endif
58
59 /// This example is using experimental API, so there is no guarantee of support for future release,
60 /// nor any there any guarantee that breaking changes will not occur across releases.
61 #include "experimental/logger.h"
62 #include "experimental/payload_logging.h"
63 #include "experimental/ocrandom.h"
64
65 #ifdef __cplusplus
66 extern "C"
67 {
68 #endif //__cplusplus
69
70 #define DISCOVERY_TIMEOUT   3  // 3 sec
71 #define CALLBACK_TIMEOUT    60  // 1 min
72 #define TAG "autoprovisioningclient"
73
74 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
75         // '_' for separaing from the same constant variable in |srmresourcestrings.c|
76 static const char* PRVN_DB_FILE_NAME = "oic_autoprvn_mng.db";
77
78 static const char* TEST_CERT_NOT_BEFORE = "20170101000000"; // Not before field for certificates, in format YYYYMMDDhhmmss
79 static const char* TEST_CERT_NOT_AFTER = "20270101000000";  // + ten years
80 static const char* TEST_CERT_ROLE1 = "IoTivity-test-role1";
81 static const char* TEST_CERT_ROLE2 = "IoTivity-test-role2";
82 static const char* TEST_CERT_AUTHORITY = "IoTivity-test-OBT-authority-name";
83
84 // |g_ctx| means provision manager application context and
85 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
86 // for accessing all function(s) for these, they are declared on global domain
87 static char* g_ctx = "Provision Manager Client Application Context";
88 static char* g_svr_fname;
89 static char* g_prvn_fname;
90 static OCProvisionDev_t* g_own_list;
91 static OCProvisionDev_t* g_unown_list;
92 static int g_own_cnt;
93 static int g_unown_cnt;
94 static char* g_csr;    /* Certificate signing request from device */
95 static OicUuid_t g_uuidDev1;
96 static char* g_idPublicKey = NULL;
97
98 static volatile bool g_doneCB;    /* Set to true by the callback to indicate it completed. */
99 static bool g_successCB; /* Set to true by the callback to indicate success. */
100
101 // function declaration(s) for calling them before implementing
102 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
103 static int printDevList(const OCProvisionDev_t*);
104 static size_t printResultList(const OCProvisionResult_t*, const size_t);
105 static void printUuid(const OicUuid_t*);
106 static int saveUuid(const OCProvisionResult_t* rslt_lst, const size_t rslt_cnt);
107 static FILE* fopen_prvnMng(const char*, const char*);
108 static int waitCallbackRet(void);
109
110 /*
111  * Test CA key and certificate created with
112  * iotivity/resource/csdk/security/scripts/test_cert_generation.sh
113  */
114 static const char* g_caCertPem = "-----BEGIN CERTIFICATE-----\n"
115 "MIIBfjCCASSgAwIBAgIJAPQXoGTceaW5MAoGCCqGSM49BAMCMBkxFzAVBgNVBAoM\n"
116 "DklvVGl2aXR5VGVzdENBMB4XDTE3MDMxNTAwNTExOVoXDTMwMTEyMjAwNTExOVow\n"
117 "GTEXMBUGA1UECgwOSW9UaXZpdHlUZXN0Q0EwWTATBgcqhkjOPQIBBggqhkjOPQMB\n"
118 "BwNCAARvYPdt+LjqASlHoc2zrjo3hHGjZsI31c+bg9AwINW5TuRZsE03w/Ejotza\n"
119 "y4VDLImMlDhGP+K/f6OmKD3FNHhKo1UwUzAhBgNVHSUEGjAYBgorBgEEAYLefAEG\n"
120 "BgorBgEEAYLefAEHMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNw+hm69Rxb5\n"
121 "UpclERf5r85g1nwmMAoGCCqGSM49BAMCA0gAMEUCIQDbvNLA3ZkwEzuoH6XUR6JS\n"
122 "UzZTVgsDgnJcOqtqOg0qEAIgUJR2g8XlMxqiuXP7JdwALdtnvCQTlJQbuD1gu+Jy\n"
123 "AdQ=\n"
124 "-----END CERTIFICATE-----\n";
125
126 static const char* g_caKeyPem = "-----BEGIN EC PRIVATE KEY-----\n"
127 "MHcCAQEEILx9VOHDrMYuan6SXN4CQIHHXNq6SjzanaDFDgIaOaXloAoGCCqGSM49\n"
128 "AwEHoUQDQgAEb2D3bfi46gEpR6HNs646N4Rxo2bCN9XPm4PQMCDVuU7kWbBNN8Px\n"
129 "I6Lc2suFQyyJjJQ4Rj/iv3+jpig9xTR4Sg==\n"
130 "-----END EC PRIVATE KEY-----\n";
131
132
133 /* At a few places in this file, warning 4028 is incorrectly produced, disable it for the whole file. */
134 #ifdef _MSC_VER
135 #pragma warning( disable : 4028)
136 #endif
137
138 // callback function(s) for provisioning client using C-level provisioning API
139 static void ownershipTransferCB(void* ctx, size_t nOfRes, OCProvisionResult_t* arr, bool hasError)
140 {
141     g_successCB = false;
142     if(!hasError)
143     {
144         OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
145         if (saveUuid((const OCProvisionResult_t*)arr, nOfRes) == 0)
146         {
147             g_successCB = true;
148         }
149     }
150     else
151     {
152         OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
153         printResultList((const OCProvisionResult_t*) arr, nOfRes);
154         g_successCB = false;
155     }
156     g_doneCB = true;
157 }
158
159 static void provisionCredCB(void* ctx, size_t nOfRes, OCProvisionResult_t* arr, bool hasError)
160 {
161     if(!hasError)
162     {
163         OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
164         g_successCB = true;
165     }
166     else
167     {
168         OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
169         printResultList((const OCProvisionResult_t*) arr, nOfRes);
170         g_successCB = false;
171     }
172     g_doneCB = true;
173 }
174
175 /* Function of type OCProvisionResultCB from \resource\csdk\security\provisioning\include\pmtypes.h */
176 void provisionTrustChainCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
177 {
178     if(!hasError)
179     {
180         OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*)ctx);
181         g_successCB = true;
182     }
183     else
184     {
185         OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*)ctx);
186         printResultList((const OCProvisionResult_t*)arr, nOfRes);
187         g_successCB = false;
188     }
189     g_doneCB = true;
190 }
191
192 static void getCsrForCertProvCB(void* ctx, size_t nOfRes, OCPMGetCsrResult_t* arr, bool hasError)
193 {
194     g_successCB = false;
195
196     if (!hasError)
197     {
198         if (nOfRes != 1)
199         {
200             OIC_LOG_V(ERROR, TAG, "getCsrForCertProvCB FAILED - ctx: %s", (char*)ctx);
201             goto exit;
202         }
203
204         if (arr[0].encoding == OIC_ENCODING_DER)
205         {
206             OCStackResult res = OCConvertDerCSRToPem((char*)arr[0].csr, arr[0].csrLen, &g_csr);
207             if (res != OC_STACK_OK)
208             {
209                 OIC_LOG_V(ERROR, TAG, "getCsrForCertProvCB FAILED (CSR re-encoding failed) - error: %d, ctx: %s", res, (char*)ctx);
210                 goto exit;
211             }
212             g_successCB = true;
213         }
214         else if (arr[0].encoding == OIC_ENCODING_PEM)
215         {
216             g_csr = (char*)OICCalloc(1, arr[0].csrLen);
217             if (g_csr == NULL)
218             {
219                 OIC_LOG_V(ERROR, TAG, "getCsrForCertProvCB FAILED (memory allocation) - ctx: %s", (char*)ctx);
220                 goto exit;
221             }
222
223             memcpy(g_csr, arr[0].csr, arr[0].csrLen);
224
225             OIC_LOG(INFO, TAG, "getCsrForCertProvCB success");
226             g_successCB = true;
227         }
228         else
229         {
230             OIC_LOG_V(ERROR, TAG, "getCsrForCertProvCB FAILED (unknown encoding) - ctx: %s", (char*)ctx);
231             goto exit;
232         }
233     }
234     else
235     {
236         OIC_LOG_V(ERROR, TAG, "getCsrForCertProvCB FAILED - ctx: %s", (char*)ctx);
237     }
238
239 exit:
240     g_doneCB = true;
241 }
242
243 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
244     OCClientResponse* clientResponse)
245 {
246     OC_UNUSED(ctx);
247     OC_UNUSED(handle);
248
249     g_doneCB = true;
250     g_successCB = false;
251
252     if (clientResponse == NULL)
253     {
254         OIC_LOG(ERROR, TAG, "getReqCB received NULL clientResponse");
255         return OC_STACK_DELETE_TRANSACTION;
256     }
257
258     if (clientResponse->result != OC_STACK_OK)
259     {
260         OIC_LOG_V(ERROR, TAG, "getReqCB response %d", clientResponse->result);
261         return OC_STACK_DELETE_TRANSACTION;
262     }
263
264     g_successCB = true;
265
266     return OC_STACK_DELETE_TRANSACTION;
267 }
268
269 static void provisionAclCB(void* ctx, size_t nOfRes, OCProvisionResult_t* arr, bool hasError)
270 {
271     if (!hasError)
272     {
273         OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*)ctx);
274         g_successCB = true;
275     }
276     else
277     {
278         OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*)ctx);
279         printResultList((const OCProvisionResult_t*)arr, nOfRes);
280         g_successCB = false;
281     }
282     g_doneCB = true;
283 }
284
285 static void assertRolesCB(void* ctx, bool hasError)
286 {
287     OC_UNUSED(ctx); // unused in release builds
288
289     if (!hasError)
290     {
291         OIC_LOG_V(INFO, TAG, "%s: Asserting roles SUCCEEDED - ctx: %s", __func__, (char*)ctx);
292         g_successCB = true;
293     }
294     else
295     {
296         OIC_LOG_V(DEBUG, TAG, "%s: Asserting roles FAILED - ctx: %s", __func__, (char*)ctx);
297         g_successCB = false;
298     }
299     g_doneCB = true;
300 }
301
302 // function(s) for provisioning client using C-level provisioning API
303 static int initProvisionClient(void)
304 {
305     // initialize persistent storage for SVR DB
306     static OCPersistentStorage pstStr =
307     {
308         .open = fopen_prvnMng,
309         .read = fread,
310         .write = fwrite,
311         .close = fclose,
312         .unlink = remove
313     };
314     if (OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
315     {
316         OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
317         return -1;
318     }
319
320     // initialize OC stack and provisioning manager
321     if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
322     {
323         OIC_LOG(ERROR, TAG, "OCStack init error");
324         return -1;
325     }
326
327     if (access(PRVN_DB_FILE_NAME, F_OK) == 0)
328     {
329         printf("************************************************************\n");
330         printf("************Provisioning DB file already exists.************\n");
331         printf("************************************************************\n");
332     }
333     else
334     {
335         printf("*************************************************************\n");
336         printf("************No provisioning DB file, creating new************\n");
337         printf("*************************************************************\n");
338     }
339
340     if (OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
341     {
342         OIC_LOG(ERROR, TAG, "OC_PM init error");
343         return -1;
344     }
345
346     return 0;
347 }
348
349 /* In some tests we need to close existing sessions after making a change
350  * in order for the effect of the change to take effect. This function shuts
351  * down the OC stack and restarts it.
352  */
353 static int closeAllSessions()
354 {
355     if (OC_STACK_OK != OCStop())
356     {
357         OIC_LOG_V(ERROR, TAG, "%s: OCStack stop error", __func__);
358         return -1;
359     }
360
361     if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
362     {
363         OIC_LOG_V(ERROR, TAG, "%s: OCStack init error", __func__);
364         return -1;
365     }
366
367     return 0;
368 }
369
370 static int discoverAllDevices(void)
371 {
372     // delete un/owned device lists before updating them
373     if(g_own_list)
374     {
375         OCDeleteDiscoveredDevices(g_own_list);
376         g_own_list = NULL;
377     }
378     if(g_unown_list)
379     {
380         OCDeleteDiscoveredDevices(g_unown_list);
381         g_unown_list = NULL;
382     }
383
384     // call |OCGetDevInfoFromNetwork| API
385     printf("   Discovering All Un/Owned Devices on Network..\n");
386     if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
387     {
388         OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
389         return -1;
390     }
391
392     // display the discovered un/owned lists
393     printf("   > Discovered Owned Devices\n");
394     g_own_cnt = printDevList(g_own_list);
395     printf("   > Discovered Unowned Devices\n");
396     g_unown_cnt = printDevList(g_unown_list);
397
398     return 0;
399 }
400
401 static int registerDevices(void)
402 {
403     // check |unown_list| for registering devices
404     if(!g_unown_list || 0>=g_unown_cnt)
405     {
406         OIC_LOG(ERROR, TAG, "Unowned device list empty, must discover unowned devices first");
407         return -1;  // Error, we should have registered unowned devices already
408     }
409
410     // call |OCDoOwnershipTransfer| API
411     // calling this API with callback actually acts like blocking
412     // for error checking, the return value saved and printed
413     g_doneCB = false;
414     printf("   Registering All Discovered Unowned Devices..\n");
415     OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
416     if(OC_STACK_OK != rst)
417     {
418         OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
419         return -1;
420     }
421     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
422     {
423         OIC_LOG(ERROR, TAG, "OCDoOwnershipTransfer callback error");
424         return -1;
425     }
426
427     if(!g_successCB)
428     {
429         OIC_LOG(ERROR, TAG, "OCDoOwnershipTransfer callback failed");
430         return -1;
431     }
432
433     // display the registered result
434     printf("   > Registered Discovered Unowned Devices\n");
435
436     return 0;
437 }
438
439 static int provisionTrustAnchor(int dev_num)
440 {
441     OCProvisionDev_t* targetDevice = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
442     if(targetDevice == NULL)
443     {
444         OIC_LOG(ERROR, TAG, "Error, invalid device %d");
445         return -1;
446     }
447
448     // Install the CA trust anchor locally
449     uint16_t caCredId = 0;
450     OCStackResult rst = OCSaveTrustCertChain((const uint8_t*)g_caCertPem, strlen(g_caCertPem) + 1,
451         OIC_ENCODING_PEM, &caCredId);
452     if (OC_STACK_OK != rst)
453     {
454         OIC_LOG_V(ERROR, TAG, "OCSaveTrustCertChain error: %d", rst);
455         return -1;
456     }
457
458     // Provision the CA root cert to the target device
459     printf("   > Saving root certificate (trust anchor) to selected device..\n");
460     g_doneCB = false;
461     OicSecCredType_t type = SIGNED_ASYMMETRIC_KEY;
462
463     rst = OCProvisionTrustCertChain((void*)g_ctx, type, caCredId, targetDevice, (OCProvisionResultCB)&provisionTrustChainCB);
464     if(OC_STACK_OK != rst)
465     {
466         OIC_LOG_V(ERROR, TAG, "OCProvisionTrustCertChain returned error: %d", rst);
467         return -1;
468     }
469
470     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
471     {
472         OIC_LOG(ERROR, TAG, "OCProvisionTrustCertChain callback error");
473         return -1;
474     }
475     if(!g_successCB)
476     {
477         return -1;
478     }
479
480     printf("   > Provisioned certificate trust anchor\n");
481
482     return 0;
483
484 }
485
486 /* If csr is not null, a copy will be made, and the caller must free it with OICFree. */
487 static int getCsr(int dev_num, char** csr)
488 {
489     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
490     if(!dev)
491     {
492         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
493         goto GETCSR_ERROR;
494     }
495
496     g_doneCB = false;
497     OCStackResult rst = OCGetCSRResource((void*) g_ctx, dev, getCsrForCertProvCB);
498     if(OC_STACK_OK != rst)
499     {
500         OIC_LOG_V(ERROR, TAG, "OCGetCSRResource API error: %d", rst);
501
502         goto GETCSR_ERROR;
503     }
504     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
505     {
506         OIC_LOG(ERROR, TAG, "OCGetCSRResource callback error");
507         goto GETCSR_ERROR;
508     }
509     if(!g_successCB)
510     {
511         return -1;
512     }
513
514     rst = OCVerifyCSRSignature(g_csr);
515     if(rst != OC_STACK_OK)
516     {
517         OIC_LOG(ERROR, TAG, "Failed to validate CSR signature");
518         OICFreeAndSetToNull((void**)&g_csr);
519         return -1;
520     }
521
522     if (csr != NULL)
523     {
524         *csr = OICStrdup(g_csr);
525         if (*csr == NULL)
526         {
527             OIC_LOG(ERROR, TAG, "OICStrdup failed");
528             OICFreeAndSetToNull((void**)&g_csr);
529             return -1;
530         }
531     }
532
533     OICFreeAndSetToNull((void**)&g_csr);
534
535     printf("   > Get CSR SUCCEEDED\n");
536
537     return 0;
538
539 GETCSR_ERROR:
540     printf("   > Get CSR FAILED\n");
541     return -1;
542 }
543
544 static int doGetRequest(const char* uri, int dev_num)
545 {
546     OCStackResult res;
547     OCCallbackData cbData;
548     OCDoHandle handle;
549     OCProvisionDev_t *device = NULL;
550
551     device = getDevInst(g_own_list, dev_num);
552     if (!device)
553     {
554         OIC_LOG(ERROR, TAG, "Selected device does not exist");
555         return -1;
556     }
557     cbData.context = NULL;
558     cbData.cd = NULL;
559     cbData.cb = &getReqCB;
560     OIC_LOG_V(INFO, TAG, "Performing GET on %s", uri);
561     g_doneCB = false;
562
563     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
564     if (!PMGenerateQuery(true,
565         device->endpoint.addr,
566         device->securePort,
567         device->connType,
568         query, sizeof(query), uri))
569     {
570         OIC_LOG_V(ERROR, TAG, "%s : Failed to generate query", __func__);
571         return -1;
572     }
573
574     res = OCDoRequest(&handle, OC_REST_GET, query, NULL, NULL,
575         device->connType, OC_HIGH_QOS, &cbData, NULL, 0);
576
577     if (res != OC_STACK_OK)
578     {
579         OIC_LOG_V(ERROR, TAG, "OCDoRequest returned error %d with method", res);
580     }
581     if (waitCallbackRet())  // input |g_doneCB| flag implicitly
582     {
583         OIC_LOG_V(ERROR, TAG, "%s callback error", __func__);
584     }
585     if (g_successCB)
586     {
587         return 0;
588     }
589
590     return -1;
591 }
592
593 static int provisionCert(int dev_num, char* cert)
594 {
595     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
596     if (!dev)
597     {
598         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
599         return -1;
600     }
601
602     printf("   > Provisioning certificate credential to selected device..\n");
603     g_doneCB = false;
604     OCStackResult rst = OCProvisionCertificate((void *)g_ctx, dev, cert, provisionCredCB);
605     if (OC_STACK_OK != rst)
606     {
607         OIC_LOG_V(ERROR, TAG, "OCProvisionCertificate returned error: %d", rst);
608         return -1;
609     }
610     if (waitCallbackRet())
611     {
612         OIC_LOG_V(ERROR, TAG, "%s failed waiting for callback", __func__);
613         return -1;
614     }
615     if (!g_successCB)
616     {
617         OIC_LOG_V(ERROR, TAG, "%s callback completed, but failed", __func__);
618         return -1;
619     }
620
621     printf("   > Provision cert SUCCEEDED\n");
622
623     return 0;
624 }
625
626 /*
627  * Create a role or identity certificate for a device, based on the information in its CSR.
628  * Assumes the CSR has already been validated wtih OCVerifyCSRSignature.
629  * If role is not NULL, a role certificate is created, otherwise an identity certificate
630  * is created.
631  */
632 static int createCertFromCSR(const char* caKeyPem, const char* caCertPem, char* csr,
633     const char* role, const char* authority, char** deviceCert)
634 {
635     char* publicKey = NULL;
636     char* serial = NULL;
637     size_t serialLen;
638     OicUuid_t uuid = { 0 };
639     OCStackResult res = OC_STACK_ERROR;
640
641     res = OCGetUuidFromCSR(csr, &uuid);
642     if (res != OC_STACK_OK)
643     {
644         OIC_LOG_V(ERROR, TAG, "Failed to get UUID from CSR, error: %d", res);
645         goto exit;
646     }
647     /* Note: a real OBT must make sure the UUID isn't already in use on the network. */
648
649     res = OCGetPublicKeyFromCSR(csr, &publicKey);
650     if (res != OC_STACK_OK)
651     {
652         OIC_LOG_V(ERROR, TAG, "Failed to get public key from CSR, error: %d", res);
653         goto exit;
654     }
655
656     res = OCGenerateRandomSerialNumber(&serial, &serialLen);
657     if (res != OC_STACK_OK)
658     {
659         OIC_LOG_V(ERROR, TAG, "OCGenerateRandomSerialNumber failed, error: %d", res);
660         goto exit;
661     }
662
663     size_t deviceCertLen;
664     if (role != NULL)
665     {
666         res = OCGenerateRoleCertificate(
667             &uuid,
668             publicKey,
669             caCertPem,
670             caKeyPem,
671             serial,
672             TEST_CERT_NOT_BEFORE,
673             TEST_CERT_NOT_AFTER,
674             role,
675             authority,
676             deviceCert,
677             &deviceCertLen);
678     }
679     else
680     {
681         res = OCGenerateIdentityCertificate(
682             &uuid,
683             publicKey,
684             caCertPem,
685             caKeyPem,
686             serial,
687             TEST_CERT_NOT_BEFORE,
688             TEST_CERT_NOT_AFTER,
689             deviceCert,
690             &deviceCertLen);
691     }
692     if (res != OC_STACK_OK)
693     {
694         OIC_LOG_V(ERROR, TAG, "Failed generating certificate, error: %d", res);
695         goto exit;
696     }
697
698 exit:
699     OICFree(publicKey);
700     OICFree(serial);
701
702     return (res == OC_STACK_OK) ? 0 : -1;
703 }
704
705 static int setupOwnCert(OicUuid_t* inputUuid)
706 {
707     OCUUIdentity deviceId = { 0 };
708     uint16_t caCredId;
709     char* serial = NULL;
710     size_t serialLen = 0;
711     size_t idPublicKeyLen = 0;
712     char* idKey = NULL;
713     size_t idKeyLen = 0;
714     char* idCert = NULL;
715     size_t idCertLen = 0;
716
717     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
718
719     /* Set our own trust anchor so that we trust certs we've issued. */
720     OCStackResult res = OCSaveTrustCertChain((const uint8_t*)g_caCertPem, strlen(g_caCertPem)+1, OIC_ENCODING_PEM, &caCredId);
721     if (OC_STACK_OK != res)
722     {
723         OIC_LOG_V(ERROR, TAG, "OCSaveTrustCertChain error: %d", res);
724         goto exit;
725     }
726
727     /* Create identity certificate for use by the CA. */
728     res = OCGenerateKeyPair(&g_idPublicKey, &idPublicKeyLen, &idKey, &idKeyLen);
729     if (res != OC_STACK_OK)
730     {
731         OIC_LOG_V(ERROR, TAG, "OCGenerateKeyPair failed, error: %d", res);
732         goto exit;
733     }
734
735     res = OCGenerateRandomSerialNumber(&serial, &serialLen);
736     if (res != OC_STACK_OK)
737     {
738         OIC_LOG_V(ERROR, TAG, "OCGenerateRandomSerialNumber failed, error: %d", res);
739         goto exit;
740     }
741
742     OicUuid_t* uuidForCert = inputUuid;
743     OicUuid_t uuid = { 0 };
744     if (inputUuid == NULL)
745     {
746         res = OCGetDeviceId(&deviceId);
747         if (res != OC_STACK_OK)
748         {
749             OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res);
750             goto exit;
751         }
752         memcpy(uuid.id, deviceId.id, sizeof(uuid.id));
753         uuidForCert = &uuid;
754     }
755
756     OIC_LOG(DEBUG, TAG, "Creating own cert with UUID:");
757     printUuid(uuidForCert);
758
759     res = OCGenerateIdentityCertificate(
760         uuidForCert,
761         g_idPublicKey,
762         g_caCertPem,
763         g_caKeyPem,
764         serial,
765         TEST_CERT_NOT_BEFORE,
766         TEST_CERT_NOT_AFTER,
767         &idCert,
768         &idCertLen);
769     if (res != OC_STACK_OK)
770     {
771         OIC_LOG_V(ERROR, TAG, "Failed to create identity cert for CA, error: %d", res);
772         goto exit;
773     }
774
775     uint16_t idCertCredId = 0;
776     res = OCSaveOwnCertChain(idCert, idKey, &idCertCredId);
777     if (res != OC_STACK_OK)
778     {
779         OIC_LOG_V(ERROR, TAG, "Failed to save CA's identity cert & key, error: %d", res);
780         goto exit;
781     }
782
783 exit:
784     OICFree(serial);
785     if (idKey != NULL)
786     {
787         OICClearMemory(idKey, idKeyLen);
788         OICFree(idKey);
789     }
790     OICFree(idCert);
791
792     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
793
794     return (res == OC_STACK_OK) ? 0 : -1;
795 }
796
797 static int setupOwnRoleCert(OicUuid_t* inputUuid, const char* role, const char* authority)
798 {
799     OCUUIdentity deviceId = { 0 };
800     char* serial = NULL;
801     size_t serialLen = 0;
802     char* roleCert = NULL;
803     size_t roleCertLen = 0;
804
805     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
806
807     if (g_idPublicKey == NULL)
808     {
809         OIC_LOG_V(ERROR, TAG, "%s failed because own public key is NULL, has setupOwnCert been called?", __func__);
810         return -1;
811     }
812
813     /* Create role certificate. */
814     OCStackResult res = OCGenerateRandomSerialNumber(&serial, &serialLen);
815     if (res != OC_STACK_OK)
816     {
817         OIC_LOG_V(ERROR, TAG, "OCGenerateRandomSerialNumber failed, error: %d", res);
818         goto exit;
819     }
820
821     OicUuid_t* uuidForCert = inputUuid;
822     OicUuid_t uuid = { 0 };
823     if (inputUuid == NULL)
824     {
825         res = OCGetDeviceId(&deviceId);
826         if (res != OC_STACK_OK)
827         {
828             OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res);
829             goto exit;
830         }
831         memcpy(uuid.id, deviceId.id, sizeof(uuid.id));
832         uuidForCert = &uuid;
833     }
834
835     OIC_LOG(DEBUG, TAG, "Creating own role cert with UUID:");
836     printUuid(uuidForCert);
837
838     res = OCGenerateRoleCertificate(
839         uuidForCert,
840         g_idPublicKey,
841         g_caCertPem,
842         g_caKeyPem,
843         serial,
844         TEST_CERT_NOT_BEFORE,
845         TEST_CERT_NOT_AFTER,
846         role,
847         authority,
848         &roleCert,
849         &roleCertLen);
850     if (res != OC_STACK_OK)
851     {
852         OIC_LOG_V(ERROR, TAG, "Failed to create role cert, error: %d", res);
853         goto exit;
854     }
855
856     uint16_t roleCertCredId = 0;
857     res = OCSaveOwnRoleCert(roleCert, &roleCertCredId);
858     if (res != OC_STACK_OK)
859     {
860         OIC_LOG_V(ERROR, TAG, "Failed to save role cert, error: %d", res);
861         goto exit;
862     }
863
864 exit:
865     OICFree(serial);
866     OICFree(roleCert);
867
868     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
869
870     return (res == OC_STACK_OK) ? 0 : -1;
871 }
872
873 /*
874  * Create an ACL for the /a/led resource.
875  * Caller must call OCDeleteACLList(newAcl).
876  * The role and authority parameters are optional.  If role is not NULL, a
877  * role-based ACL will be created. Otherwise a subject-based ACL is created.
878  */
879 static int createLedAcl(OicSecAcl_t** newAcl, const char* role, const char* authority)
880 {
881     int ret = -1;
882     OCUUIdentity ownUuid = { 0 };
883     OicSecAcl_t* acl = NULL;
884     OicSecAce_t* ace = NULL;
885     OicSecRsrc_t* rsrc = NULL;
886     const char* resource = "/a/led";
887     const char* resource_type = "core.led";
888     const char* resource_interface = "oic.if.baseline";
889     uint16_t perms = PERMISSION_FULL_CONTROL;
890
891     /* Create an ACL with one ACE */
892     acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
893     if (!acl)
894     {
895         OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (acl)", __func__);
896         goto exit;
897     }
898     ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
899     if (!ace)
900     {
901         OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (ace)", __func__);
902         goto exit;
903     }
904     LL_APPEND(acl->aces, ace);
905
906     if (role != NULL)    /* Create a role-based ACL */
907     {
908         ace->subjectType = OicSecAceRoleSubject;
909         assert(strlen(role) + 1 < ROLEID_LENGTH);
910         memcpy(ace->subjectRole.id, role, strlen(role) + 1);
911
912         if (authority != NULL)
913         {
914             assert(strlen(authority) + 1 < ROLEAUTHORITY_LENGTH);
915             memcpy(ace->subjectRole.authority, role, strlen(authority) + 1);
916         }
917         OIC_LOG_V(DEBUG, TAG, "Creating ACE with role id = %s, authority = %s:", ace->subjectRole.id, ace->subjectRole.authority);
918     }
919     else /* Create a subject based ACL */
920     {
921         /* Set uuid to our own */
922         OCStackResult res = OCGetDeviceId(&ownUuid);
923         if (res != OC_STACK_OK)
924         {
925             OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res);
926             goto exit;
927         }
928         ace->subjectType = OicSecAceUuidSubject;
929         memcpy(ace->subjectuuid.id, ownUuid.id, sizeof(ace->subjectuuid.id));
930
931         OicUuid_t uuid = { 0 };
932         memcpy(uuid.id, ownUuid.id, sizeof(uuid.id));
933         OIC_LOG(DEBUG, TAG, "Creating ACE with UUID:");
934         printUuid(&uuid);
935     }
936
937     /* Add a resource (e.g. '/a/led') to the ACE */
938     rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
939     if (!rsrc)
940     {
941         OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc)", __func__);
942         goto exit;
943     }
944     LL_APPEND(ace->resources, rsrc);
945     rsrc->href = OICStrdup(resource);
946
947     /* Set resource type, e.g., 'core.led' */
948     rsrc->typeLen = 1;
949     rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char*));
950     if (!rsrc->types)
951     {
952         OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc->types)", __func__);
953         goto exit;
954     }
955     rsrc->types[0] = OICStrdup(resource_type);
956
957     /* Set interface, e.g., 'oic.if.baseline' */
958     rsrc->interfaceLen = 1;
959     rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char*));
960     if (!rsrc->interfaces)
961     {
962         OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc->interfaces)", __func__);
963         goto exit;
964     }
965     rsrc->interfaces[0] = OICStrdup(resource_interface);
966
967     if (!rsrc->href || !rsrc->types[0] || !rsrc->interfaces[0])
968     {
969         OIC_LOG_V(ERROR, TAG, "%s: OICStrdup failed", __func__);
970         goto exit;
971     }
972
973     /* Set permission for the ACE */
974     ace->permission = perms;
975
976     ret = 0; /* success */
977     *newAcl = acl;
978
979 exit:
980
981     if (ret != 0)
982     {
983         *newAcl = NULL;
984         OCDeleteACLList(acl);
985     }
986
987     return ret;
988 }
989
990 static int provisionAcl(int dev_num, OicSecAcl_t* acl)
991 {
992     OCStackResult res = OC_STACK_ERROR;
993
994     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
995     if (!dev)
996     {
997         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
998         goto exit;
999     }
1000
1001     g_doneCB = false;
1002     res = OCProvisionACL((void*)g_ctx, dev, acl, provisionAclCB);
1003     if (OC_STACK_OK != res)
1004     {
1005         OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", res);
1006         goto exit;
1007     }
1008     if (waitCallbackRet())
1009     {
1010         OIC_LOG(ERROR, TAG, "OCProvisionACL callback error");
1011         goto exit;
1012     }
1013     if (!g_successCB)
1014     {
1015         OIC_LOG_V(ERROR, TAG, "%s callback completed, but failed", __func__);
1016         goto exit;
1017     }
1018
1019 exit:
1020
1021     return (res == OC_STACK_OK) ? 0 : -1;
1022 }
1023
1024 /* Function to work around IOT-1927.  The ocrandom.h include is only required for the workaround.
1025  * @todo: when IOT-1927 is resolved remove this function
1026  */
1027 int workAroundBug()
1028 {
1029     /* Remove credential for 31313131-3131-3131-3131-313131313131 */
1030     const char* uuidStr = "31313131-3131-3131-3131-313131313131";
1031     OicUuid_t uuid = { 0 };
1032     if (!OCConvertStringToUuid(uuidStr, uuid.id))
1033     {
1034         OIC_LOG(ERROR, TAG, "UUID conversion failed - caller bug, or the .dat file not longer contains a cred for this UUID. ");
1035         return -1;
1036     }
1037
1038     OCStackResult res = OCRemoveCredential(&uuid);
1039     if (res != OC_STACK_RESOURCE_DELETED)
1040     {
1041         OIC_LOG_V(ERROR, TAG, "%s failed to remove credential for subject UUID: ", __func__);
1042         OIC_LOG_BUFFER(DEBUG, TAG, uuid.id, UUID_LENGTH);
1043         return -1;
1044     }
1045
1046     return 0;
1047 }
1048
1049 static int testCertUse(int dev_num)
1050 {
1051     char* csr = NULL;
1052     char* deviceCert = NULL;
1053     const char* uri = "/a/led";
1054     OicSecAcl_t* acl = NULL;
1055
1056     // Make sure we own at least one device to provision
1057     if (!g_own_list || (g_own_cnt == 0))
1058     {
1059         OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
1060         return -1;  // Error, we should have registered unowned devices already
1061     }
1062
1063     /* Provision the device with the CA root, and issue it a cert. */
1064     if (provisionTrustAnchor(dev_num) != 0)
1065     {
1066         return -1;
1067     }
1068
1069     if (getCsr(dev_num, &csr) != 0)
1070     {
1071         return -1;
1072     }
1073
1074     int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &deviceCert);
1075     if (ret != 0)
1076     {
1077         OIC_LOG_V(ERROR, TAG, "%s Failed to create identity certificate", __func__);
1078         goto exit;
1079     }
1080
1081     ret = provisionCert(dev_num, deviceCert);
1082     if (ret != 0)
1083     {
1084         OIC_LOG_V(ERROR, TAG, "%s Failed to provision certificate", __func__);
1085         goto exit;
1086     }
1087
1088     /* Try a GET request, expecting success because the owner credential is used.*/
1089     ret = doGetRequest(uri, dev_num);
1090     if (ret != 0)
1091     {
1092         OIC_LOG_V(ERROR, TAG, "%s failed when requesting %s", __func__, uri);
1093         goto exit;
1094     }
1095
1096     ret = createLedAcl(&acl, NULL, NULL);
1097     if (ret != 0)
1098     {
1099         OIC_LOG_V(ERROR, TAG, "%s failed to create ACL", __func__);
1100         goto exit;
1101     }
1102
1103     /* Provision an ACL on the server, allowing us to access '/a/led' with our cert. */
1104     ret = provisionAcl(dev_num, acl);
1105     if (ret != 0)
1106     {
1107         OIC_LOG_V(ERROR, TAG, "%s failed to provision ACL", __func__);
1108         goto exit;
1109     }
1110
1111     /* Remove the owner credential */
1112     OCStackResult res = OCRemoveCredential(&g_uuidDev1);
1113     if (res != OC_STACK_RESOURCE_DELETED)
1114     {
1115         OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__);
1116         OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH);
1117         ret = -1;
1118         goto exit;
1119     }
1120
1121     /*
1122      * Work around bug IOT-1927
1123      * @todo: When that bug is resolved, remove this call and the function workAroundBug
1124      */
1125     if (workAroundBug() != 0)
1126     {
1127         OIC_LOG_V(ERROR, TAG, "%s bug workaround failed: ", __func__);
1128         ret = -1;
1129         goto exit;
1130     }
1131
1132     /* Close all secure sessions, so that we don't re-use a cached session */
1133     if (closeAllSessions() != 0)
1134     {
1135         OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
1136         ret = -1;
1137         goto exit;
1138     }
1139
1140     /* Try a GET request, expect failure, we don't share a credential. */
1141     ret = doGetRequest(uri, dev_num);
1142     if (ret == 0)
1143     {
1144         OIC_LOG_V(ERROR, TAG, "%s Get request to %s succeeded, but should have failed", __func__, uri);
1145         goto exit;
1146     }
1147
1148     /* Provision ourself a valid certificate credential */
1149     ret = setupOwnCert(NULL);
1150     if (ret != 0)
1151     {
1152         OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__);
1153         goto exit;
1154     }
1155
1156     /* Close all secure sessions again */
1157     if (closeAllSessions() != 0)
1158     {
1159         OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
1160         ret = -1;
1161         goto exit;
1162     }
1163
1164     /* Try a get request, expect success */
1165     ret = doGetRequest(uri, dev_num);
1166     if (ret != 0)
1167     {
1168         OIC_LOG_V(ERROR, TAG, "%s Get request to %s failed, but should have succeeded", __func__, uri);
1169         goto exit;
1170     }
1171
1172 exit:
1173
1174     OICFree(csr);
1175     OICFree(deviceCert);
1176     OCDeleteACLList(acl);
1177
1178     return ret;
1179 }
1180
1181 static int testRoleProvisioning(int dev_num)
1182 {
1183     char* csr = NULL;
1184     char* idCert = NULL;
1185     char* roleCert = NULL;
1186
1187     // Make sure we own at least one device to provision
1188     if (!g_own_list || (g_own_cnt == 0))
1189     {
1190         OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
1191         return -1;  // Error, we should have registered unowned devices already
1192     }
1193
1194     /* Provision the device with the CA root, and issue it a role and identity cert. */
1195     if (provisionTrustAnchor(dev_num) != 0)
1196     {
1197         return -1;
1198     }
1199
1200     if (getCsr(dev_num, &csr) != 0)
1201     {
1202         return -1;
1203     }
1204
1205     int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &idCert);
1206     if (ret != 0)
1207     {
1208         OIC_LOG_V(ERROR, TAG, "%s Failed to create identity certificate", __func__);
1209         goto exit;
1210     }
1211
1212     ret = provisionCert(dev_num, idCert);
1213     if (ret != 0)
1214     {
1215         OIC_LOG_V(ERROR, TAG, "%s Failed to provision id certificate", __func__);
1216         goto exit;
1217     }
1218
1219     /* The first role cert will have no authority field (it's optional) */
1220     ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, TEST_CERT_ROLE1, NULL, &roleCert);
1221     if (ret != 0)
1222     {
1223         OIC_LOG_V(ERROR, TAG, "%s Failed to create role certificate", __func__);
1224         goto exit;
1225     }
1226
1227     ret = provisionCert(dev_num, roleCert);
1228     if (ret != 0)
1229     {
1230         OIC_LOG_V(ERROR, TAG, "%s Failed to provision role certificate", __func__);
1231         goto exit;
1232     }
1233     OICFreeAndSetToNull((void**)&roleCert);
1234
1235     /* The second will have the authority field set */
1236     ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, TEST_CERT_ROLE2, TEST_CERT_AUTHORITY, &roleCert);
1237     if (ret != 0)
1238     {
1239         OIC_LOG_V(ERROR, TAG, "%s Failed to create role certificate", __func__);
1240         goto exit;
1241     }
1242
1243     ret = provisionCert(dev_num, roleCert);
1244     if (ret != 0)
1245     {
1246         OIC_LOG_V(ERROR, TAG, "%s Failed to provision role certificate", __func__);
1247         goto exit;
1248     }
1249
1250 exit:
1251
1252     OICFree(csr);
1253     OICFree(idCert);
1254     OICFree(roleCert);
1255
1256     return ret;
1257 }
1258
1259 static int testRoleAssertion(int dev_num)
1260 {
1261     char* csr = NULL;
1262     char* idCert = NULL;
1263     char* roleCert = NULL;
1264     OicSecAcl_t* acl = NULL;
1265
1266     /* Make sure we own at least one device to provision */
1267     if (!g_own_list || (g_own_cnt == 0))
1268     {
1269         OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
1270         return -1;  // Error, we should have registered unowned devices already
1271     }
1272
1273     /* Provision the device with the CA root, and issue it an identity cert. */
1274     if (provisionTrustAnchor(dev_num) != 0)
1275     {
1276         return -1;
1277     }
1278
1279     if (getCsr(dev_num, &csr) != 0)
1280     {
1281         return -1;
1282     }
1283
1284     int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &idCert);
1285     if (ret != 0)
1286     {
1287         OIC_LOG_V(ERROR, TAG, "%s Failed to create identity certificate", __func__);
1288         goto exit;
1289     }
1290
1291     ret = provisionCert(dev_num, idCert);
1292     if (ret != 0)
1293     {
1294         OIC_LOG_V(ERROR, TAG, "%s Failed to provision id certificate", __func__);
1295         goto exit;
1296     }
1297
1298     /* Create and provision a role-based ACL allowing ROLE1 to access '/a/led'. */
1299     ret = createLedAcl(&acl, TEST_CERT_ROLE1, NULL);
1300     if (ret != 0)
1301     {
1302         OIC_LOG_V(ERROR, TAG, "%s failed to create led ACL", __func__);
1303         goto exit;
1304     }
1305
1306     ret = provisionAcl(dev_num, acl);
1307     if (ret != 0)
1308     {
1309         OIC_LOG_V(ERROR, TAG, "%s failed to provision led ACL", __func__);
1310         goto exit;
1311     }
1312
1313     /* Provision ourselves an identity and role cert.
1314      * For the identity cert we use a random UUID, since the server has an ACE granting our UUID
1315      * access to everything (as owner). We don't want to remove this ACE because it would lock
1316      * us out. Using another UUID makes us appear as another device on the network.
1317      */
1318     OicUuid_t notOurUuid;
1319     (void)OCGenerateUuid(notOurUuid.id);
1320     ret = setupOwnCert(&notOurUuid);
1321     if (ret != 0)
1322     {
1323         OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__);
1324         goto exit;
1325     }
1326
1327     ret = setupOwnRoleCert(NULL, TEST_CERT_ROLE1, NULL);
1328     if (ret != 0)
1329     {
1330         OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__);
1331         goto exit;
1332     }
1333
1334     /* Remove the owner credential so that we don't use it when asserting role certs. */
1335     OCStackResult res = OCRemoveCredential(&g_uuidDev1);
1336     if (res != OC_STACK_RESOURCE_DELETED)
1337     {
1338         OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__);
1339         OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH);
1340         ret = -1;
1341         goto exit;
1342     }
1343
1344     /*
1345      * Work around bug IOT-1927
1346      * @todo: When that bug is resolved, remove this call and the function workAroundBug
1347      */
1348     if (workAroundBug() != 0)
1349     {
1350         OIC_LOG_V(ERROR, TAG, "%s bug workaround failed: ", __func__);
1351         ret = -1;
1352         goto exit;
1353     }
1354
1355     /* Close all secure sessions */
1356     if (closeAllSessions() != 0)
1357     {
1358         OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
1359         ret = -1;
1360         goto exit;
1361     }
1362
1363     /* Assert role certificate */
1364     OCProvisionDev_t *device = NULL;
1365     device = getDevInst(g_own_list, dev_num);
1366     if (!device)
1367     {
1368         OIC_LOG(ERROR, TAG, "Selected device does not exist");
1369         ret = -1;
1370         goto exit;
1371     }
1372
1373     OCDevAddr devAddr = device->endpoint;
1374     devAddr.port = device->securePort;
1375
1376     g_doneCB = false;
1377     res = OCAssertRoles(g_ctx, &devAddr, assertRolesCB);
1378     if (res != OC_STACK_OK)
1379     {
1380         OIC_LOG_V(ERROR, TAG, "OCAssertRoles returned error %d with method", res);
1381         ret = -1;
1382         goto exit;
1383     }
1384     if (waitCallbackRet())
1385     {
1386         OIC_LOG_V(ERROR, TAG, "%s callback error", __func__);
1387     }
1388     if (!g_successCB)
1389     {
1390         ret = -1;
1391         goto exit;
1392     }
1393
1394 exit:
1395     OICFree(csr);
1396     OICFree(idCert);
1397     OICFree(roleCert);
1398     OCDeleteACLList(acl);
1399
1400     return ret;
1401 }
1402
1403 static int testRoleAssertionAndUse(int dev_num)
1404 {
1405     char* csr = NULL;
1406     char* idCert = NULL;
1407     char* roleCert = NULL;
1408     const char* uri = "/a/led";
1409     OicSecAcl_t* acl = NULL;
1410
1411     // Make sure we own at least one device to provision
1412     if (!g_own_list || (g_own_cnt == 0))
1413     {
1414         OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
1415         return -1;  // Error, we should have registered unowned devices already
1416     }
1417
1418     /* Provision the device with the CA root, and issue it an identity cert. */
1419     if (provisionTrustAnchor(dev_num) != 0)
1420     {
1421         return -1;
1422     }
1423
1424     if (getCsr(dev_num, &csr) != 0)
1425     {
1426         return -1;
1427     }
1428
1429     int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &idCert);
1430     if (ret != 0)
1431     {
1432         OIC_LOG_V(ERROR, TAG, "%s Failed to create identity certificate", __func__);
1433         goto exit;
1434     }
1435
1436     ret = provisionCert(dev_num, idCert);
1437     if (ret != 0)
1438     {
1439         OIC_LOG_V(ERROR, TAG, "%s Failed to provision id certificate", __func__);
1440         goto exit;
1441     }
1442
1443     /* Create and provision a role-based ACL allowing ROLE1 to access '/a/led'. */
1444     ret = createLedAcl(&acl, TEST_CERT_ROLE1, NULL);
1445     if (ret != 0)
1446     {
1447         OIC_LOG_V(ERROR, TAG, "%s failed to create led ACL", __func__);
1448         goto exit;
1449     }
1450
1451     ret = provisionAcl(dev_num, acl);
1452     if (ret != 0)
1453     {
1454         OIC_LOG_V(ERROR, TAG, "%s failed to provision led ACL", __func__);
1455         goto exit;
1456     }
1457
1458     /* Provision ourselves an identity and role cert.
1459      * For the identity cert we use a random UUID, since the server has an ACE granting our UUID
1460      * access to everything (as owner). We don't want to remove this ACE because it would lock
1461      * us out. Using another UUID makes us appear as another device on the network.
1462      */
1463     OicUuid_t notOurUuid;
1464     (void) OCGenerateUuid(notOurUuid.id);
1465     ret = setupOwnCert(&notOurUuid);
1466     if (ret != 0)
1467     {
1468         OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__);
1469         goto exit;
1470     }
1471
1472     ret = setupOwnRoleCert(NULL, TEST_CERT_ROLE1, NULL);
1473     if (ret != 0)
1474     {
1475         OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__);
1476         goto exit;
1477     }
1478
1479     /* Remove the owner credential so that we don't use it when asserting role certs. */
1480     OCStackResult res = OCRemoveCredential(&g_uuidDev1);
1481     if (res != OC_STACK_RESOURCE_DELETED)
1482     {
1483         OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__);
1484         OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH);
1485         ret = -1;
1486         goto exit;
1487     }
1488
1489     /*
1490     * Work around bug IOT-1927
1491     * @todo: When that bug is resolved, remove this call and the function workAroundBug
1492     */
1493     if (workAroundBug() != 0)
1494     {
1495         OIC_LOG_V(ERROR, TAG, "%s bug workaround failed: ", __func__);
1496         ret = -1;
1497         goto exit;
1498     }
1499
1500     /* Close all secure sessions */
1501     if (closeAllSessions() != 0)
1502     {
1503         OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
1504         ret = -1;
1505         goto exit;
1506     }
1507
1508     /* Try a get request, expect success, role certificate will be automatically asserted */
1509     ret = doGetRequest(uri, dev_num);
1510     if (ret != 0)
1511     {
1512         OIC_LOG_V(ERROR, TAG, "%s Get request to %s failed, but should have succeeded", __func__, uri);
1513         goto exit;
1514     }
1515
1516 exit:
1517     OICFree(csr);
1518     OICFree(idCert);
1519     OICFree(roleCert);
1520     OCDeleteACLList(acl);
1521
1522     return ret;
1523 }
1524
1525 static int provisionSymmetricRoleCred(int dev_num)
1526 {
1527     OicSecRole_t role;
1528     memset(&role, 0, sizeof(role));
1529     OICStrcpy(role.id, sizeof(role.id), TEST_CERT_ROLE1);
1530
1531     // call |OCProvisionCredentials| API
1532     // calling this API with callback actually acts like blocking
1533     // for error checking, the return value saved and printed
1534     g_doneCB = false;
1535     OCStackResult rst =
1536         OCProvisionSymmetricRoleCredentials((void*) g_ctx,
1537                     SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
1538                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
1539                     NULL, NULL, &role,
1540                     provisionCredCB);
1541     if (OC_STACK_OK != rst)
1542     {
1543         OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
1544         return -1;
1545     }
1546     if (waitCallbackRet())  // input |g_doneCB| flag implicitly
1547     {
1548         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
1549         return -1;
1550     }
1551
1552     return 0;
1553 }
1554
1555 static int testSymmetricRoleUse(int dev_num)
1556 {
1557     const char* uri = "/a/led";
1558     OicSecAcl_t* acl = NULL;
1559
1560     // Make sure we own at least one device to provision
1561     if (!g_own_list || (g_own_cnt == 0))
1562     {
1563         OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
1564         return -1;  // Error, we should have registered unowned devices already
1565     }
1566
1567     /* Create and provision a role-based ACL allowing ROLE1 to access '/a/led'. */
1568     int ret = createLedAcl(&acl, TEST_CERT_ROLE1, NULL);
1569     if (ret != 0)
1570     {
1571         OIC_LOG_V(ERROR, TAG, "%s failed to create led ACL", __func__);
1572         return ret;
1573     }
1574
1575     ret = provisionAcl(dev_num, acl);
1576     if (ret != 0)
1577     {
1578         OIC_LOG_V(ERROR, TAG, "%s failed to provision led ACL", __func__);
1579         goto exit;
1580     }
1581
1582     /* Remove the owner credential so that we don't use it when asserting role certs. */
1583     OCStackResult res = OCRemoveCredential(&g_uuidDev1);
1584     if (res != OC_STACK_RESOURCE_DELETED)
1585     {
1586         OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__);
1587         OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH);
1588         ret = -1;
1589         goto exit;
1590     }
1591
1592     /* The server has an owner PSK associated with our GUID. Change our GUID to something else,
1593      * which will both be used to generate the role credential and for the later connection.
1594      */
1595     const OCUUIdentity newIdentity = { .id = { 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46 } };
1596     if (OC_STACK_OK != OCSetDeviceId(&newIdentity))
1597     {
1598         OIC_LOG_V(ERROR, TAG, "%s failed to set device ID", __func__);
1599         ret = -1;
1600         goto exit;
1601     }
1602
1603     /* Create a new symmetric credential with the role. */
1604     ret = provisionSymmetricRoleCred(dev_num);
1605     if (ret != 0)
1606     {
1607         OIC_LOG_V(ERROR, TAG, "%s failed to provision symmetric role pair-wise keys", __func__);
1608         goto exit;
1609     }
1610
1611     /* Close all secure sessions */
1612     if (closeAllSessions() != 0)
1613     {
1614         OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
1615         ret = -1;
1616         goto exit;
1617     }
1618
1619     /* Try a get request, expect success */
1620     ret = doGetRequest(uri, dev_num);
1621     if (ret != 0)
1622     {
1623         OIC_LOG_V(ERROR, TAG, "%s Get request to %s failed, but should have succeeded", __func__, uri);
1624         goto exit;
1625     }
1626
1627 exit:
1628
1629     OCDeleteACLList(acl);
1630
1631     return ret;
1632 }
1633
1634 /* Get a specific device from the provided device list. The devices in the list
1635  * are numbered starting from 1.
1636  */
1637 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1638 {
1639     if (!dev_lst || 0 >= dev_num)
1640     {
1641         printf("     Device List is Empty..\n");
1642         return NULL;
1643     }
1644
1645     OCProvisionDev_t* lst = (OCProvisionDev_t*)dev_lst;
1646     for (int i = 0; lst; )
1647     {
1648         if (dev_num == ++i)
1649         {
1650             return lst;
1651         }
1652         lst = lst->next;
1653     }
1654
1655     OIC_LOG_V(ERROR, TAG, "%s failed, requested device not found in list (does the device need to be discovered or owned first?)", __func__);
1656     return NULL;  // in here |lst| is always |NULL|
1657 }
1658
1659 static int printDevList(const OCProvisionDev_t* dev_lst)
1660 {
1661     if (!dev_lst)
1662     {
1663         printf("     Device List is Empty..\n\n");
1664         return 0;
1665     }
1666
1667     OCProvisionDev_t* lst = (OCProvisionDev_t*)dev_lst;
1668     int lst_cnt = 0;
1669     for (; lst; )
1670     {
1671         printf("     [%d] ", ++lst_cnt);
1672         printUuid((const OicUuid_t*)&lst->doxm->deviceID);
1673         printf("\n");
1674         lst = lst->next;
1675     }
1676     printf("\n");
1677
1678     return lst_cnt;
1679 }
1680
1681 static size_t printResultList(const OCProvisionResult_t* rslt_lst, const size_t rslt_cnt)
1682 {
1683     if (!rslt_lst || (0 == rslt_cnt))
1684     {
1685         printf("     Device List is Empty..\n\n");
1686         return 0;
1687     }
1688
1689     size_t lst_cnt = 0;
1690     for (; rslt_cnt > lst_cnt; ++lst_cnt)
1691     {
1692         printf("     [%" PRIuPTR "] ", lst_cnt + 1);
1693         printUuid((const OicUuid_t*)&rslt_lst[lst_cnt].deviceId);
1694         printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1695     }
1696     printf("\n");
1697
1698     return lst_cnt;
1699 }
1700
1701 static int saveUuid(const OCProvisionResult_t* rslt_lst, const size_t rslt_cnt)
1702 {
1703     if (!rslt_lst || (rslt_cnt != 1))
1704     {
1705         OIC_LOG_V(ERROR, TAG, "%s: expected only one device", __func__);
1706         return -1;
1707     }
1708
1709     memcpy(&g_uuidDev1, &rslt_lst[0].deviceId, sizeof(OicUuid_t));
1710
1711     return 0;
1712 }
1713
1714 static void printUuid(const OicUuid_t* uid)
1715 {
1716     for (int i = 0; i<UUID_LENGTH; )
1717     {
1718         printf("%02X", (*uid).id[i++]);
1719         if (i == 4 || i == 6 || i == 8 || i == 10)  // canonical format for UUID has '8-4-4-4-12'
1720         {
1721             printf("-");
1722         }
1723     }
1724     printf("\n");
1725 }
1726
1727 static FILE* fopen_prvnMng(const char* path, const char* mode)
1728 {
1729     if (0 == strncmp(path, OC_SECURITY_DB_DAT_FILE_NAME, strlen(OC_SECURITY_DB_DAT_FILE_NAME)))
1730     {
1731         // input |g_svr_db_fname| internally by force, not using |path| parameter
1732         // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1733         // with its own |SVR_DB_FILE_NAME|
1734         return fopen(SVR_DB_FILE_NAME, mode);
1735     }
1736     else
1737     {
1738         return fopen(path, mode);
1739     }
1740 }
1741
1742 static int waitCallbackRet(void)
1743 {
1744     for(int i = 0; !g_doneCB; ++i)
1745     {
1746         if(OC_STACK_OK != OCProcess())
1747         {
1748             OIC_LOG(ERROR, TAG, "OCStack process error");
1749             return -1;
1750         }
1751
1752         if (i == CALLBACK_TIMEOUT)
1753         {
1754             return -1;
1755         }
1756
1757         sleep(1);
1758     }
1759
1760     return 0;
1761 }
1762
1763 void shutdownProvisionClient()
1764 {
1765     if(OC_STACK_OK != OCStop())
1766     {
1767         OIC_LOG(ERROR, TAG, "OCStack stop error");
1768     }
1769     OCDeleteDiscoveredDevices(g_own_list);  // after here |g_own_list| points to nothing
1770     OCDeleteDiscoveredDevices(g_unown_list);  // after here |g_unown_list| points to nothing
1771
1772     OICFreeAndSetToNull((void**)&g_svr_fname);
1773     OICFreeAndSetToNull((void**)&g_prvn_fname);
1774 }
1775
1776 static int initDiscoverRegisterAllDevices()
1777 {
1778     if(initProvisionClient())
1779     {
1780         OIC_LOG_V(ERROR, TAG, "%s: ProvisionClient init error", __func__);
1781         return -1;
1782     }
1783
1784     if(discoverAllDevices())
1785     {
1786         OIC_LOG_V(ERROR, TAG, "%s: Discovery failed", __func__);
1787         return -1;
1788     }
1789
1790     if(registerDevices())
1791     {
1792         OIC_LOG_V(ERROR, TAG, "%s: Failed to onboard devices", __func__);
1793         return -1;
1794     }
1795
1796     if(discoverAllDevices())
1797     {
1798         OIC_LOG_V(ERROR, TAG, "%s: Re-discovery failed after registerDevices", __func__);
1799         return -1;
1800     }
1801
1802     return 0;
1803
1804 }
1805
1806 int TestTrustAnchorProvisioning()
1807 {
1808     int ret = -1;
1809
1810     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1811
1812     if(initDiscoverRegisterAllDevices())
1813     {
1814         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1815         goto exit;
1816     }
1817
1818     /* There should be one owned device with number 1. */
1819     if(provisionTrustAnchor(1))
1820     {
1821         OIC_LOG_V(ERROR, TAG, "%s: Failed to provision trust anchor to device", __func__);
1822         goto exit;
1823     }
1824
1825     ret = 0;
1826
1827 exit:
1828
1829     shutdownProvisionClient();
1830
1831     return ret;
1832 }
1833
1834 int TestCSRResource()
1835 {
1836     int ret = -1;
1837
1838     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1839
1840     if(initDiscoverRegisterAllDevices())
1841     {
1842         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1843         goto exit;
1844     }
1845
1846     /* There should be one owned device with number 1. */
1847     if(getCsr(1, NULL))
1848     {
1849         OIC_LOG(ERROR, TAG, "Failed to get CSR from device");
1850         goto exit;
1851     }
1852
1853     ret = 0;
1854
1855 exit:
1856
1857     shutdownProvisionClient();
1858
1859     return ret;
1860 }
1861
1862 int TestCertUse()
1863 {
1864     int ret = -1;
1865
1866     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1867
1868     if (initDiscoverRegisterAllDevices())
1869     {
1870         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1871         goto exit;
1872     }
1873
1874     /* There should be one owned device with number 1. */
1875     if (testCertUse(1))
1876     {
1877         OIC_LOG(ERROR, TAG, "Failed to authenticate to device with certificate");
1878         goto exit;
1879     }
1880
1881     ret = 0;
1882
1883 exit:
1884
1885     shutdownProvisionClient();
1886
1887     return ret;
1888 }
1889
1890 int TestRoleProvisioning()
1891 {
1892     int ret = -1;
1893
1894     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1895
1896     if (initDiscoverRegisterAllDevices())
1897     {
1898         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1899         goto exit;
1900     }
1901
1902     /* There should be one owned device with number 1. */
1903     if (testRoleProvisioning(1))
1904     {
1905         OIC_LOG(ERROR, TAG, "Failed to provision roles to device");
1906         goto exit;
1907     }
1908
1909     ret = 0;
1910
1911 exit:
1912
1913     shutdownProvisionClient();
1914
1915     return ret;
1916 }
1917
1918 int TestRoleAssertion()
1919 {
1920     int ret = -1;
1921
1922     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1923
1924     if (initDiscoverRegisterAllDevices())
1925     {
1926         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1927         goto exit;
1928     }
1929
1930     /* There should be one owned device with number 1. */
1931     if (testRoleAssertion(1))
1932     {
1933         OIC_LOG(ERROR, TAG, "Failed to assert roles");
1934         goto exit;
1935     }
1936
1937     ret = 0;
1938
1939 exit:
1940
1941     shutdownProvisionClient();
1942
1943     return ret;
1944 }
1945
1946 int TestRoleAssertionAndUse()
1947 {
1948     int ret = -1;
1949
1950     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1951
1952     if (initDiscoverRegisterAllDevices())
1953     {
1954         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1955         goto exit;
1956     }
1957
1958     /* There should be one owned device with number 1. */
1959     if (testRoleAssertionAndUse(1))
1960     {
1961         OIC_LOG(ERROR, TAG, "Failed to assert and use roles");
1962         goto exit;
1963     }
1964
1965     ret = 0;
1966
1967 exit:
1968
1969     shutdownProvisionClient();
1970
1971     return ret;
1972 }
1973
1974 int TestSymmetricRoleUse()
1975 {
1976     int ret = -1;
1977
1978     OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
1979
1980     if (initDiscoverRegisterAllDevices())
1981     {
1982         OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
1983         goto exit;
1984     }
1985
1986     /* There should be one owned device with number 1. */
1987     if (testSymmetricRoleUse(1))
1988     {
1989         OIC_LOG(ERROR, TAG, "Failed to use symmetric key role");
1990         goto exit;
1991     }
1992
1993     ret = 0;
1994
1995 exit:
1996
1997     shutdownProvisionClient();
1998
1999     return ret;
2000 }
2001
2002 // main function for provisioning client using C-level provisioning API
2003 int main(int argc, char** argv)
2004 {
2005     if(argc != 2)
2006     {
2007         printf("%s: No test number provided (argc = %d)\n", argv[0], argc);
2008         return 1;
2009     }
2010
2011     unsigned int testNumber = strtoul(argv[1], NULL, 10);
2012     switch (testNumber)
2013     {
2014         case 1:
2015             return TestTrustAnchorProvisioning();
2016         case 2:
2017             return TestCSRResource();
2018         case 3:
2019             return TestCertUse();
2020         case 4:
2021             return TestRoleProvisioning();
2022         case 5:
2023             return TestRoleAssertion();
2024         case 6:
2025             return TestRoleAssertionAndUse();
2026         case 7:
2027             return TestSymmetricRoleUse();
2028         default:
2029             printf("%s: Invalid test number\n", argv[0]);
2030             return 1;
2031
2032         /* Note: when adding a new test, update NUM_TESTS in provisioningTest.py */
2033     }
2034
2035 }
2036
2037 #ifdef __cplusplus
2038 }
2039 #endif //__cplusplus