Skip to content

Commit 679474d

Browse files
committed
programs: improved cert_write serial management
Now it can accept serial both as decimal and hex number (only one format at a time, of course, not simultaneously). Signed-off-by: Valerio Setti <vsetti@baylibre.com>
1 parent a939885 commit 679474d

File tree

2 files changed

+90
-31
lines changed

2 files changed

+90
-31
lines changed

ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt

+9
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,12 @@ New deprecations
88
* mbedtls_x509write_crt_set_serial() is now being deprecated in favor of
99
mbedtls_x509write_crt_set_serial_new(). The goal here is to remove any
1010
direct dependency of X509 on BIGNUM_C.
11+
12+
Changes
13+
* programs/x509/cert_write:
14+
- now it accepts the serial number in 2 different formats: decimal and
15+
hex. They cannot be used simultaneously
16+
- "serial" is used for the decimal format and it's limted in size to
17+
unsigned long long int
18+
- "serial_hex" is used for the hex format; max length here is
19+
MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN*2

programs/x509/cert_write.c

+81-31
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ int main( void )
4343
#include "mbedtls/ctr_drbg.h"
4444
#include "mbedtls/md.h"
4545
#include "mbedtls/error.h"
46+
#include "test/helpers.h"
4647

4748
#include <stdio.h>
4849
#include <stdlib.h>
4950
#include <string.h>
51+
#include <errno.h>
5052

5153
#define SET_OID(x, oid) \
5254
do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char*)oid; } while( 0 )
@@ -75,6 +77,7 @@ int main( void )
7577
#define DFL_NOT_BEFORE "20010101000000"
7678
#define DFL_NOT_AFTER "20301231235959"
7779
#define DFL_SERIAL "1"
80+
#define DFL_SERIAL_HEX "1"
7881
#define DFL_SELFSIGN 0
7982
#define DFL_IS_CA 0
8083
#define DFL_MAX_PATHLEN -1
@@ -110,6 +113,13 @@ int main( void )
110113
" issuer_pwd=%%s default: (empty)\n" \
111114
" output_file=%%s default: cert.crt\n" \
112115
" serial=%%s default: 1\n" \
116+
" In decimal format; it can be used as\n" \
117+
" alternative to serial_hex, but it's\n" \
118+
" limited in max length to\n" \
119+
" unsigned long long int\n" \
120+
" serial_hex=%%s default: 1\n" \
121+
" In hex format; it can be used as\n" \
122+
" alternative to serial\n" \
113123
" not_before=%%s default: 20010101000000\n"\
114124
" not_after=%%s default: 20301231235959\n"\
115125
" is_ca=%%d default: 0 (disabled)\n" \
@@ -159,6 +169,12 @@ int main( void )
159169
" format=pem|der default: pem\n" \
160170
"\n"
161171

172+
typedef enum
173+
{
174+
SERIAL_FRMT_UNSPEC,
175+
SERIAL_FRMT_DEC,
176+
SERIAL_FRMT_HEX
177+
} serial_format_t;
162178

163179
/*
164180
* global options
@@ -176,7 +192,8 @@ struct options
176192
const char *issuer_name; /* issuer name for certificate */
177193
const char *not_before; /* validity period not before */
178194
const char *not_after; /* validity period not after */
179-
const char *serial; /* serial number string */
195+
const char *serial; /* serial number string (decimal) */
196+
const char *serial_hex; /* serial number string (hex) */
180197
int selfsign; /* selfsign the certificate */
181198
int is_ca; /* is a CA certificate */
182199
int max_pathlen; /* maximum CA path length */
@@ -235,39 +252,42 @@ int write_certificate( mbedtls_x509write_cert *crt, const char *output_file,
235252
return( 0 );
236253
}
237254

238-
/*
239-
* Convert the input "in_buff" string to a raw byte array "out_buff". The amount
240-
* of converted data is returned on "written_data".
241-
*/
242-
static int parse_serial( const char* in_buff, size_t in_buff_len,
243-
unsigned char* out_buff, size_t out_buff_len,
244-
size_t *written_data )
255+
int parse_serial_decimal_format( unsigned char *obuf, size_t obufmax,
256+
const char *ibuf, size_t *len )
245257
{
246-
char c;
258+
unsigned long long int dec;
259+
unsigned int remaining_bytes = sizeof( dec );
260+
unsigned char *p = obuf;
247261
unsigned char val;
248-
int i;
262+
char* end_ptr = NULL;
249263

250-
if( out_buff_len < in_buff_len )
251-
return( -1 );
264+
errno = 0;
265+
dec = strtoull( ibuf, &end_ptr, 10 );
266+
267+
if( ( errno != 0 ) || ( end_ptr == ibuf ) )
268+
return -1;
252269

253-
*written_data = 0;
270+
*len = 0;
254271

255-
for( i = 0; i < (int) in_buff_len; i++, (*written_data)++ )
272+
while( remaining_bytes > 0 )
256273
{
257-
c = in_buff[i];
258-
if( c >= 0x30 && c <= 0x39 )
259-
val = c - 0x30;
260-
else if( c >= 0x41 && c <= 0x46 )
261-
val = c - 0x37;
262-
else if( c >= 0x61 && c <= 0x66 )
263-
val = c - 0x57;
264-
else
265-
return( -1 );
274+
if( obufmax < ( *len + 1 ) )
275+
return -1;
276+
277+
val = ( dec >> ( ( remaining_bytes - 1 ) * 8 ) ) & 0xFF;
266278

267-
out_buff[i] = val;
279+
/* Skip leading zeros */
280+
if( ( val ) != 0 )
281+
{
282+
*p = val;
283+
(*len)++;
284+
p++;
285+
}
286+
287+
remaining_bytes--;
268288
}
269289

270-
return( 0 );
290+
return 0;
271291
}
272292

