Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / credentialgenerator.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20 #include <string.h>
21 #include "credentialgenerator.h"
22 #include "base64.h"
23 #include "oic_malloc.h"
24 #include "oic_string.h"
25 #include "ocpayload.h"
26 #include "payload_logging.h"
27 #include "credresource.h"
28 #include "ocrandom.h"
29 #include "srmutility.h"
30 #include "stdbool.h"
31 #include "securevirtualresourcetypes.h"
32 #ifdef __WITH_X509__
33 #include "ck_manager.h"
34 //Certificate-related functions
35 #define CERT_LEN_PREFIX (3)
36 #define BYTE_SIZE (8) //bits
37
38 #define CHAIN_LEN (2) //TODO: replace by external define or a runtime value
39 #endif  //__WITH_X509__
40
41 #define TAG "SRPAPI-CG"
42
43 OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
44         const OicUuid_t *ptDeviceId, const OicUuid_t *firstDeviceId,
45         const OicUuid_t *secondDeviceId, OicSecCred_t **firstCred, OicSecCred_t **secondCred)
46 {
47     if (NULL == ptDeviceId || NULL == firstDeviceId || NULL != *firstCred || \
48         NULL == secondDeviceId || NULL != *secondCred)
49     {
50         OIC_LOG(INFO, TAG, "Invalid params");
51         return OC_STACK_INVALID_PARAM;
52     }
53     if(!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
54     {
55         OIC_LOG(INFO, TAG, "Invalid key size");
56         return OC_STACK_INVALID_PARAM;
57     }
58     OCStackResult res = OC_STACK_ERROR;
59     OicSecCred_t *tempFirstCred = NULL;
60     OicSecCred_t *tempSecondCred = NULL;
61
62     size_t privDataKeySize = keySize;
63
64     uint8_t *privData = (uint8_t *)OICCalloc(privDataKeySize, sizeof(uint8_t));
65     VERIFY_NON_NULL(TAG, privData, ERROR);
66     OicSecKey_t privKey = {privData, keySize};
67
68     OCFillRandomMem(privData, privDataKeySize);
69
70     // TODO: currently owner array is 1. only provisioning tool's id.
71     tempFirstCred =  GenerateCredential(secondDeviceId, type, NULL, &privKey, ptDeviceId);
72     VERIFY_NON_NULL(TAG, tempFirstCred, ERROR);
73
74     // TODO: currently owner array is 1. only provisioning tool's id.
75     tempSecondCred =  GenerateCredential(firstDeviceId, type, NULL, &privKey, ptDeviceId);
76     VERIFY_NON_NULL(TAG, tempSecondCred, ERROR);
77
78     *firstCred = tempFirstCred;
79     *secondCred = tempSecondCred;
80     res = OC_STACK_OK;
81
82 exit:
83     OICFree(privData);
84
85     if(res != OC_STACK_OK)
86     {
87         OICFree(tempFirstCred);
88         OICFree(tempSecondCred);
89         *firstCred = NULL;
90         *secondCred = NULL;
91     }
92
93     return res;
94 }
95
96 #ifdef __WITH_X509__
97 static void writeCertPrefix(uint8_t *prefix, uint32_t certLen)
98 {
99     for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
100     {
101         prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
102     }
103 }
104
105 static uint32_t appendCert2Chain(uint8_t *appendPoint, uint8_t *cert, size_t len)
106 {
107     uint32_t ret = 0;
108     VERIFY_NON_NULL(TAG, appendPoint, ERROR);
109     VERIFY_NON_NULL(TAG, cert, ERROR);
110
111     memcpy(appendPoint + CERT_LEN_PREFIX, cert, len);
112     writeCertPrefix(appendPoint, len);
113
114     ret = len + CERT_LEN_PREFIX;
115 exit:
116     return ret;
117 }
118
119 /**
120  * Function to generate Base64 encoded credential data for device.
121  *
122  * @param[in]   subject             Device id.
123  * @param[out]  certificateChain    Pointer to Array of Base64 encoded certificate strings.
124  * @param[out]  chainLength         Pointer to number of the certificates in certificateChain.
125  * @param[out]  privKey             Pointer to Base64 encoded private key.
126  * @return  OC_STACK_OK on success
127  */
128 static OCStackResult GenerateCertificateAndKeys(const OicUuid_t * subject, OicSecCert_t * certificateChain,
129         OicSecKey_t * privKey)
130 {
131     if (NULL == subject || NULL == certificateChain || NULL == privKey)
132     {
133         return  OC_STACK_INVALID_PARAM;
134     }
135     certificateChain->data = NULL;
136     privKey->data = NULL;
137
138     ByteArray pubKeyBA  = BYTE_ARRAY_INITIALIZER;
139     ByteArray privKeyBA = BYTE_ARRAY_INITIALIZER;
140     ByteArray cert[CHAIN_LEN];
141
142     uint8_t pubKeyData[PUBLIC_KEY_SIZE] = {0};
143     uint8_t privKeyData[PRIVATE_KEY_SIZE] = {0};
144     uint8_t certData[ISSUER_MAX_CERT_SIZE * CHAIN_LEN] = {0};
145     uint8_t subjName[UUID_LENGTH + 1] = {0};
146
147     pubKeyBA.data  = pubKeyData;
148     pubKeyBA.len   = PUBLIC_KEY_SIZE;
149     privKeyBA.data = privKeyData;
150     privKeyBA.len  = PRIVATE_KEY_SIZE;
151     for (size_t i = 0; i < CHAIN_LEN; ++i)
152     {
153         cert[i].data      = certData + ISSUER_MAX_CERT_SIZE * i;
154         cert[i].len       = ISSUER_MAX_CERT_SIZE;
155     }
156
157     memcpy(subjName, subject->id, UUID_LENGTH);
158     subjName[UUID_LENGTH] = '\0';
159
160     if (PKI_SUCCESS != GenerateKeyPair(&privKeyBA, &pubKeyBA))
161     {
162         OIC_LOG(ERROR, TAG, "Error generating keys.");
163         return OC_STACK_ERROR;
164     }
165     if (PKI_SUCCESS != CKMIssueDeviceCertificate(subjName, NULL, NULL, pubKeyBA.data, cert))
166     {
167         OIC_LOG(ERROR, TAG, "Error generating certificate.");
168         return OC_STACK_ERROR;
169     }
170
171     uint8_t numCert = 0;
172     if (PKI_SUCCESS != GetCAChain(&numCert , cert + 1))
173     {
174         OIC_LOG(ERROR, TAG, "Error getting CA certificate chain.");
175         return OC_STACK_ERROR;
176     }
177
178     numCert ++;
179     uint32_t len = 0;
180     for (size_t i = 0; i < numCert; i++)
181     {
182         certificateChain->data = (uint8_t *) OICRealloc(certificateChain->data,
183                                                         len + cert[i].len + CERT_LEN_PREFIX);
184         if (NULL == certificateChain->data)
185         {
186             OIC_LOG(ERROR, TAG, "Error while memory allocation");
187             return OC_STACK_ERROR;
188         }
189
190         uint32_t appendedLen = appendCert2Chain(certificateChain->data + len,
191                                                 cert[i].data, cert[i].len);
192         if (0 == appendedLen)
193         {
194             OIC_LOG(ERROR, TAG, "Error while certifiacate chain creation.");
195             OICFree(certificateChain->data);
196             certificateChain->len = 0;
197             return OC_STACK_ERROR;
198         }
199         len += appendedLen;
200     }
201     certificateChain->len = len;
202     privKey->data = (uint8_t*) OICMalloc(PRIVATE_KEY_SIZE);
203     if (NULL == privKey->data)
204     {
205         OIC_LOG(ERROR, TAG, "Error while memory allocation");
206         OICFree(certificateChain->data);
207         certificateChain->len = 0;
208         privKey->len = 0;
209         return OC_STACK_ERROR;
210     }
211     memcpy(privKey->data, privKeyData, PRIVATE_KEY_SIZE);
212     privKey->len = PRIVATE_KEY_SIZE;
213
214     return OC_STACK_OK;
215 }
216
217 OCStackResult PMGenerateCertificateCredentials(const OicUuid_t *ptDeviceId,
218         const OicUuid_t *deviceId, OicSecCred_t **const cred)
219 {
220     if (NULL == ptDeviceId || NULL == deviceId || NULL == cred)
221     {
222         return OC_STACK_INVALID_PARAM;
223     }
224     OicSecCert_t certificateChain;
225     OicSecKey_t privKey;
226     if (OC_STACK_OK != GenerateCertificateAndKeys(deviceId, &certificateChain, &privKey))
227     {
228         OIC_LOG(ERROR, TAG, "Error while generating credential data.");
229         return OC_STACK_ERROR;
230     }
231
232     *cred = GenerateCredential(deviceId, SIGNED_ASYMMETRIC_KEY, &certificateChain,
233                               &privKey, ptDeviceId);
234     return OC_STACK_OK;
235 }
236 #endif // __WITH_X509__