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 */
10 * \brief Implement a trivial version of PEM encoding, for use with NSS.
12 * We deliberately do not support any encryption here.
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"
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.
33 pem_encoded_size(size_t src_len
, const char *objtype
)
36 strlen("-----BEGIN -----\n") +
37 strlen("-----END -----\n") +
39 base64_encode_size(src_len
, BASE64_ENCODE_MULTILINE
)
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.
49 pem_encode(char *dest
, size_t destlen
, const uint8_t *src
, size_t srclen
,
52 if (tor_snprintf(dest
, destlen
, "-----BEGIN %s-----\n", objtype
) < 0)
55 size_t offset
= strlen(dest
);
57 int n
= base64_encode(dest
+ offset
, destlen
- offset
,
58 (const char *)src
, srclen
, BASE64_ENCODE_MULTILINE
);
62 if (BUG(offset
> destlen
))
65 if (tor_snprintf(dest
+ offset
, destlen
- offset
,
66 "-----END %s-----\n", objtype
) < 0)
69 tor_assert(strlen(dest
) + 1 <= pem_encoded_size(srclen
, objtype
));
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
80 pem_decode(uint8_t *dest
, size_t destlen
, const char *src
, size_t srclen
,
83 const char *eos
= src
+ srclen
;
85 src
= eat_whitespace_eos(src
, eos
);
88 tor_asprintf(&tag
, "-----BEGIN %s-----", objtype
);
89 if ((size_t)(eos
-src
) < strlen(tag
) || fast_memneq(src
, tag
, strlen(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. */
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
);
106 if (end_of_base64
== NULL
)
109 /* Should we actually allow extra stuff at the end? */
111 return base64_decode((char*)dest
, destlen
, src
, end_of_base64
-src
);