Skip to content

Commit 74ac6e3

Browse files
committed
Merge remote-tracking branch 'public/pr/2028' into development
* public/pr/2028: Update the crypto submodule to a78c958 Fix ChangeLog entry to correct release version Fix typo in x509write test data Add ChangeLog entry for unused bits in bitstrings Improve docs for named bitstrings and their usage Add tests for (named) bitstring to suite_asn1write Add new function mbedtls_asn1_write_named_bitstring()
2 parents bbed914 + 1e198f5 commit 74ac6e3

23 files changed

+403
-104
lines changed

ChangeLog

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Features
77
which allows copy-less parsing of DER encoded X.509 CRTs,
88
at the cost of additional lifetime constraints on the input
99
buffer, but at the benefit of reduced RAM consumption.
10+
* Add a new function mbedtls_asn1_write_named_bitstring() to write ASN.1
11+
named bitstring in DER as required by RFC 5280 Appendix B.
1012

1113
API Changes
1214
* Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.
@@ -31,6 +33,12 @@ Bugfix
3133
Fixes #2190.
3234
* Fix false failure in all.sh when backup files exist in include/mbedtls
3335
(e.g. config.h.bak). Fixed by Peter Kolbus (Garmin) #2407.
36+
* Ensure that unused bits are zero when writing ASN.1 bitstrings when using
37+
mbedtls_asn1_write_bitstring().
38+
* Fix issue when writing the named bitstrings in KeyUsage and NsCertType
39+
extensions in CSRs and CRTs that caused these bitstrings to not be encoded
40+
correctly as trailing zeroes were not accounted for as unused bits in the
41+
leading content octet. Fixes #1610.
3442

3543
Changes
3644
* Reduce RAM consumption during session renegotiation by not storing

crypto

Submodule crypto updated 60 files

include/mbedtls/asn1write.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,28 @@ int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
282282
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
283283
const unsigned char *buf, size_t bits );
284284

285+
/**
286+
* \brief This function writes a named bitstring tag
287+
* (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format.
288+
*
289+
* As stated in RFC 5280 Appendix B, trailing zeroes are
290+
* omitted when encoding named bitstrings in DER.
291+
*
292+
* \note This function works backwards within the data buffer.
293+
*
294+
* \param p The reference to the current position pointer.
295+
* \param start The start of the buffer which is used for bounds-checking.
296+
* \param buf The bitstring to write.
297+
* \param bits The total number of bits in the bitstring.
298+
*
299+
* \return The number of bytes written to \p p on success.
300+
* \return A negative error code on failure.
301+
*/
302+
int mbedtls_asn1_write_named_bitstring( unsigned char **p,
303+
unsigned char *start,
304+
const unsigned char *buf,
305+
size_t bits );
306+
285307
/**
286308
* \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
287309
* and value in ASN.1 format.

include/mbedtls/x509_csr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_ty
205205
* \param key_usage key usage flags to set
206206
*
207207
* \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED
208+
*
209+
* \note The <code>decipherOnly</code> flag from the Key Usage
210+
* extension is represented by bit 8 (i.e.
211+
* <code>0x8000</code>), which cannot typically be represented
212+
* in an unsigned char. Therefore, the flag
213+
* <code>decipherOnly</code> (i.e.
214+
* #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this
215+
* function.
208216
*/
209217
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage );
210218

library/asn1write.c

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -290,26 +290,75 @@ int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
290290
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
291291
}
292292

