source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/src/iothub_auth_client.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 20.9 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#include "umock_c/umock_c_prod.h"
6#include "azure_c_shared_utility/gballoc.h"
7#include "azure_c_shared_utility/sastoken.h"
8#include "azure_c_shared_utility/azure_base64.h"
9#include "azure_c_shared_utility/sha.h"
10#include "azure_c_shared_utility/urlencode.h"
11#include "azure_c_shared_utility/strings.h"
12#include "azure_c_shared_utility/xlogging.h"
13#include "azure_c_shared_utility/crt_abstractions.h"
14#include "azure_c_shared_utility/hmacsha256.h"
15
16#include "azure_prov_client/internal/iothub_auth_client.h"
17#include "azure_prov_client/iothub_security_factory.h"
18#include "hsm_client_data.h"
19
20typedef struct IOTHUB_SECURITY_INFO_TAG
21{
22 DEVICE_AUTH_TYPE cred_type;
23
24 HSM_CLIENT_HANDLE hsm_client_handle;
25
26 HSM_CLIENT_CREATE hsm_client_create;
27 HSM_CLIENT_DESTROY hsm_client_destroy;
28
29 HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_data;
30
31 HSM_CLIENT_GET_CERTIFICATE hsm_client_get_cert;
32 HSM_CLIENT_GET_ALIAS_KEY hsm_client_get_alias_key;
33
34 HSM_CLIENT_GET_TRUST_BUNDLE hsm_client_get_trust_bundle;
35 HSM_CLIENT_GET_SYMMETRICAL_KEY hsm_client_get_symm_key;
36 HSM_CLIENT_SET_SYMMETRICAL_KEY_INFO hsm_client_set_symm_key_info;
37
38 char* sas_token;
39 char* x509_certificate;
40 char* x509_alias_key;
41 bool base64_encode_signature;
42 bool urlencode_token_scope;
43} IOTHUB_SECURITY_INFO;
44
45#define HMAC_LENGTH 32
46static const char* const SAS_TOKEN_FORMAT = "SharedAccessSignature sr=%s&sig=%s&se=%s%s%s";
47static const char* const SKN_SECTION_FORMAT = "&skn=";
48
49static int sign_sas_data(IOTHUB_SECURITY_INFO* security_info, const char* payload, unsigned char** output, size_t* len)
50{
51 int result;
52 size_t payload_len = strlen(payload);
53 if (security_info->cred_type == AUTH_TYPE_SAS)
54 {
55 if (security_info->hsm_client_sign_data(security_info->hsm_client_handle, (const unsigned char*)payload, strlen(payload), output, len) != 0)
56 {
57 LogError("Failed signing data");
58 result = MU_FAILURE;
59 }
60 else
61 {
62 result = 0;
63 }
64 }
65 else
66 {
67 char* symmetrical_key = security_info->hsm_client_get_symm_key(security_info->hsm_client_handle);
68 if (symmetrical_key == NULL)
69 {
70 LogError("Failed getting asymmetrical key");
71 result = MU_FAILURE;
72 }
73 else
74 {
75 BUFFER_HANDLE decoded_key;
76 BUFFER_HANDLE output_hash;
77
78 if ((decoded_key = Azure_Base64_Decode(symmetrical_key)) == NULL)
79 {
80 LogError("Failed decoding symmetrical key");
81 result = MU_FAILURE;
82 }
83 else if ((output_hash = BUFFER_new()) == NULL)
84 {
85 LogError("Failed allocating output hash buffer");
86 BUFFER_delete(decoded_key);
87 result = MU_FAILURE;
88 }
89 else
90 {
91 if (HMACSHA256_ComputeHash(BUFFER_u_char(decoded_key), BUFFER_length(decoded_key), (const unsigned char*)payload, payload_len, output_hash) != HMACSHA256_OK)
92 {
93 LogError("Failed computing HMAC Hash");
94 result = MU_FAILURE;
95 }
96 else
97 {
98 *len = BUFFER_length(output_hash);
99 if ((*output = malloc(*len)) == NULL)
100 {
101 LogError("Failed allocating output buffer");
102 result = MU_FAILURE;
103 }
104 else
105 {
106 const unsigned char* output_data = BUFFER_u_char(output_hash);
107 memcpy(*output, output_data, *len);
108 result = 0;
109 }
110 }
111 BUFFER_delete(decoded_key);
112 BUFFER_delete(output_hash);
113 }
114 free(symmetrical_key);
115 }
116 }
117 return result;
118}
119
120IOTHUB_SECURITY_HANDLE iothub_device_auth_create()
121{
122 IOTHUB_SECURITY_INFO* result;
123
124 IOTHUB_SECURITY_TYPE iothub_security_t = iothub_security_type();
125
126 if ((result = (IOTHUB_SECURITY_INFO*)malloc(sizeof(IOTHUB_SECURITY_INFO))) == NULL)
127 {
128 /* Codes_IOTHUB_DEV_AUTH_07_001: [ if any failure is encountered iothub_device_auth_create shall return NULL. ] */
129 LogError("Failed allocating IOTHUB_SECURITY_INFO.");
130 }
131 else
132 {
133 memset(result, 0, sizeof(IOTHUB_SECURITY_INFO) );
134#if defined(HSM_TYPE_SAS_TOKEN) || defined(HSM_AUTH_TYPE_CUSTOM)
135 if (iothub_security_t == IOTHUB_SECURITY_TYPE_SAS)
136 {
137 result->cred_type = AUTH_TYPE_SAS;
138 result->base64_encode_signature = true;
139 result->urlencode_token_scope = false;
140 const HSM_CLIENT_TPM_INTERFACE* tpm_interface = hsm_client_tpm_interface();
141 if ((tpm_interface == NULL) ||
142 ((result->hsm_client_create = tpm_interface->hsm_client_tpm_create) == NULL) ||
143 ((result->hsm_client_destroy = tpm_interface->hsm_client_tpm_destroy) == NULL) ||
144 ((result->hsm_client_sign_data = tpm_interface->hsm_client_sign_with_identity) == NULL)
145 )
146 {
147 /* Codes_IOTHUB_DEV_AUTH_07_034: [ if any of the iothub_security_interface function are NULL iothub_device_auth_create shall return NULL. ] */
148 LogError("Invalid secure device interface");
149 free(result);
150 result = NULL;
151 }
152 }
153#endif
154#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
155 if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_X509)
156 {
157 result->cred_type = AUTH_TYPE_X509;
158 result->base64_encode_signature = true;
159 result->urlencode_token_scope = false;
160 const HSM_CLIENT_X509_INTERFACE* x509_interface = hsm_client_x509_interface();
161 if ((x509_interface == NULL) ||
162 ((result->hsm_client_create = x509_interface->hsm_client_x509_create) == NULL) ||
163 ((result->hsm_client_destroy = x509_interface->hsm_client_x509_destroy) == NULL) ||
164 ((result->hsm_client_get_cert = x509_interface->hsm_client_get_cert) == NULL) ||
165 ((result->hsm_client_get_alias_key = x509_interface->hsm_client_get_key) == NULL)
166 )
167 {
168 /* Codes_IOTHUB_DEV_AUTH_07_034: [ if any of the iothub_security_interface function are NULL iothub_device_auth_create shall return NULL. ] */
169 LogError("Invalid handle parameter: DEVICE_AUTH_CREATION_INFO is NULL");
170 free(result);
171 result = NULL;
172 }
173 }
174#endif
175#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
176 if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_SYMMETRIC_KEY)
177 {
178 result->cred_type = AUTH_TYPE_SYMM_KEY;
179 result->base64_encode_signature = true;
180 result->urlencode_token_scope = false;
181 const HSM_CLIENT_KEY_INTERFACE* key_interface = hsm_client_key_interface();
182 if ((key_interface == NULL) ||
183 ((result->hsm_client_create = key_interface->hsm_client_key_create) == NULL) ||
184 ((result->hsm_client_destroy = key_interface->hsm_client_key_destroy) == NULL) ||
185 ((result->hsm_client_get_symm_key = key_interface->hsm_client_get_symm_key) == NULL) ||
186 ((result->hsm_client_set_symm_key_info = key_interface->hsm_client_set_symm_key_info) == NULL)
187 )
188 {
189 LogError("Invalid x509 secure device interface was specified");
190 free(result);
191 result = NULL;
192 }
193 }
194#endif
195#ifdef HSM_TYPE_HTTP_EDGE
196 if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_HTTP_EDGE)
197 {
198 result->cred_type = AUTH_TYPE_SAS;
199 // Because HTTP_edge operates over HTTP, the server has already base64 encoded signature its returning to us.
200 result->base64_encode_signature = false;
201 result->urlencode_token_scope = true;
202 const HSM_CLIENT_HTTP_EDGE_INTERFACE* http_edge_interface = hsm_client_http_edge_interface();
203 if ((http_edge_interface == NULL) ||
204 ((result->hsm_client_create = http_edge_interface->hsm_client_http_edge_create) == NULL) ||
205 ((result->hsm_client_destroy = http_edge_interface->hsm_client_http_edge_destroy) == NULL) ||
206 ((result->hsm_client_sign_data = http_edge_interface->hsm_client_sign_with_identity) == NULL) ||
207 ((result->hsm_client_get_trust_bundle = http_edge_interface->hsm_client_get_trust_bundle) == NULL))
208 {
209 LogError("Invalid secure device interface");
210 free(result);
211 result = NULL;
212 }
213 }
214#endif
215 if (result == NULL)
216 {
217 LogError("Error allocating result or else unsupported security type %d", iothub_security_t);
218 }
219 else if (result->hsm_client_create == NULL)
220 {
221 LogError("hsm_client_create is not a valid address");
222 free(result);
223 result = NULL;
224 }
225 else
226 {
227 /* Codes_IOTHUB_DEV_AUTH_07_025: [ iothub_device_auth_create shall call the concrete_iothub_device_auth_create function associated with the interface_desc. ] */
228 /* Codes_IOTHUB_DEV_AUTH_07_026: [ if concrete_iothub_device_auth_create fails iothub_device_auth_create shall return NULL. ] */
229 if ((result->hsm_client_handle = result->hsm_client_create()) == NULL)
230 {
231 /* Codes_IOTHUB_DEV_AUTH_07_002: [ iothub_device_auth_create shall allocate the IOTHUB_SECURITY_INFO and shall fail if the allocation fails. ]*/
232 LogError("failed create device auth module.");
233 free(result);
234 result = NULL;
235 }
236 else if (result->cred_type == AUTH_TYPE_SYMM_KEY && result->hsm_client_set_symm_key_info(result->hsm_client_handle, iothub_security_get_symm_registration_name(), iothub_security_get_symmetric_key()) != 0)
237 {
238 LogError("Invalid x509 secure device interface was specified");
239 result->hsm_client_destroy(result->hsm_client_handle);
240 free(result);
241 result = NULL;
242 }
243 }
244 }
245 /* Codes_IOTHUB_DEV_AUTH_07_003: [ If the function succeeds iothub_device_auth_create shall return a IOTHUB_SECURITY_HANDLE. ] */
246 return result;
247}
248
249void iothub_device_auth_destroy(IOTHUB_SECURITY_HANDLE handle)
250{
251 /* Codes_IOTHUB_DEV_AUTH_07_006: [ If the argument handle is NULL, iothub_device_auth_destroy shall do nothing ] */
252 if (handle != NULL)
253 {
254 /* Codes_IOTHUB_DEV_AUTH_07_005: [ iothub_device_auth_destroy shall call the concrete_iothub_device_auth_destroy function associated with the XDA_INTERFACE_DESCRIPTION. ] */
255 free(handle->x509_certificate);
256 free(handle->x509_alias_key);
257 free(handle->sas_token);
258 handle->hsm_client_destroy(handle->hsm_client_handle);
259 /* Codes_IOTHUB_DEV_AUTH_07_004: [ iothub_device_auth_destroy shall free all resources associated with the IOTHUB_SECURITY_HANDLE handle ] */
260 free(handle);
261 }
262}
263
264DEVICE_AUTH_TYPE iothub_device_auth_get_type(IOTHUB_SECURITY_HANDLE handle)
265{
266 DEVICE_AUTH_TYPE result;
267 /* Codes_IOTHUB_DEV_AUTH_07_007: [ If the argument handle is NULL, iothub_device_auth_get_auth_type shall return AUTH_TYPE_UNKNOWN. ] */
268 if (handle == NULL)
269 {
270 LogError("Invalid handle specified");
271 result = AUTH_TYPE_UNKNOWN;
272 }
273 else
274 {
275 /* Codes_IOTHUB_DEV_AUTH_07_008: [ iothub_device_auth_get_auth_type shall call concrete_iothub_device_auth_type function associated with the XDA_INTERFACE_DESCRIPTION. ] */
276 /* Codes_IOTHUB_DEV_AUTH_07_009: [ iothub_device_auth_get_auth_type shall return the DEVICE_AUTH_TYPE returned by the concrete_iothub_device_auth_type function. ] */
277 result = handle->cred_type;
278 }
279 return result;
280}
281
282CREDENTIAL_RESULT* iothub_device_auth_generate_credentials(IOTHUB_SECURITY_HANDLE handle, const DEVICE_AUTH_CREDENTIAL_INFO* dev_auth_cred)
283{
284 CREDENTIAL_RESULT* result;
285 /* Codes_IOTHUB_DEV_AUTH_07_010: [ If the argument handle or dev_auth_cred is NULL, iothub_device_auth_generate_credentials shall return a NULL value. ] */
286 if (handle == NULL)
287 {
288 LogError("Invalid handle parameter: handle");
289 result = NULL;
290 }
291 else
292 {
293 if (handle->cred_type == AUTH_TYPE_SAS || handle->cred_type == AUTH_TYPE_SYMM_KEY)
294 {
295 char expire_token[64] = { 0 };
296 if (handle->sas_token != NULL)
297 {
298 free(handle->sas_token);
299 handle->sas_token = NULL;
300 }
301 if (dev_auth_cred == NULL || dev_auth_cred->sas_info.token_scope == NULL)
302 {
303 LogError("Invalid handle parameter: dev_auth_cred");
304 result = NULL;
305 }
306 else if (dev_auth_cred->dev_auth_type != AUTH_TYPE_SAS && dev_auth_cred->dev_auth_type != AUTH_TYPE_SYMM_KEY)
307 {
308 LogError("Invalid handle parameter: dev_auth_cred.dev_auth_type");
309 result = NULL;
310 }
311 else if (size_tToString(expire_token, sizeof(expire_token), (size_t)dev_auth_cred->sas_info.expiry_seconds) != 0)
312 {
313 result = NULL;
314 LogError("Failure creating expire token");
315 }
316 else
317 {
318 size_t len = strlen(dev_auth_cred->sas_info.token_scope)+strlen(expire_token)+3;
319 char* payload = malloc(len+1);
320 if (payload == NULL)
321 {
322 result = NULL;
323 LogError("Failure allocating payload.");
324 }
325 else
326 {
327 unsigned char* data_value;
328 size_t data_len;
329
330 size_t total_len = sprintf(payload, "%s\n%s", dev_auth_cred->sas_info.token_scope, expire_token);
331 if (total_len <= 0)
332 {
333 result = NULL;
334 LogError("Failure constructing hash payload.");
335 }
336 /* Codes_IOTHUB_DEV_AUTH_07_035: [ For tpm type iothub_device_auth_generate_credentials shall call the concrete_dev_auth_sign_data function to hash the data. ] */
337 else if (sign_sas_data(handle, payload, &data_value, &data_len) == 0)
338 {
339 STRING_HANDLE urlEncodedSignature = NULL;
340 STRING_HANDLE signature = NULL;
341 if (handle->base64_encode_signature == true)
342 {
343 signature = Azure_Base64_Encode_Bytes(data_value, data_len);
344 }
345 else
346 {
347 signature = STRING_construct((const char*)data_value);
348 }
349
350 if (signature == NULL)
351 {
352 result = NULL;
353 LogError("Failure constructing encoding.");
354 }
355 else if ((urlEncodedSignature = URL_Encode(signature)) == NULL)
356 {
357 result = NULL;
358 LogError("Failure constructing url Signature.");
359 STRING_delete(signature);
360 }
361 else
362 {
363 const char* skn_key = "";
364 const char* skn_value = "";
365
366 if ((dev_auth_cred->sas_info.key_name != NULL) && (strlen(dev_auth_cred->sas_info.key_name) > 0))
367 {
368 // If the key name is valid then add to the sas token
369 skn_key = SKN_SECTION_FORMAT;
370 skn_value = dev_auth_cred->sas_info.key_name;
371 }
372
373 STRING_HANDLE sas_token_handle = NULL;
374
375 if (handle->urlencode_token_scope == true)
376 {
377 STRING_HANDLE url_encoded = URL_EncodeString(dev_auth_cred->sas_info.token_scope);
378 if (url_encoded == NULL)
379 {
380 LogError("failed to url string %s", dev_auth_cred->sas_info.token_scope);
381 }
382 else
383 {
384 sas_token_handle = STRING_construct_sprintf(SAS_TOKEN_FORMAT, STRING_c_str(url_encoded), STRING_c_str(urlEncodedSignature), expire_token, skn_key, skn_value);
385 }
386
387 STRING_delete(url_encoded);
388 }
389 else
390 {
391 sas_token_handle = STRING_construct_sprintf(SAS_TOKEN_FORMAT, dev_auth_cred->sas_info.token_scope, STRING_c_str(urlEncodedSignature), expire_token, skn_key, skn_value);
392 }
393
394 if (sas_token_handle == NULL)
395 {
396 result = NULL;
397 LogError("Failure constructing url Signature.");
398 }
399 else if ((result = malloc(sizeof(CREDENTIAL_RESULT))) == NULL)
400 {
401 STRING_delete(sas_token_handle);
402 LogError("Failure allocating credential result.");
403 }
404 else
405 {
406 const char* temp_sas_token = STRING_c_str(sas_token_handle);
407 if (mallocAndStrcpy_s(&handle->sas_token, temp_sas_token) != 0)
408 {
409 free(result);
410 result = NULL;
411 LogError("Failure allocating and copying string.");
412 }
413 else
414 {
415 result->auth_cred_result.sas_result.sas_token = handle->sas_token;
416 }
417 STRING_delete(sas_token_handle);
418 }
419 STRING_delete(signature);
420 STRING_delete(urlEncodedSignature);
421 }
422 free(data_value);
423 }
424 else
425 {
426 result = NULL;
427 LogError("Failure generate hash from tpm.");
428 }
429 free(payload);
430 }
431 }
432 }
433 else
434 {
435 if (handle->x509_certificate != NULL)
436 {
437 free(handle->x509_certificate);
438 handle->x509_certificate = NULL;
439 }
440 if (handle->x509_alias_key != NULL)
441 {
442 free(handle->x509_alias_key);
443 handle->x509_alias_key = NULL;
444 }
445
446 if ((result = malloc(sizeof(CREDENTIAL_RESULT))) == NULL)
447 {
448 LogError("Failure allocating credential result.");
449 }
450 else if ((handle->x509_certificate = handle->hsm_client_get_cert(handle->hsm_client_handle)) == NULL)
451 {
452 LogError("Failure allocating device credential result.");
453 free(result);
454 result = NULL;
455 }
456 else if ((handle->x509_alias_key = handle->hsm_client_get_alias_key(handle->hsm_client_handle)) == NULL)
457 {
458 LogError("Failure allocating device credential result.");
459 free(handle->x509_certificate);
460 handle->x509_certificate = NULL;
461 free(result);
462 result = NULL;
463 }
464 else
465 {
466 result->auth_cred_result.x509_result.x509_cert = handle->x509_certificate;
467 result->auth_cred_result.x509_result.x509_alias_key = handle->x509_alias_key;
468 }
469 }
470 }
471 return result;
472}
473
474#ifdef USE_EDGE_MODULES
475char* iothub_device_auth_get_trust_bundle(IOTHUB_SECURITY_HANDLE handle)
476{
477 if (handle->hsm_client_get_trust_bundle == NULL)
478 {
479 LogError("This authentication type does not support getting trusted certificates");
480 return NULL;
481 }
482 return handle->hsm_client_get_trust_bundle(handle->hsm_client_handle);
483}
484#endif
Note: See TracBrowser for help on using the repository browser.