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