blob: 6c2a71f0044b5f76c69e9a918d84f6d2e892ad1d [file] [log] [blame]
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001/*
2 * ASN.1 buffer writing functionality
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * 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, WITHOUT
15 * 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.
Paul Bakkerbdb912d2012-02-13 23:11:30 +000018 */
19
Gilles Peskinedb09ef62020-06-03 01:43:33 +020020#include "common.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if defined(MBEDTLS_ASN1_WRITE_C)
Paul Bakkerbdb912d2012-02-13 23:11:30 +000023
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000024#include "mbedtls/asn1write.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000025#include "mbedtls/error.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000026
Rich Evans00ab4702015-02-06 13:43:58 +000027#include <string.h>
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/platform.h"
Paul Bakker59ba59f2013-09-09 11:26:00 +020031#else
32#include <stdlib.h>
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020033#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#define mbedtls_free free
Paul Bakker59ba59f2013-09-09 11:26:00 +020035#endif
36
Mateusz Starzyk4e300d02021-01-27 15:37:12 +010037int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_t len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +000038{
39 if( len < 0x80 )
40 {
41 if( *p - start < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +000043
Paul Bakkerb9cfaa02013-10-11 18:58:55 +020044 *--(*p) = (unsigned char) len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000045 return( 1 );
46 }
47
48 if( len <= 0xFF )
49 {
50 if( *p - start < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +000052
Paul Bakkerb9cfaa02013-10-11 18:58:55 +020053 *--(*p) = (unsigned char) len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000054 *--(*p) = 0x81;
55 return( 2 );
56 }
57
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010058 if( len <= 0xFFFF )
59 {
60 if( *p - start < 3 )
61 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +000062
Joe Subbiani2194dc42021-07-14 12:31:31 +010063 *--(*p) = MBEDTLS_BYTE_0( len );
64 *--(*p) = MBEDTLS_BYTE_1( len );
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010065 *--(*p) = 0x82;
66 return( 3 );
67 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +000068
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010069 if( len <= 0xFFFFFF )
70 {
71 if( *p - start < 4 )
72 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
73
Joe Subbiani2194dc42021-07-14 12:31:31 +010074 *--(*p) = MBEDTLS_BYTE_0( len );
75 *--(*p) = MBEDTLS_BYTE_1( len );
76 *--(*p) = MBEDTLS_BYTE_2( len );
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010077 *--(*p) = 0x83;
78 return( 4 );
79 }
80
David Horstmann8a7629f2022-10-06 18:57:57 +010081 int len_valid = 1;
Azim Khan45b79cf2018-05-23 16:55:16 +010082#if SIZE_MAX > 0xFFFFFFFF
David Horstmann8a7629f2022-10-06 18:57:57 +010083 len_valid = ( len <= 0xFFFFFFFF );
Azim Khan45b79cf2018-05-23 16:55:16 +010084#endif
David Horstmann8a7629f2022-10-06 18:57:57 +010085 if( len_valid )
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010086 {
87 if( *p - start < 5 )
88 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
89
Joe Subbiani2194dc42021-07-14 12:31:31 +010090 *--(*p) = MBEDTLS_BYTE_0( len );
91 *--(*p) = MBEDTLS_BYTE_1( len );
92 *--(*p) = MBEDTLS_BYTE_2( len );
93 *--(*p) = MBEDTLS_BYTE_3( len );
Paul Bakkerc7d6bd42016-07-14 11:39:56 +010094 *--(*p) = 0x84;
95 return( 5 );
96 }
David Horstmann8a7629f2022-10-06 18:57:57 +010097 else
98 {
99 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
100 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000101}
102
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100103int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, unsigned char tag )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000104{
105 if( *p - start < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000107
108 *--(*p) = tag;
109
110 return( 1 );
111}
112
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100113int mbedtls_asn1_write_raw_buffer( unsigned char **p, const unsigned char *start,
Paul Bakker9852d002013-08-26 17:56:37 +0200114 const unsigned char *buf, size_t size )
115{
116 size_t len = 0;
117
Manuel Pégourié-Gonnard22c3b7b2015-10-21 12:07:47 +0200118 if( *p < start || (size_t)( *p - start ) < size )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakker9852d002013-08-26 17:56:37 +0200120
121 len = size;
122 (*p) -= len;
123 memcpy( *p, buf, len );
124
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200125 return( (int) len );
Paul Bakker9852d002013-08-26 17:56:37 +0200126}
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#if defined(MBEDTLS_BIGNUM_C)
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100129int mbedtls_asn1_write_mpi( unsigned char **p, const unsigned char *start, const mbedtls_mpi *X )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000130{
Janos Follath24eed8d2019-11-22 13:21:35 +0000131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000132 size_t len = 0;
133
134 // Write the MPI
135 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 len = mbedtls_mpi_size( X );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000137
Gilles Peskine321a0892022-06-10 20:13:33 +0200138 /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
139 * as 0 digits. We need to end up with 020100, not with 0200. */
140 if( len == 0 )
141 len = 1;
142
Manuel Pégourié-Gonnard22c3b7b2015-10-21 12:07:47 +0200143 if( *p < start || (size_t)( *p - start ) < len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000145
146 (*p) -= len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000148
149 // DER format assumes 2s complement for numbers, so the leftmost bit
150 // should be 0 for positive numbers and 1 for negative numbers.
151 //
Paul Bakker66d5d072014-06-17 16:39:18 +0200152 if( X->s ==1 && **p & 0x80 )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000153 {
154 if( *p - start < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000156
157 *--(*p) = 0x00;
158 len += 1;
159 }
160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
162 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000163
Paul Bakker3d8fb632014-04-17 12:42:41 +0200164 ret = (int) len;
165
166cleanup:
167 return( ret );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000168}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169#endif /* MBEDTLS_BIGNUM_C */
Paul Bakkered27a042013-04-18 22:46:23 +0200170
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100171int mbedtls_asn1_write_null( unsigned char **p, const unsigned char *start )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000172{
Janos Follath24eed8d2019-11-22 13:21:35 +0000173 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000174 size_t len = 0;
175
176 // Write NULL
177 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
179 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000180
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200181 return( (int) len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000182}
183
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100184int mbedtls_asn1_write_oid( unsigned char **p, const unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200185 const char *oid, size_t oid_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000186{
Janos Follath24eed8d2019-11-22 13:21:35 +0000187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000188 size_t len = 0;
189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200191 (const unsigned char *) oid, oid_len ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
193 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000194
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200195 return( (int) len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000196}
197
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100198int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, const unsigned char *start,
Manuel Pégourié-Gonnardedda9042013-09-12 02:17:54 +0200199 const char *oid, size_t oid_len,
200 size_t par_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000201{
Janos Follath24eed8d2019-11-22 13:21:35 +0000202 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000203 size_t len = 0;
204
Manuel Pégourié-Gonnardedda9042013-09-12 02:17:54 +0200205 if( par_len == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
Manuel Pégourié-Gonnardedda9042013-09-12 02:17:54 +0200207 else
208 len += par_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
213 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
214 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000215
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200216 return( (int) len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000217}
218
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100219int mbedtls_asn1_write_bool( unsigned char **p, const unsigned char *start, int boolean )
Paul Bakker329def32013-09-06 16:34:38 +0200220{
Janos Follath24eed8d2019-11-22 13:21:35 +0000221 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker329def32013-09-06 16:34:38 +0200222 size_t len = 0;
223
224 if( *p - start < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakker329def32013-09-06 16:34:38 +0200226
Jonathan Leroy87c96c22015-10-14 09:41:56 +0200227 *--(*p) = (boolean) ? 255 : 0;
Paul Bakker329def32013-09-06 16:34:38 +0200228 len++;
229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
231 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
Paul Bakker329def32013-09-06 16:34:38 +0200232
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200233 return( (int) len );
Paul Bakker329def32013-09-06 16:34:38 +0200234}
235
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100236static int asn1_write_tagged_int( unsigned char **p, const unsigned char *start, int val, int tag )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000237{
Janos Follath24eed8d2019-11-22 13:21:35 +0000238 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000239 size_t len = 0;
240
Gilles Peskine1dbab672019-03-01 18:15:18 +0100241 do
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000242 {
243 if( *p - start < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Gilles Peskine1dbab672019-03-01 18:15:18 +0100245 len += 1;
246 *--(*p) = val & 0xff;
247 val >>= 8;
248 }
249 while( val > 0 );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000250
Gilles Peskine1dbab672019-03-01 18:15:18 +0100251 if( **p & 0x80 )
252 {
253 if( *p - start < 1 )
254 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000255 *--(*p) = 0x00;
256 len += 1;
257 }
258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
Mykhailo Sopiha20180ca2019-10-29 15:58:10 +0200260 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000261
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200262 return( (int) len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000263}
264
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100265int mbedtls_asn1_write_int( unsigned char **p, const unsigned char *start, int val )
Mykhailo Sopiha20180ca2019-10-29 15:58:10 +0200266{
267 return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
268}
269
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100270int mbedtls_asn1_write_enum( unsigned char **p, const unsigned char *start, int val )
Mykhailo Sopiha20180ca2019-10-29 15:58:10 +0200271{
272 return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
273}
274
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100275int mbedtls_asn1_write_tagged_string( unsigned char **p, const unsigned char *start, int tag,
Jaeden Amero23f954d2018-05-17 11:46:13 +0100276 const char *text, size_t text_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000277{
Janos Follath24eed8d2019-11-22 13:21:35 +0000278 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000279 size_t len = 0;
280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Jaeden Amero23f954d2018-05-17 11:46:13 +0100282 (const unsigned char *) text, text_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
Jaeden Amero23f954d2018-05-17 11:46:13 +0100285 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000286
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200287 return( (int) len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000288}
Paul Bakker598e4502013-08-25 14:46:39 +0200289
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100290int mbedtls_asn1_write_utf8_string( unsigned char **p, const unsigned char *start,
Jaeden Amero23f954d2018-05-17 11:46:13 +0100291 const char *text, size_t text_len )
292{
thomas-deeeba6c9b2018-09-19 09:10:37 +0200293 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
Jaeden Amero23f954d2018-05-17 11:46:13 +0100294}
295
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100296int mbedtls_asn1_write_printable_string( unsigned char **p, const unsigned char *start,
Jaeden Amero23f954d2018-05-17 11:46:13 +0100297 const char *text, size_t text_len )
298{
thomas-deeeba6c9b2018-09-19 09:10:37 +0200299 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
Jaeden Amero23f954d2018-05-17 11:46:13 +0100300}
301
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100302int mbedtls_asn1_write_ia5_string( unsigned char **p, const unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200303 const char *text, size_t text_len )
Paul Bakker05888152012-02-16 10:26:57 +0000304{
thomas-deeeba6c9b2018-09-19 09:10:37 +0200305 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
Paul Bakker05888152012-02-16 10:26:57 +0000306}
Paul Bakker598e4502013-08-25 14:46:39 +0200307
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100308int mbedtls_asn1_write_named_bitstring( unsigned char **p,
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100309 const unsigned char *start,
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100310 const unsigned char *buf,
311 size_t bits )
312{
313 size_t unused_bits, byte_len;
314 const unsigned char *cur_byte;
315 unsigned char cur_byte_shifted;
316 unsigned char bit;
317
318 byte_len = ( bits + 7 ) / 8;
319 unused_bits = ( byte_len * 8 ) - bits;
320
321 /*
322 * Named bitstrings require that trailing 0s are excluded in the encoding
323 * of the bitstring. Trailing 0s are considered part of the 'unused' bits
324 * when encoding this value in the first content octet
325 */
326 if( bits != 0 )
327 {
328 cur_byte = buf + byte_len - 1;
329 cur_byte_shifted = *cur_byte >> unused_bits;
330
331 for( ; ; )
332 {
333 bit = cur_byte_shifted & 0x1;
334 cur_byte_shifted >>= 1;
335
336 if( bit != 0 )
337 break;
338
339 bits--;
340 if( bits == 0 )
341 break;
342
343 if( bits % 8 == 0 )
344 cur_byte_shifted = *--cur_byte;
345 }
346 }
347
348 return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
349}
350
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100351int mbedtls_asn1_write_bitstring( unsigned char **p, const unsigned char *start,
Paul Bakker598e4502013-08-25 14:46:39 +0200352 const unsigned char *buf, size_t bits )
353{
Janos Follath24eed8d2019-11-22 13:21:35 +0000354 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100355 size_t len = 0;
356 size_t unused_bits, byte_len;
Paul Bakker598e4502013-08-25 14:46:39 +0200357
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100358 byte_len = ( bits + 7 ) / 8;
359 unused_bits = ( byte_len * 8 ) - bits;
Paul Bakker598e4502013-08-25 14:46:39 +0200360
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100361 if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
Paul Bakker598e4502013-08-25 14:46:39 +0200363
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100364 len = byte_len + 1;
Paul Bakker598e4502013-08-25 14:46:39 +0200365
Andres Amaya Garciaec6329f2018-09-26 10:48:24 +0100366 /* Write the bitstring. Ensure the unused bits are zeroed */
367 if( byte_len > 0 )
368 {
369 byte_len--;
370 *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
371 ( *p ) -= byte_len;
372 memcpy( *p, buf, byte_len );
373 }
374
375 /* Write unused bits */
376 *--( *p ) = (unsigned char)unused_bits;
Paul Bakker598e4502013-08-25 14:46:39 +0200377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
379 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
Paul Bakker598e4502013-08-25 14:46:39 +0200380
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200381 return( (int) len );
Paul Bakker598e4502013-08-25 14:46:39 +0200382}
383
Mateusz Starzyk4e300d02021-01-27 15:37:12 +0100384int mbedtls_asn1_write_octet_string( unsigned char **p, const unsigned char *start,
Paul Bakker598e4502013-08-25 14:46:39 +0200385 const unsigned char *buf, size_t size )
386{
Janos Follath24eed8d2019-11-22 13:21:35 +0000387 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker598e4502013-08-25 14:46:39 +0200388 size_t len = 0;
389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
Paul Bakker598e4502013-08-25 14:46:39 +0200391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
393 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
Paul Bakker598e4502013-08-25 14:46:39 +0200394
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200395 return( (int) len );
Paul Bakker598e4502013-08-25 14:46:39 +0200396}
Paul Bakker59ba59f2013-09-09 11:26:00 +0200397
Hanno Becker44da18a2018-10-12 10:42:13 +0100398
399/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
400 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
401static mbedtls_asn1_named_data *asn1_find_named_data(
402 mbedtls_asn1_named_data *list,
403 const char *oid, size_t len )
404{
405 while( list != NULL )
406 {
407 if( list->oid.len == len &&
408 memcmp( list->oid.p, oid, len ) == 0 )
409 {
410 break;
411 }
412
413 list = list->next;
414 }
415
416 return( list );
417}
418
419mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
420 mbedtls_asn1_named_data **head,
Paul Bakker59ba59f2013-09-09 11:26:00 +0200421 const char *oid, size_t oid_len,
422 const unsigned char *val,
423 size_t val_len )
424{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 mbedtls_asn1_named_data *cur;
Paul Bakker59ba59f2013-09-09 11:26:00 +0200426
Hanno Becker44da18a2018-10-12 10:42:13 +0100427 if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200428 {
429 // Add new entry if not present yet based on OID
430 //
Simon Butcher29176892016-05-20 00:19:09 +0100431 cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
432 sizeof(mbedtls_asn1_named_data) );
433 if( cur == NULL )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200434 return( NULL );
435
Paul Bakker59ba59f2013-09-09 11:26:00 +0200436 cur->oid.len = oid_len;
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200437 cur->oid.p = mbedtls_calloc( 1, oid_len );
Paul Bakker59ba59f2013-09-09 11:26:00 +0200438 if( cur->oid.p == NULL )
439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 mbedtls_free( cur );
Paul Bakker59ba59f2013-09-09 11:26:00 +0200441 return( NULL );
442 }
443
Manuel Pégourié-Gonnarde5b0fc12014-11-12 22:27:42 +0100444 memcpy( cur->oid.p, oid, oid_len );
445
Paul Bakker59ba59f2013-09-09 11:26:00 +0200446 cur->val.len = val_len;
Gilles Peskine09c0a232019-03-04 15:00:06 +0100447 if( val_len != 0 )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200448 {
Gilles Peskine09c0a232019-03-04 15:00:06 +0100449 cur->val.p = mbedtls_calloc( 1, val_len );
450 if( cur->val.p == NULL )
451 {
452 mbedtls_free( cur->oid.p );
453 mbedtls_free( cur );
454 return( NULL );
455 }
Paul Bakker59ba59f2013-09-09 11:26:00 +0200456 }
457
Paul Bakker59ba59f2013-09-09 11:26:00 +0200458 cur->next = *head;
459 *head = cur;
460 }
Gilles Peskine09c0a232019-03-04 15:00:06 +0100461 else if( val_len == 0 )
462 {
463 mbedtls_free( cur->val.p );
464 cur->val.p = NULL;
465 }
466 else if( cur->val.len != val_len )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200467 {
Manuel Pégourié-Gonnard97b52092015-12-10 10:50:51 +0100468 /*
469 * Enlarge existing value buffer if needed
470 * Preserve old data until the allocation succeeded, to leave list in
471 * a consistent state in case allocation fails.
472 */
473 void *p = mbedtls_calloc( 1, val_len );
474 if( p == NULL )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200475 return( NULL );
Manuel Pégourié-Gonnard97b52092015-12-10 10:50:51 +0100476
477 mbedtls_free( cur->val.p );
478 cur->val.p = p;
479 cur->val.len = val_len;
Paul Bakker59ba59f2013-09-09 11:26:00 +0200480 }
481
Werner Lewise59a5312022-05-04 09:44:50 +0100482 if( val != NULL && val_len != 0 )
Paul Bakker59ba59f2013-09-09 11:26:00 +0200483 memcpy( cur->val.p, val, val_len );
484
485 return( cur );
486}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487#endif /* MBEDTLS_ASN1_WRITE_C */