/* Copyright (C) 2019, Texas A&M University.
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
#include "pal_crypto.h"
#include "pal_error.h"
#include "mbedtls/base64.h"
#include "mbedtls/asn1.h"
/*
* Encoding a byte string in Base64 format. If "dst" is NULL, this function returns the
* expected length after encoding.
*
* @src: The raw data for encoding.
* @slen: The length of data
* @dst: The buffer for storing the encoded data.
* @dlen: Returns the length after encoding.
*/
int lib_Base64Encode(const uint8_t* src, size_t slen, char* dst, size_t* dlen) {
int ret = mbedtls_base64_encode((unsigned char*)dst, *dlen, dlen,
(const unsigned char*)src, slen);
if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
return !dst ? 0 : -PAL_ERROR_OVERFLOW;
} else if (ret != 0) {
return -PAL_ERROR_INVAL;
} else {
return 0;
}
}
/*
* Decoding a byte string in Base64 format. If "dst" is NULL, this function returns the
* expected length after decoding.
*
* @src: The Base64 string for decoding
* @slen: The length of data
* @dst: The buffer for storing the decoded data.
* @dlen: Returns the length after decoding.
*/
int lib_Base64Decode(const char* src, size_t slen, uint8_t* dst, size_t* dlen) {
int ret = mbedtls_base64_decode((unsigned char*)dst, *dlen, dlen,
(const unsigned char*)src, slen);
if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
return !dst ? 0 : -PAL_ERROR_OVERFLOW;
} else if (ret != 0) {
return -PAL_ERROR_INVAL;
} else {
return 0;
}
}
/*
* Retrieve the next serialized object in the ASN1 format.
*
* @ptr: Pass in the pointer for reading the ASN1 data. On success, will be updated
* to the beginning of the next serialized object.
* @end: The end of ASN1 data.
* @tag: Returns the tag of the object.
* @is_construct: Returns a boolean to represent whether the object is a construct object.
* @buf: Returns the data field of the object.
* @len: Returns the length of the data field.
*/
int lib_ASN1GetSerial(uint8_t** ptr, const uint8_t* end, enum asn1_tag* tag, bool* is_construct,
uint8_t** buf, size_t* len) {
if (end - (*ptr) < 1)
return -PAL_ERROR_ENDOFSTREAM;
uint8_t t = *(*ptr)++;
size_t l;
int ret = mbedtls_asn1_get_len((unsigned char**)ptr, (const unsigned char*)end, &l);
if (ret != 0)
return -PAL_ERROR_INVAL;
*tag = t & ~(MBEDTLS_ASN1_CONSTRUCTED|MBEDTLS_ASN1_CONTEXT_SPECIFIC);
*is_construct = t & MBEDTLS_ASN1_CONSTRUCTED;
*buf = *ptr;
*len = l;
*ptr += l;
return 0;
}
/*
* Retrieve the next ASN1 object which must be a large number (MBEDTLS_ASN1_INTEGER).
* Returns -PAL_ERROR_INVAL if the object is not a large number.
*
* @ptr: Pass in the pointer for reading the ASN1 data. On sucess, will be updated
* to the beginning of the next serialized object.
* @end: The end of ASN1 data.
* @len: Returns the length (number of bytes) of the large number.
*/
int lib_ASN1GetLargeNumberLength(uint8_t** ptr, const uint8_t* end, size_t* len) {
int ret = mbedtls_asn1_get_tag(ptr, end, len, MBEDTLS_ASN1_INTEGER);
if (ret < 0)
return -PAL_ERROR_INVAL;
return 0;
}
/*
* Retrieve the next ASN1 object which must be a bitstring. Returns -PAL_ERROR_INVAL if the
* object is not a bitstring.
*
* @ptr: Pass in the pointer for reading the ASN1 data. On sucess, will be updated
* to the beginning of the next serialized object.
* @end: The end of ASN1 data.
* @str: Returns the pointer to the bitstring.
* @len: Returns the length of the bitstring.
*/
int lib_ASN1GetBitstring(uint8_t** ptr, const uint8_t* end, uint8_t** str, size_t* len) {
mbedtls_asn1_bitstring bs;
int ret = mbedtls_asn1_get_bitstring((unsigned char**)ptr, (const unsigned char*)end, &bs);
if (ret < 0)
return -PAL_ERROR_INVAL;
*str = (uint8_t*)bs.p;
*len = bs.len;
return 0;
}