293+
int mbedtls_asn1_write_named_bitstring( unsigned char **p,
294+
unsigned char *start,
295+
const unsigned char *buf,
296+
size_t bits )
297+
{
298+
size_t unused_bits, byte_len;
299+
const unsigned char *cur_byte;
300+
unsigned char cur_byte_shifted;
301+
unsigned char bit;
302+
303+
byte_len = ( bits + 7 ) / 8;
304+
unused_bits = ( byte_len * 8 ) - bits;
305+
306+
/*
307+
* Named bitstrings require that trailing 0s are excluded in the encoding
308+
* of the bitstring. Trailing 0s are considered part of the 'unused' bits
309+
* when encoding this value in the first content octet
310+
*/
311+
if( bits != 0 )
312+
{
313+
cur_byte = buf + byte_len - 1;
314+
cur_byte_shifted = *cur_byte >> unused_bits;
315+
316+
for( ; ; )
317+
{
318+
bit = cur_byte_shifted & 0x1;
319+
cur_byte_shifted >>= 1;
320+
321+
if( bit != 0 )
322+
break;
323+
324+
bits--;
325+
if( bits == 0 )
326+
break;
327+
328+
if( bits % 8 == 0 )
329+
cur_byte_shifted = *--cur_byte;
330+
}
331+
}
332+
333+
return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
334+
}
335+
293336
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
294337
const unsigned char *buf, size_t bits )
295338
{
296339
int ret;
297-
size_t len = 0, size;
340+
size_t len = 0;
341+
size_t unused_bits, byte_len;
298342

299-
size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
343+
byte_len = ( bits + 7 ) / 8;
344+
unused_bits = ( byte_len * 8 ) - bits;
300345

301-
// Calculate byte length
302-
//
303-
if( *p < start || (size_t)( *p - start ) < size + 1 )
346+
if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
304347
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
305348

306-
len = size + 1;
307-
(*p) -= size;
308-
memcpy( *p, buf, size );
349+
len = byte_len + 1;
309350

310-
// Write unused bits
311-
//
312-
*--(*p) = (unsigned char) (size * 8 - bits);
351+
/* Write the bitstring. Ensure the unused bits are zeroed */
352+
if( byte_len > 0 )
353+
{
354+
byte_len--;
355+
*--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
356+
( *p ) -= byte_len;
357+
memcpy( *p, buf, byte_len );
358+
}
359+
360+
/* Write unused bits */
361+
*--( *p ) = (unsigned char)unused_bits;
313362

314363
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
315364
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );

library/x509write_crt.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,23 +221,36 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
221221
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
222222
unsigned int key_usage )
223223
{
224-
unsigned char buf[4], ku;
224+
unsigned char buf[5], ku[2];
225225
unsigned char *c;
226226
int ret;
227-
228-
/* We currently only support 7 bits, from 0x80 to 0x02 */
229-
if( ( key_usage & ~0xfe ) != 0 )
227+
const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
228+
MBEDTLS_X509_KU_NON_REPUDIATION |
229+
MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
230+
MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
231+
MBEDTLS_X509_KU_KEY_AGREEMENT |
232+
MBEDTLS_X509_KU_KEY_CERT_SIGN |
233+
MBEDTLS_X509_KU_CRL_SIGN |
234+
MBEDTLS_X509_KU_ENCIPHER_ONLY |
235+
MBEDTLS_X509_KU_DECIPHER_ONLY;
236+
237+
/* Check that nothing other than the allowed flags is set */
238+
if( ( key_usage & ~allowed_bits ) != 0 )
230239
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
231240

232-
c = buf + 4;
233-
ku = (unsigned char) key_usage;
241+
c = buf + 5;
242+
ku[0] = (unsigned char)( key_usage );
243+
ku[1] = (unsigned char)( key_usage >> 8 );
244+
ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
234245

235-
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 )
246+
if( ret < 0 )
236247
return( ret );
248+
else if( ret < 3 || ret > 5 )
249+
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
237250

238251
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
239252
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
240-
1, buf, 4 );
253+
1, c, (size_t)ret );
241254
if( ret != 0 )
242255
return( ret );
243256

@@ -253,12 +266,13 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
253266

254267
c = buf + 4;
255268

256-
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
269+
ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
270+
if( ret < 3 || ret > 4 )
257271
return( ret );
258272

259273
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
260274
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
261-
0, buf, 4 );
275+
0, c, (size_t)ret );
262276
if( ret != 0 )
263277
return( ret );
264278

library/x509write_csr.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned ch
9494

9595
c = buf + 4;
9696

97-
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
97+
ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 );
98+
if( ret < 3 || ret > 4 )
9899
return( ret );
99100

100101
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
101102
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
102-
buf, 4 );
103+
c, (size_t)ret );
103104
if( ret != 0 )
104105
return( ret );
105106

@@ -115,12 +116,13 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
115116

116117
c = buf + 4;
117118

118-
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
119+
ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
120+
if( ret < 3 || ret > 4 )
119121
return( ret );
120122

121123
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
122124
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
123-
buf, 4 );
125+
c, (size_t)ret );
124126
if( ret != 0 )
125127
return( ret );
126128

