Tor  0.4.7.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"
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"
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  */
32 size_t
33 pem_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  */
48 int
49 pem_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  */
79 int
80 pem_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:52
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:102
const char * eat_whitespace_eos_no_nl(const char *s, const char *eos)
Definition: util_string.c:342
const char * eat_whitespace_eos(const char *s, const char *eos)
Definition: util_string.c:304
Header for util_string.c.