1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
#ifndef AWS_C_CAL_DER_H
#define AWS_C_CAL_DER_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/cal/exports.h>
#include <aws/common/array_list.h>
#include <aws/common/byte_buf.h>
struct aws_der_encoder;
struct aws_der_decoder;
/*
* Note: encoder/decoder only supports unsigned representations of integers and usage
* of signed integers might lead to unexpected results.
* Context: DER spec requires ints to be stored in big endian format with MSB
* representing signedness. To disambiguate between negative number and big
* positive number, null byte can be added in front of positive number. DER spec
* requires representation to be the shortest possible one.
* During encoding aws_der_encoder_write_unsigned_integer assumes that cursor
* points to a positive number and will prepend 0 if needed by DER spec to
* indicate its positive number. Encoder does not support writing negative numbers.
* Decoder aws_der_encoder_write_unsigned_integer will strip any leading 0 as
* needed and will error out if der contains negative number.
* Take special care when integrating with 3p libraries cause they might expect
* different format. Ex. this format matches what openssl calls bin format
* (BN_bin2bn) and might not work as expected with openssl mpi format.
*/
enum aws_der_type {
/* Primitives */
AWS_DER_BOOLEAN = 0x01,
AWS_DER_INTEGER = 0x02,
AWS_DER_BIT_STRING = 0x03,
AWS_DER_OCTET_STRING = 0x04,
AWS_DER_NULL = 0x05,
AWS_DER_OBJECT_IDENTIFIER = 0x06,
AWS_DER_BMPString = 0x1e,
AWS_DER_UNICODE_STRING = AWS_DER_BMPString,
AWS_DER_IA5String = 0x16, /* Unsupported */
AWS_DER_PrintableString = 0x13,
AWS_DER_TeletexString = 0x14, /* Unsupported */
/* Constructed types */
AWS_DER_SEQUENCE = 0x30,
AWS_DER_SEQUENCE_OF = AWS_DER_SEQUENCE,
AWS_DER_SET = 0x31,
AWS_DER_SET_OF = AWS_DER_SET,
AWS_DER_UTF8_STRING = 0x0c,
/* class types */
AWS_DER_CLASS_UNIVERSAL = 0x00,
AWS_DER_CLASS_APPLICATION = 0x40,
AWS_DER_CLASS_CONTEXT = 0x80,
AWS_DER_CLASS_PRIVATE = 0xc0,
/* forms */
AWS_DER_FORM_CONSTRUCTED = 0x20,
AWS_DER_FORM_PRIMITIVE = 0x00,
};
AWS_EXTERN_C_BEGIN
/**
* Initializes a DER encoder
* @param allocator The allocator to use for all allocations within the encoder
* @param capacity The initial capacity of the encoder scratch buffer (the max size of all encoded TLVs)
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API struct aws_der_encoder *aws_der_encoder_new(struct aws_allocator *allocator, size_t capacity);
/**
* Cleans up a DER encoder
* @param encoder The encoder to clean up
*
* Note that this destroys the encoder buffer, invalidating any references to the contents given via get_contents()
*/
AWS_CAL_API void aws_der_encoder_destroy(struct aws_der_encoder *encoder);
/**
* Writes an arbitrarily sized integer to the DER stream
* @param encoder The encoder to use
* @param integer A cursor pointing to the integer's memory
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_write_unsigned_integer(struct aws_der_encoder *encoder, struct aws_byte_cursor integer);
/**
* Writes a boolean to the DER stream
* @param encoder The encoder to use
* @param boolean The boolean to write
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_write_boolean(struct aws_der_encoder *encoder, bool boolean);
/**
* Writes a NULL token to the stream
* @param encoder The encoder to write to
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_write_null(struct aws_der_encoder *encoder);
/**
* Writes a BIT_STRING to the stream
* @param encoder The encoder to use
* @param bit_string The bit string to encode
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_write_bit_string(struct aws_der_encoder *encoder, struct aws_byte_cursor bit_string);
/**
* Writes a string to the stream
* @param encoder The encoder to use
* @param octet_string The string to encode
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_write_octet_string(
struct aws_der_encoder *encoder,
struct aws_byte_cursor octet_string);
/**
* Begins a SEQUENCE of objects in the DER stream
* @param encoder The encoder to use
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_begin_sequence(struct aws_der_encoder *encoder);
/**
* Finishes a SEQUENCE and applies it to the DER stream buffer
* @param encoder The encoder to update
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_end_sequence(struct aws_der_encoder *encoder);
/**
* Begins a SET of objects in the DER stream
* @param encoder The encoder to use
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_begin_set(struct aws_der_encoder *encoder);
/**
* Finishes a SET and applies it to the DER stream buffer
* @param encoder The encoder to update
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_end_set(struct aws_der_encoder *encoder);
/**
* Retrieves the contents of the encoder stream buffer
* @param encoder The encoder to read from
* @param cursor The cursor to point at the stream buffer
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_encoder_get_contents(struct aws_der_encoder *encoder, struct aws_byte_cursor *contents);
/**
* Initializes an DER decoder
* @param allocator The allocator to use
* @param input The DER formatted buffer to parse
* @return Initialized decoder, or NULL
*/
AWS_CAL_API struct aws_der_decoder *aws_der_decoder_new(struct aws_allocator *allocator, struct aws_byte_cursor input);
/**
* Cleans up a DER encoder
* @param decoder The encoder to clean up
*/
AWS_CAL_API void aws_der_decoder_destroy(struct aws_der_decoder *decoder);
/**
* Allows for iteration over the decoded TLVs.
* @param decoder The decoder to iterate over
* @return true if there is a tlv to read after advancing, false when done
*/
AWS_CAL_API bool aws_der_decoder_next(struct aws_der_decoder *decoder);
/**
* The type of the current TLV
* @param decoder The decoder to inspect
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API enum aws_der_type aws_der_decoder_tlv_type(struct aws_der_decoder *decoder);
/**
* The size of the current TLV
* @param decoder The decoder to inspect
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API size_t aws_der_decoder_tlv_length(struct aws_der_decoder *decoder);
/**
* The number of elements in the current TLV container
* @param decoder The decoder to inspect
* @return Number of elements in the current container
*/
AWS_CAL_API size_t aws_der_decoder_tlv_count(struct aws_der_decoder *decoder);
/**
* Extracts the current TLV string value (BIT_STRING, OCTET_STRING)
* @param decoder The decoder to extract from
* @param string The buffer to store the string into
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_decoder_tlv_string(struct aws_der_decoder *decoder, struct aws_byte_cursor *string);
/**
* Extracts the current TLV INTEGER value (INTEGER)
* @param decoder The decoder to extract from
* @param integer The buffer to store the integer into
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_decoder_tlv_unsigned_integer(struct aws_der_decoder *decoder, struct aws_byte_cursor *integer);
/**
* Extracts the current TLV BOOLEAN value (BOOLEAN)
* @param decoder The decoder to extract from
* @param boolean The boolean to store the value into
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_decoder_tlv_boolean(struct aws_der_decoder *decoder, bool *boolean);
/**
* Extracts the current TLV value as a blob
* @param decoder The decoder to extract from
* @param blob The buffer to store the value into
* @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS
*/
AWS_CAL_API int aws_der_decoder_tlv_blob(struct aws_der_decoder *decoder, struct aws_byte_cursor *blob);
AWS_EXTERN_C_END
#endif
|