#include "orconfig.h"
#include "lib/encoding/pem.h"
#include "lib/ctime/di_ops.h"
#include "lib/encoding/binascii.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
#include <string.h>
size_t
pem_encoded_size(size_t src_len, const char *objtype)
{
return
strlen("-----BEGIN -----\n") +
strlen("-----END -----\n") +
strlen(objtype) * 2 +
base64_encode_size(src_len, BASE64_ENCODE_MULTILINE)
+ 1;
}
int
pem_encode(char *dest, size_t destlen, const uint8_t *src, size_t srclen,
const char *objtype)
{
if (tor_snprintf(dest, destlen, "-----BEGIN %s-----\n", objtype) < 0)
return -1;
size_t offset = strlen(dest);
int n = base64_encode(dest + offset, destlen - offset,
(const char *)src, srclen, BASE64_ENCODE_MULTILINE);
if (n < 0)
return -1;
offset += n;
if (BUG(offset > destlen))
return -1;
if (tor_snprintf(dest + offset, destlen - offset,
"-----END %s-----\n", objtype) < 0)
return -1;
tor_assert(strlen(dest) + 1 <= pem_encoded_size(srclen, objtype));
return 0;
}
int
pem_decode(uint8_t *dest, size_t destlen, const char *src, size_t srclen,
const char *objtype)
{
const char *eos = src + srclen;
src = eat_whitespace_eos(src, eos);
char *tag = NULL;
tor_asprintf(&tag, "-----BEGIN %s-----", objtype);
if ((size_t)(eos-src) < strlen(tag) || fast_memneq(src, tag, strlen(tag))) {
tor_free(tag);
return -1;
}
src += strlen(tag);
tor_free(tag);
src = eat_whitespace_eos_no_nl(src, eos);
if (src == eos || *src != '\n') {
return -1;
}
tor_asprintf(&tag, "\n-----END %s-----", objtype);
const char *end_of_base64 = tor_memstr(src, eos-src, tag);
tor_free(tag);
if (end_of_base64 == NULL)
return -1;
return base64_decode((char*)dest, destlen, src, end_of_base64-src);
}