programs/x509/cert_req.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ int main( void )
6565
#define DFL_OUTPUT_FILENAME "cert.req"
6666
#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK"
6767
#define DFL_KEY_USAGE 0
68+
#define DFL_FORCE_KEY_USAGE 0
6869
#define DFL_NS_CERT_TYPE 0
70+
#define DFL_FORCE_NS_CERT_TYPE 0
6971
#define DFL_MD_ALG MBEDTLS_MD_SHA256
7072

7173
#define USAGE \
@@ -85,6 +87,8 @@ int main( void )
8587
" key_agreement\n" \
8688
" key_cert_sign\n" \
8789
" crl_sign\n" \
90+
" force_key_usage=0/1 default: off\n" \
91+
" Add KeyUsage even if it is empty\n" \
8892
" ns_cert_type=%%s default: (empty)\n" \
8993
" Comma-separated-list of values:\n" \
9094
" ssl_client\n" \
@@ -94,6 +98,8 @@ int main( void )
9498
" ssl_ca\n" \
9599
" email_ca\n" \
96100
" object_signing_ca\n" \
101+
" force_ns_cert_type=0/1 default: off\n" \
102+
" Add NsCertType even if it is empty\n" \
97103
" md=%%s default: SHA256\n" \
98104
" possible values:\n" \
99105
" MD4, MD5, SHA1\n" \
@@ -123,7 +129,9 @@ struct options
123129
const char *output_file; /* where to store the constructed key file */
124130
const char *subject_name; /* subject name for certificate request */
125131
unsigned char key_usage; /* key usage flags */
132+
int force_key_usage; /* Force adding the KeyUsage extension */
126133
unsigned char ns_cert_type; /* NS cert type */
134+
int force_ns_cert_type; /* Force adding NsCertType extension */
127135
mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */
128136
} opt;
129137

@@ -190,7 +198,9 @@ int main( int argc, char *argv[] )
190198
opt.output_file = DFL_OUTPUT_FILENAME;
191199
opt.subject_name = DFL_SUBJECT_NAME;
192200
opt.key_usage = DFL_KEY_USAGE;
201+
opt.force_key_usage = DFL_FORCE_KEY_USAGE;
193202
opt.ns_cert_type = DFL_NS_CERT_TYPE;
203+
opt.force_ns_cert_type = DFL_FORCE_NS_CERT_TYPE;
194204
opt.md_alg = DFL_MD_ALG;
195205

196206
for( i = 1; i < argc; i++ )
@@ -292,6 +302,15 @@ int main( int argc, char *argv[] )
292302
q = r;
293303
}
294304
}
305+
else if( strcmp( p, "force_key_usage" ) == 0 )
306+
{
307+
switch( atoi( q ) )
308+
{
309+
case 0: opt.force_key_usage = 0; break;
310+
case 1: opt.force_key_usage = 1; break;
311+
default: goto usage;
312+
}
313+
}
295314
else if( strcmp( p, "ns_cert_type" ) == 0 )
296315
{
297316
while( q != NULL )
@@ -319,16 +338,25 @@ int main( int argc, char *argv[] )
319338
q = r;
320339
}
321340
}
341+
else if( strcmp( p, "force_ns_cert_type" ) == 0 )
342+
{
343+
switch( atoi( q ) )
344+
{
345+
case 0: opt.force_ns_cert_type = 0; break;
346+
case 1: opt.force_ns_cert_type = 1; break;
347+
default: goto usage;
348+
}
349+
}
322350
else
323351
goto usage;
324352
}
325353

326354
mbedtls_x509write_csr_set_md_alg( &req, opt.md_alg );
327355

328-
if( opt.key_usage )
356+
if( opt.key_usage || opt.force_key_usage == 1 )
329357
mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );
330358

331-
if( opt.ns_cert_type )
359+
if( opt.ns_cert_type || opt.force_ns_cert_type == 1 )
332360
mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );
333361

