Tor 0.4.9.0-alpha-dev
pem.c
Go to the documentation of this file.
1/* Copyright (c) 2001, Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * \file pem.c
9 *
10 * \brief Implement a trivial version of PEM encoding, for use with NSS.
11 *
12 * We deliberately do not support any encryption here.
13 **/
14
15#include "orconfig.h"
16
17#include "lib/encoding/pem.h"
18
19#include "lib/ctime/di_ops.h"
21#include "lib/log/util_bug.h"
22#include "lib/malloc/malloc.h"
23#include "lib/string/printf.h"
25
26#include <string.h>
27
28/**
29 * Return the length of a <b>src_len</b>-byte object when tagged with
30 * <b>objtype</b> and PEM-encoded. Includes terminating NUL.
31 */
32size_t
33pem_encoded_size(size_t src_len, const char *objtype)
34{
35 return
36 strlen("-----BEGIN -----\n") +
37 strlen("-----END -----\n") +
38 strlen(objtype) * 2 +
39 base64_encode_size(src_len, BASE64_ENCODE_MULTILINE)
40 + 1;
41}
42
43/**
44 * PEM-encode the <b>srclen</b>-byte object at <b>src</b> into the
45 * <b>destlen</b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>.
46 * Return 0 on success and -1 on failure.
47 */
48int
49pem_encode(char *dest, size_t destlen, const uint8_t *src, size_t srclen,
50 const char *objtype)
51{
52 if (tor_snprintf(dest, destlen, "-----BEGIN %s-----\n", objtype) < 0)
53 return -1;
54
55 size_t offset = strlen(dest);
56
57 int n = base64_encode(dest + offset, destlen - offset,
58 (const char *)src, srclen, BASE64_ENCODE_MULTILINE);
59 if (n < 0)
60 return -1;
61 offset += n;
62 if (BUG(offset > destlen))
63 return -1;
64
65 if (tor_snprintf(dest + offset, destlen - offset,
66 "-----END %s-----\n", objtype) < 0)
67 return -1;
68
69 tor_assert(strlen(dest) + 1 <= pem_encoded_size(srclen, objtype));
70 return 0;
71}
72
73/**
74 * Given a PEM-encoded block of size <b>srclen</b> in <b>src</b>, if it has
75 * object type <b>objtype</b>, decode it into the <b>destlen</b>-byte buffer
76 * at <b>dest</b>. Return the number of characters decoded on success, or -1
77 * on failure.
78 */
79int
80pem_decode(uint8_t *dest, size_t destlen, const char *src, size_t srclen,
81 const char *objtype)
82{
83 const char *eos = src + srclen;
84
85 src = eat_whitespace_eos(src, eos);
86
87 char *tag = NULL;
88 tor_asprintf(&tag, "-----BEGIN %s-----", objtype);
89 if ((size_t)(eos-src) < strlen(tag) || fast_memneq(src, tag, strlen(tag))) {
90 tor_free(tag);
91 return -1;
92 }
93 src += strlen(tag);
94 tor_free(tag);
95 /* At this point we insist on spaces (including CR), then an LF. */
96 src = eat_whitespace_eos_no_nl(src, eos);
97 if (src == eos || *src != '\n') {
98 /* Extra junk at end of line: this isn't valid. */
99 return -1;
100 }
101
102 // NOTE lack of trailing \n. We do not enforce its presence.
103 tor_asprintf(&tag, "\n-----END %s-----", objtype);
104 const char *end_of_base64 = tor_memstr(src, eos-src, tag);
105 tor_free(tag);
106 if (end_of_base64 == NULL)
107 return -1;
108
109 /* Should we actually allow extra stuff at the end? */
110
111 return base64_decode((char*)dest, destlen, src, end_of_base64-src);
112}
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, int flags)
Definition: binascii.c:215
size_t base64_encode_size(size_t srclen, int flags)
Definition: binascii.c:166
Header for binascii.c.
Headers for di_ops.c.
#define fast_memneq(a, b, c)
Definition: di_ops.h:42
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
int pem_decode(uint8_t *dest, size_t destlen, const char *src, size_t srclen, const char *objtype)
Definition: pem.c:80
size_t pem_encoded_size(size_t src_len, const char *objtype)
Definition: pem.c:33
int pem_encode(char *dest, size_t destlen, const uint8_t *src, size_t srclen, const char *objtype)
Definition: pem.c:49
Header for pem.c.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
Header for printf.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103
const char * eat_whitespace_eos(const char *s, const char *eos)
Definition: util_string.c:306
const char * eat_whitespace_eos_no_nl(const char *s, const char *eos)
Definition: util_string.c:344
Header for util_string.c.