273293
int main( int argc, char *argv[] )
@@ -287,6 +307,7 @@ int main( int argc, char *argv[] )
287307
mbedtls_x509_csr csr;
288308
#endif
289309
mbedtls_x509write_cert crt;
310+
serial_format_t serial_frmt = SERIAL_FRMT_UNSPEC;
290311
unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
291312
size_t serial_len;
292313
mbedtls_asn1_sequence *ext_key_usage;
@@ -307,6 +328,7 @@ int main( int argc, char *argv[] )
307328
#endif
308329
mbedtls_x509_crt_init( &issuer_crt );
309330
memset( buf, 0, sizeof(buf) );
331+
memset( serial, 0, sizeof( serial ) );
310332

311333
if( argc == 0 )
312334
{
@@ -327,6 +349,7 @@ int main( int argc, char *argv[] )
327349
opt.not_before = DFL_NOT_BEFORE;
328350
opt.not_after = DFL_NOT_AFTER;
329351
opt.serial = DFL_SERIAL;
352+
opt.serial_hex = DFL_SERIAL_HEX;
330353
opt.selfsign = DFL_SELFSIGN;
331354
opt.is_ca = DFL_IS_CA;
332355
opt.max_pathlen = DFL_MAX_PATHLEN;
@@ -380,8 +403,24 @@ int main( int argc, char *argv[] )
380403
}
381404
else if( strcmp( p, "serial" ) == 0 )
382405
{
406+
if( serial_frmt != SERIAL_FRMT_UNSPEC )
407+
{
408+
mbedtls_printf( "Invalid attempt to set the serial more than once\n" );
409+
goto usage;
410+
}
411+
serial_frmt = SERIAL_FRMT_DEC;
383412
opt.serial = q;
384413
}
414+
else if( strcmp( p, "serial_hex" ) == 0 )
415+
{
416+
if( serial_frmt != SERIAL_FRMT_UNSPEC )
417+
{
418+
mbedtls_printf( "Invalid attempt to set the serial more than once\n" );
419+
goto usage;
420+
}
421+
serial_frmt = SERIAL_FRMT_HEX;
422+
opt.serial_hex = q;
423+
}
385424
else if( strcmp( p, "authority_identifier" ) == 0 )
386425
{
387426
opt.authority_identifier = atoi( q );
@@ -594,6 +633,23 @@ int main( int argc, char *argv[] )
594633
mbedtls_printf( " . Reading serial number..." );
595634
fflush( stdout );
596635

636+
if( serial_frmt == SERIAL_FRMT_HEX )
637+
{
638+
ret = mbedtls_test_unhexify( serial, sizeof( serial ),
639+
opt.serial_hex, &serial_len );
640+
}
641+
else // SERIAL_FRMT_DEC || SERIAL_FRMT_UNSPEC
642+
{
643+
ret = parse_serial_decimal_format( serial, sizeof( serial ),
644+
opt.serial, &serial_len );
645+
}
646+
647+
if( ret != 0)
648+
{
649+
mbedtls_printf( " failed\n ! Unable to parse serial\n" );
650+
goto exit;
651+
}
652+
597653
mbedtls_printf( " ok\n" );
598654

599655
// Parse issuer certificate if present
@@ -748,12 +804,6 @@ int main( int argc, char *argv[] )
748804
mbedtls_x509write_crt_set_version( &crt, opt.version );
749805
mbedtls_x509write_crt_set_md_alg( &crt, opt.md );
750806

751-
if( parse_serial( opt.serial, strlen( opt.serial ),
752-
serial, sizeof( serial ), &serial_len ) < 0 )
753-
{
754-
mbedtls_printf( " failed\n ! Unable to parse serial\n\n" );
755-
goto exit;
756-
}
757807
ret = mbedtls_x509write_crt_set_serial_new( &crt, serial, serial_len );
758808
if( ret != 0 )
759809
{

0 commit comments

Comments
 (0)