libretro-dolphin/Externals/mbedtls/library/asn1write.c
Lioncash 3053fea160 Externals: Update mbedtls to 2.16.1
On a few of our buildbot instances, we get warnings about the usage of
deprecated functions. We should correct these, especially if we're
delegating to system versions of the libraries if they're available.
However, in order to do that, we need to update our library variant from
2.1.1 so that the non-deprecated alternatives are actually available.
2019-06-07 21:56:28 -04:00

422 lines
11 KiB
C

/*
* ASN.1 buffer writing functionality
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ASN1_WRITE_C)
#include "mbedtls/asn1write.h"
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
{
if( len < 0x80 )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (unsigned char) len;
return( 1 );
}
if( len <= 0xFF )
{
if( *p - start < 2 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (unsigned char) len;
*--(*p) = 0x81;
return( 2 );
}
if( len <= 0xFFFF )
{
if( *p - start < 3 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = ( len ) & 0xFF;
*--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = 0x82;
return( 3 );
}
if( len <= 0xFFFFFF )
{
if( *p - start < 4 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = ( len ) & 0xFF;
*--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = ( len >> 16 ) & 0xFF;
*--(*p) = 0x83;
return( 4 );
}
#if SIZE_MAX > 0xFFFFFFFF
if( len <= 0xFFFFFFFF )
#endif
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = ( len ) & 0xFF;
*--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = ( len >> 16 ) & 0xFF;
*--(*p) = ( len >> 24 ) & 0xFF;
*--(*p) = 0x84;
return( 5 );
}
#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = tag;
return( 1 );
}
int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size )
{
size_t len = 0;
if( *p < start || (size_t)( *p - start ) < size )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len = size;
(*p) -= len;
memcpy( *p, buf, len );
return( (int) len );
}
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
{
int ret;
size_t len = 0;
// Write the MPI
//
len = mbedtls_mpi_size( X );
if( *p < start || (size_t)( *p - start ) < len )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
(*p) -= len;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
// DER format assumes 2s complement for numbers, so the leftmost bit
// should be 0 for positive numbers and 1 for negative numbers.
//
if( X->s ==1 && **p & 0x80 )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00;
len += 1;
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
ret = (int) len;
cleanup:
return( ret );
}
#endif /* MBEDTLS_BIGNUM_C */
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
{
int ret;
size_t len = 0;
// Write NULL
//
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
return( (int) len );
}
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len )
{
int ret;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) oid, oid_len ) );
MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
return( (int) len );
}
int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len,
size_t par_len )
{
int ret;
size_t len = 0;
if( par_len == 0 )
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
else
len += par_len;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
return( (int) len );
}
int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
{
int ret;
size_t len = 0;
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (boolean) ? 255 : 0;
len++;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
return( (int) len );
}
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
{
int ret;
size_t len = 0;
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len += 1;
*--(*p) = val;
if( val > 0 && **p & 0x80 )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00;
len += 1;
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
return( (int) len );
}
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len )
{
int ret;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) text, text_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
{
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
}
int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
{
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
}
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
{
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
}
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits )
{
int ret;
size_t len = 0;
size_t unused_bits, byte_len;
byte_len = ( bits + 7 ) / 8;
unused_bits = ( byte_len * 8 ) - bits;
if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len = byte_len + 1;
/* Write the bitstring. Ensure the unused bits are zeroed */
if( byte_len > 0 )
{
byte_len--;
*--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
( *p ) -= byte_len;
memcpy( *p, buf, byte_len );
}
/* Write unused bits */
*--( *p ) = (unsigned char)unused_bits;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
return( (int) len );
}
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size )
{
int ret;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
return( (int) len );
}
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
* which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
static mbedtls_asn1_named_data *asn1_find_named_data(
mbedtls_asn1_named_data *list,
const char *oid, size_t len )
{
while( list != NULL )
{
if( list->oid.len == len &&
memcmp( list->oid.p, oid, len ) == 0 )
{
break;
}
list = list->next;
}
return( list );
}
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
mbedtls_asn1_named_data **head,
const char *oid, size_t oid_len,
const unsigned char *val,
size_t val_len )
{
mbedtls_asn1_named_data *cur;
if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
{
// Add new entry if not present yet based on OID
//
cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
sizeof(mbedtls_asn1_named_data) );
if( cur == NULL )
return( NULL );
cur->oid.len = oid_len;
cur->oid.p = mbedtls_calloc( 1, oid_len );
if( cur->oid.p == NULL )
{
mbedtls_free( cur );
return( NULL );
}
memcpy( cur->oid.p, oid, oid_len );
cur->val.len = val_len;
cur->val.p = mbedtls_calloc( 1, val_len );
if( cur->val.p == NULL )
{
mbedtls_free( cur->oid.p );
mbedtls_free( cur );
return( NULL );
}
cur->next = *head;
*head = cur;
}
else if( cur->val.len < val_len )
{
/*
* Enlarge existing value buffer if needed
* Preserve old data until the allocation succeeded, to leave list in
* a consistent state in case allocation fails.
*/
void *p = mbedtls_calloc( 1, val_len );
if( p == NULL )
return( NULL );
mbedtls_free( cur->val.p );
cur->val.p = p;
cur->val.len = val_len;
}
if( val != NULL )
memcpy( cur->val.p, val, val_len );
return( cur );
}
#endif /* MBEDTLS_ASN1_WRITE_C */