1 /* *****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
21 #include "credentialgenerator.h"
23 #include "oic_malloc.h"
24 #include "oic_string.h"
25 #include "ocpayload.h"
26 #include "payload_logging.h"
27 #include "credresource.h"
29 #include "srmutility.h"
31 #include "securevirtualresourcetypes.h"
33 #include "ck_manager.h"
34 //Certificate-related functions
35 #define CERT_LEN_PREFIX (3)
36 #define BYTE_SIZE (8) //bits
38 #define CHAIN_LEN (2) //TODO: replace by external define or a runtime value
39 #endif //__WITH_X509__
41 #define TAG "SRPAPI-CG"
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)
47 if (NULL == ptDeviceId || NULL == firstDeviceId || NULL != *firstCred || \
48 NULL == secondDeviceId || NULL != *secondCred)
50 OIC_LOG(INFO, TAG, "Invalid params");
51 return OC_STACK_INVALID_PARAM;
53 if(!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
55 OIC_LOG(INFO, TAG, "Invalid key size");
56 return OC_STACK_INVALID_PARAM;
58 OCStackResult res = OC_STACK_ERROR;
59 OicSecCred_t *tempFirstCred = NULL;
60 OicSecCred_t *tempSecondCred = NULL;
62 size_t privDataKeySize = keySize;
64 uint8_t *privData = (uint8_t *)OICCalloc(privDataKeySize, sizeof(uint8_t));
65 VERIFY_NON_NULL(TAG, privData, ERROR);
66 OicSecKey_t privKey = {privData, keySize};
68 OCFillRandomMem(privData, privDataKeySize);
70 // TODO: currently owner array is 1. only provisioning tool's id.
71 tempFirstCred = GenerateCredential(secondDeviceId, type, NULL, &privKey, 1, ptDeviceId);
72 VERIFY_NON_NULL(TAG, tempFirstCred, ERROR);
74 // TODO: currently owner array is 1. only provisioning tool's id.
75 tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, &privKey, 1, ptDeviceId);
76 VERIFY_NON_NULL(TAG, tempSecondCred, ERROR);
78 *firstCred = tempFirstCred;
79 *secondCred = tempSecondCred;
85 if(res != OC_STACK_OK)
87 OICFree(tempFirstCred);
88 OICFree(tempSecondCred);
97 static void writeCertPrefix(uint8_t *prefix, uint32_t certLen)
99 for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
101 prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
105 static uint32_t appendCert2Chain(uint8_t *appendPoint, uint8_t *cert, size_t len)
108 VERIFY_NON_NULL(TAG, appendPoint, ERROR);
109 VERIFY_NON_NULL(TAG, cert, ERROR);
111 memcpy(appendPoint + CERT_LEN_PREFIX, cert, len);
112 writeCertPrefix(appendPoint, len);
114 ret = len + CERT_LEN_PREFIX;
120 * Function to generate Base64 encoded credential data for device.
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
128 static OCStackResult GenerateCertificateAndKeys(const OicUuid_t * subject, OicSecCert_t * certificateChain,
129 OicSecKey_t * privKey)
131 if (NULL == subject || NULL == certificateChain || NULL == privKey)
133 return OC_STACK_INVALID_PARAM;
135 certificateChain->data = NULL;
136 privKey->data = NULL;
138 ByteArray pubKeyBA = BYTE_ARRAY_INITIALIZER;
139 ByteArray privKeyBA = BYTE_ARRAY_INITIALIZER;
140 ByteArray cert[CHAIN_LEN];
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};
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)
153 cert[i].data = certData + ISSUER_MAX_CERT_SIZE * i;
154 cert[i].len = ISSUER_MAX_CERT_SIZE;
157 memcpy(subjName, subject->id, UUID_LENGTH);
158 subjName[UUID_LENGTH] = '\0';
160 if (PKI_SUCCESS != GenerateKeyPair(&privKeyBA, &pubKeyBA))
162 OIC_LOG(ERROR, TAG, "Error generating keys.");
163 return OC_STACK_ERROR;
165 if (PKI_SUCCESS != CKMIssueDeviceCertificate(subjName, NULL, NULL, pubKeyBA.data, cert))
167 OIC_LOG(ERROR, TAG, "Error generating certificate.");
168 return OC_STACK_ERROR;
172 if (PKI_SUCCESS != GetCAChain(&numCert , cert + 1))
174 OIC_LOG(ERROR, TAG, "Error getting CA certificate chain.");
175 return OC_STACK_ERROR;
180 for (size_t i = 0; i < numCert; i++)
182 certificateChain->data = (uint8_t *) OICRealloc(certificateChain->data,
183 len + cert[i].len + CERT_LEN_PREFIX);
184 if (NULL == certificateChain->data)
186 OIC_LOG(ERROR, TAG, "Error while memory allocation");
187 return OC_STACK_ERROR;
190 uint32_t appendedLen = appendCert2Chain(certificateChain->data + len,
191 cert[i].data, cert[i].len);
192 if (0 == appendedLen)
194 OIC_LOG(ERROR, TAG, "Error while certifiacate chain creation.");
195 OICFree(certificateChain->data);
196 certificateChain->len = 0;
197 return OC_STACK_ERROR;
201 certificateChain->len = len;
202 privKey->data = (uint8_t*) OICMalloc(PRIVATE_KEY_SIZE);
203 if (NULL == privKey->data)
205 OIC_LOG(ERROR, TAG, "Error while memory allocation");
206 OICFree(certificateChain->data);
207 certificateChain->len = 0;
209 return OC_STACK_ERROR;
211 memcpy(privKey->data, privKeyData, PRIVATE_KEY_SIZE);
212 privKey->len = PRIVATE_KEY_SIZE;
217 OCStackResult PMGenerateCertificateCredentials(const OicUuid_t *ptDeviceId,
218 const OicUuid_t *deviceId, OicSecCred_t **const cred)
220 if (NULL == ptDeviceId || NULL == deviceId || NULL == cred)
222 return OC_STACK_INVALID_PARAM;
224 OicSecCert_t certificateChain;
226 if (OC_STACK_OK != GenerateCertificateAndKeys(deviceId, &certificateChain, &privKey))
228 OIC_LOG(ERROR, TAG, "Error while generating credential data.");
229 return OC_STACK_ERROR;
232 *cred = GenerateCredential(deviceId, SIGNED_ASYMMETRIC_KEY, &certificateChain,
233 &privKey, 1, ptDeviceId);
236 #endif // __WITH_X509__