334362
/*

tests/data_files/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,14 @@ server1.req.ku-ct: server1.key
785785
$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< key_usage=digital_signature,non_repudiation,key_encipherment ns_cert_type=ssl_server subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA1
786786
all_final += server1.req.ku-ct
787787

788+
server1.req.key_usage_empty: server1.key
789+
$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA1 force_key_usage=1
790+
all_final += server1.req.key_usage_empty
791+
792+
server1.req.cert_type_empty: server1.key
793+
$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA1 force_ns_cert_type=1
794+
all_final += server1.req.cert_type_empty
795+
788796
# server2*
789797

790798
server2.req.sha256: server2.key

tests/data_files/server1.cert_type.crt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
1111
bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
1212
o2AwXjAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf
1313
BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zARBglghkgBhvhCAQEEBAMC
14-
AEAwDQYJKoZIhvcNAQEFBQADggEBAEQOk5Ejgu/GsxvMo+RknXcta5Qr6MiNo1EM
15-
G5Xrf++aaf4Mi38p5ZxWDxQDyBmutSnuJgzO+Dxe5w/RNojFa4ri4g5Zk8zwfIcQ
16-
8jR6a9DJtxarxDj/UqEzaiBa5MpxsbQqbmou7X7YW9LHDzmCgzbaabyWCuGYxvmh
17-
lDbcISST73G+vJEeExcBHyom/GV9TNcFAGa66YV/FtABg2tiy9znmUeMnZeYkC9S
18-
05m6UstAU6pMdwiTpjZjovsTlAcmC76XmE/GpREhRvtGCKTb2pUi3agqsrapABmF
19-
EGZT9cpwkrl3cxh+jxAMEuhJLdEScDWHVsiNS5y9yxitWC4NqR4=
14+
BkAwDQYJKoZIhvcNAQEFBQADggEBAK1WXZYd6k7/zE2NcszT6rxNaSixPZrDYzRt
15+
Iz5rpH33IHkCdR956/ExCcDMqGNVtKtBdr8kw3+jzyPQhwyHVPNv4C/cgt0C89Pf
16+
qZLQGuEPVp1X4tzEY2Kno9c1tllLVzJdvz1mRhSb9z5CWQKNMT+8MMl3k+0NZ4LT
17+
NEx4gTZxYEsAGEuO/Yij9ctxp4RdSP585FXgiMC00ieMe/aJxlOIgpIhuWdu0KPP
18+
G5guYd4hQ9ZrGVOGdjv2cZbh4DuQOsCwU9in/e1RKFV6eMmyOdvLJ4jkTauwkGJG
19+
lCclZZQwzGawOiMl2OYPUia5bkaEsdE/0QW/lf36lco8CNjpUfY=
2020
-----END CERTIFICATE-----

tests/data_files/server1.cert_type_noauthid.crt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
1010
lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
1111
bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
1212
oz8wPTAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAR
13-
BglghkgBhvhCAQEEBAMCAEAwDQYJKoZIhvcNAQEFBQADggEBAJc3yZUS9X3/lb63
14-
Nlt8rtXC45wbWZUoOK8N55IzEJC7FrttAStq24kq9QV0qiox8m1WLA+6xVaeZaXu
15-
h2z3WlUlyCNaKqHEpuSYu/XQ0td6j3jCMj3VDSZGHnKgliQ9fkkt+waPVCAZldwj
16-
rHsZibl2Dqzb3KttKqD1VyEVOUJ+saXRDJLFdK1M9nwdWMfOg/XE0WbqfVzw9COs
17-
08dJ6KL7SOvXtiOVQLNv7XN/2j+wF6+IoLDdLCDByj5VtK2q2vyVk5tpDJI1S696
18-
dP8Zi7VbBTS9OlVC+Gw3CntDKZA8e215MNG6iBuEM2mgi4i0umo7mN8FoA1zusnE
19-
8mCO55Q=
13+
BglghkgBhvhCAQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADggEBAGl6bYCGKvDCvfSU
14+
PTyaiFPNGXV98AnIG0Hu4EJjs1owBU/Yf8UdFbWJtOymR80SbzmeQ6rEIoY1oXDA
15+
o9Y8yRgW8t25Wmq/0DCu/5P0/L6asstLTxLG4qajClVwqDLEqZNixmq8QorAOtK1
16+
JngFA+A5jzc70Ikl9+Hbx/2SEMrCpo0QLSco7KDK7XpNOHbkRz2AqSm0se4jDMP1
17+
Cwd2UtcpctIZEbECZo6S9WrVMqIhRF1Y5FeauBA2ORvGIHohaYJ9VzYWYXIp7N8d
18+
QXGv+M7ffpZiERcRr8lxtboPnTXKlv1mLCEX7g+KuiJQUm4OGfTCd5VHzWM7O5Id
19+
b+IvZD0=
2020
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)