/* encodes data and puts the result into result (locally allocated) * The result_size (including the null terminator) is the return value. */ int _gnutls_fbase64_encode (const char *msg, const uint8_t * data, size_t data_size, gnutls_datum_t * result) { int tmp; unsigned int i; char tmpres[66]; uint8_t *ptr; char top[80]; char bottom[80]; size_t size, max, bytes; int pos, top_len, bottom_len; if (msg == NULL || strlen(msg) > 50) { gnutls_assert (); return GNUTLS_E_BASE64_ENCODING_ERROR; } _gnutls_str_cpy (top, sizeof(top), "-----BEGIN "); _gnutls_str_cat (top, sizeof(top), msg); _gnutls_str_cat (top, sizeof(top), "-----\n"); _gnutls_str_cpy (bottom, sizeof(bottom), "-----END "); _gnutls_str_cat (bottom, sizeof(bottom), msg); _gnutls_str_cat (bottom, sizeof(bottom), "-----\n"); top_len = strlen (top); bottom_len = strlen (bottom); max = B64FSIZE (top_len+bottom_len, data_size); result->data = gnutls_malloc (max + 1); if (result->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } bytes = pos = 0; INCR (bytes, top_len, max); pos = top_len; memcpy (result->data, top, top_len); for (i = 0; i < data_size; i += 48) { if (data_size - i < 48) tmp = data_size - i; else tmp = 48; base64_encode ((void*)&data[i], tmp, tmpres, sizeof(tmpres)); size = strlen(tmpres); INCR (bytes, size+1, max); ptr = &result->data[pos]; memcpy(ptr, tmpres, size); ptr += size; *ptr++ = '\n'; pos += size + 1; } INCR (bytes, bottom_len, max); memcpy (&result->data[bytes - bottom_len], bottom, bottom_len); result->data[bytes] = 0; result->size = bytes; return max + 1; }
/* A generic export function. Will export the given ASN.1 encoded data * to PEM or DER raw data. */ int _gnutls_x509_export_int (ASN1_TYPE asn1_data, gnutls_x509_crt_fmt_t format, char *pem_header, int tmp_buf_size, unsigned char *output_data, size_t * output_data_size) { int result, len; if (tmp_buf_size == 0) tmp_buf_size = 16 * 1024; if (format == GNUTLS_X509_FMT_DER) { if (output_data == NULL) *output_data_size = 0; len = *output_data_size; if ((result = asn1_der_coding (asn1_data, "", output_data, &len, NULL)) != ASN1_SUCCESS) { *output_data_size = len; if (result == ASN1_MEM_ERROR) { return GNUTLS_E_SHORT_MEMORY_BUFFER; } gnutls_assert (); return _gnutls_asn2err (result); } *output_data_size = len; } else { /* PEM */ opaque *tmp; opaque *out; len = tmp_buf_size; tmp = gnutls_alloca (len); if (tmp == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if ((result = asn1_der_coding (asn1_data, "", tmp, &len, NULL)) != ASN1_SUCCESS) { gnutls_assert (); if (result == ASN1_MEM_ERROR) { *output_data_size = B64FSIZE (strlen (pem_header), len) + 1; } gnutls_afree (tmp); return _gnutls_asn2err (result); } result = _gnutls_fbase64_encode (pem_header, tmp, len, &out); gnutls_afree (tmp); if (result < 0) { gnutls_assert (); return result; } if (result == 0) { /* oooops */ gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if ((unsigned) result > *output_data_size) { gnutls_assert (); gnutls_free (out); *output_data_size = result; return GNUTLS_E_SHORT_MEMORY_BUFFER; } *output_data_size = result; if (output_data) { memcpy (output_data, out, result); /* do not include the null character into output size. */ *output_data_size = result - 1; } gnutls_free (out); } return 0; }