Repository navigation
[C] Software updates: size signature buffers from the request buffer #398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
80b954d
97fa924
7a372b0
7924977
8484fab
edbed6f
9c6956c
415223f
f55a8c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license | ||
| // information. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we adding this? Don't we have base64 functionality in azure-sdk-for-c?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does use azure-sdk-for-c: the decoding itself is
|
||
|
|
||
| /* SPDX-License-Identifier: MIT */ | ||
| #include <stdint.h> | ||
| #include <string.h> | ||
|
|
||
| #include <azure/core/az_base64.h> | ||
|
|
||
| #include "internal/base64.h" | ||
|
|
||
| /** @brief Characters decoded per az_core call; a multiple of 4. */ | ||
| #define AZ_IOT_BASE64_BLOCK 64 | ||
|
|
||
| /** | ||
| * @brief 6-bit value of a base64 character. | ||
| * | ||
| * @param c The character. | ||
| * @param std Standard alphabet ('+', '/') rather than base64url ('-', '_'). | ||
| * @return The value; -1 outside the alphabet, including '='. | ||
| */ | ||
| static int32_t b64_value(uint8_t c, bool std) | ||
| { | ||
| if (c >= 'A' && c <= 'Z') | ||
| { | ||
| return c - 'A'; | ||
| } | ||
| if (c >= 'a' && c <= 'z') | ||
| { | ||
| return c - 'a' + 26; | ||
| } | ||
| if (c >= '0' && c <= '9') | ||
| { | ||
| return c - '0' + 52; | ||
| } | ||
| if (c == (std ? '+' : '-')) | ||
| { | ||
| return 62; | ||
| } | ||
| if (c == (std ? '/' : '_')) | ||
| { | ||
| return 63; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| az_iot_result az_iot_base64_decode(az_span in, bool allow_std, az_span out, az_span* out_decoded) | ||
| { | ||
| const uint8_t* p = az_span_ptr(in); | ||
| int32_t len = az_span_size(in); | ||
| if (out_decoded == NULL || len <= 0) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
|
|
||
| bool std = false; | ||
| for (int32_t i = 0; allow_std && i < len; ++i) | ||
| { | ||
| std = std || p[i] == '+' || p[i] == '/' || p[i] == '='; | ||
| } | ||
| int32_t data_len = len; | ||
| if (std) | ||
| { | ||
| if (len % 4 != 0) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
| while (data_len > len - 2 && p[data_len - 1] == '=') | ||
| { | ||
| --data_len; | ||
| } | ||
| } | ||
| int32_t rem = data_len % 4; | ||
| if (data_len <= 0 || rem == 1 || (std && len - data_len != (4 - rem) % 4)) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
| for (int32_t i = 0; i < data_len; ++i) | ||
| { | ||
| if (b64_value(p[i], std) < 0) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
| } | ||
| /* Canonical form: the bits past the last whole byte are zero. */ | ||
| int32_t last = b64_value(p[data_len - 1], std); | ||
| if ((rem == 2 && (last & 0x0F) != 0) || (rem == 3 && (last & 0x03) != 0)) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
| if ((data_len / 4) * 3 + (rem * 3) / 4 > az_span_size(out)) | ||
| { | ||
| return AZ_IOT_ERR_NOT_ENOUGH_SPACE; | ||
| } | ||
|
|
||
| /* Each block is read before its bytes are written, and output never passes | ||
| * input, so decoding in place is safe. */ | ||
| uint8_t block[AZ_IOT_BASE64_BLOCK / 4 * 3]; | ||
| uint8_t* dst = az_span_ptr(out); | ||
| int32_t w = 0; | ||
| for (int32_t i = 0; i < len; i += AZ_IOT_BASE64_BLOCK) | ||
| { | ||
| int32_t end = (len - i < AZ_IOT_BASE64_BLOCK) ? len : i + AZ_IOT_BASE64_BLOCK; | ||
| az_span src = az_span_slice(in, i, end); | ||
| int32_t written = 0; | ||
| az_result r = std ? az_base64_decode(AZ_SPAN_FROM_BUFFER(block), src, &written) | ||
| : az_base64_url_decode(AZ_SPAN_FROM_BUFFER(block), src, &written); | ||
| if (az_result_failed(r)) | ||
| { | ||
| return AZ_IOT_ERR_INVALID_ARG; | ||
| } | ||
| memmove(dst + w, block, (size_t)written); | ||
| w += written; | ||
| } | ||
| *out_decoded = az_span_create(dst, w); | ||
| return AZ_IOT_OK; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license | ||
| // information. | ||
|
|
||
| /* SPDX-License-Identifier: MIT */ | ||
| /** | ||
| * @file base64.h | ||
| * @brief Canonical base64 decoding, in place or not. | ||
| * | ||
| * Validates the input before handing it to az_core, which left-shifts a | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we adding this? Don't we have base64 functionality in azure-sdk-for-c?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does use azure-sdk-for-c: the decoding itself is
|
||
| * negative value on a character outside the alphabet and accepts nonzero | ||
| * trailing bits. Decodes in blocks through a small buffer, so the output may | ||
| * overwrite the input. | ||
| */ | ||
| #ifndef AZ_IOT_BASE64_H | ||
| #define AZ_IOT_BASE64_H | ||
|
|
||
| #include <stdbool.h> | ||
|
|
||
| #include <azure/core/az_span.h> | ||
|
|
||
| #include "azure/iot/az_iot_result.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" | ||
| { | ||
| #endif | ||
|
|
||
| /** | ||
| * @brief Decode canonical unpadded base64url or, if @p allow_std, padded standard base64. | ||
| * | ||
| * Standard base64 is chosen when @p in has '+', '/' or '='. Its length must be a multiple | ||
| * of 4, with at most two trailing '='. Unused trailing bits must be zero. | ||
| * | ||
| * @param in Encoded text. | ||
| * @param allow_std Also accept standard base64. | ||
| * @param out Destination. May start at az_span_ptr(@p in) (in place); must not | ||
| * otherwise overlap @p in. | ||
| * @param out_decoded The decoded slice of @p out. Untouched on error; @p out may then hold | ||
| * a partial result. | ||
| * @return AZ_IOT_OK; AZ_IOT_ERR_INVALID_ARG if @p in is empty, has a character outside the | ||
| * alphabet, misplaced padding, a bad length or nonzero trailing bits; | ||
| * AZ_IOT_ERR_NOT_ENOUGH_SPACE when @p out is too small. | ||
| */ | ||
| az_iot_result az_iot_base64_decode(az_span in, bool allow_std, az_span out, az_span* out_decoded); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* AZ_IOT_BASE64_H */ | ||
Uh oh!
There was an error while loading. Please reload this page.