Remove unused function: dns_randfn_() in dns.c.
[tor.git] / src / lib / encoding / pem.c
blob51f37d0840175259d92718ad4e854472d2fbf6ec
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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file pem.c
10 * \brief Implement a trivial version of PEM encoding, for use with NSS.
12 * We deliberately do not support any encryption here.
13 **/
15 #include "orconfig.h"
17 #include "lib/encoding/pem.h"
19 #include "lib/ctime/di_ops.h"
20 #include "lib/encoding/binascii.h"
21 #include "lib/log/util_bug.h"
22 #include "lib/malloc/malloc.h"
23 #include "lib/string/printf.h"
24 #include "lib/string/util_string.h"
26 #include <string.h>
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.
32 size_t
33 pem_encoded_size(size_t src_len, const char *objtype)
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;
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.
48 int
49 pem_encode(char *dest, size_t destlen, const uint8_t *src, size_t srclen,
50 const char *objtype)
52 if (tor_snprintf(dest, destlen, "-----BEGIN %s-----\n", objtype) < 0)
53 return -1;
55 size_t offset = strlen(dest);
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;
65 if (tor_snprintf(dest + offset, destlen - offset,
66 "-----END %s-----\n", objtype) < 0)
67 return -1;
69 tor_assert(strlen(dest) + 1 <= pem_encoded_size(srclen, objtype));
70 return 0;
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.
79 int
80 pem_decode(uint8_t *dest, size_t destlen, const char *src, size_t srclen,
81 const char *objtype)
83 const char *eos = src + srclen;
85 src = eat_whitespace_eos(src, eos);
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;
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;
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;
109 /* Should we actually allow extra stuff at the end? */
111 return base64_decode((char*)dest, destlen, src, end_of_base64-src);