diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-07-31 11:21:34 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-07-31 11:21:34 -0400 |
commit | 347fe449fe818f97e0f3ba29dd0a08ff6d39081e (patch) | |
tree | 9397c155e38a7e7084b91c55f1c57f576aa42b25 /src/common/crypto_format.c | |
parent | 8c83e8cec0e8d4c29577ae7c7b27637e5b91c99e (diff) | |
download | tor-347fe449fe818f97e0f3ba29dd0a08ff6d39081e.tar.gz tor-347fe449fe818f97e0f3ba29dd0a08ff6d39081e.zip |
Move formatting functions around.
The base64 and base32 functions used to be in crypto.c;
crypto_format.h had no header; some general-purpose functions were in
crypto_curve25519.c.
This patch makes a {crypto,util}_format.[ch], and puts more functions
there. Small modules are beautiful!
Diffstat (limited to 'src/common/crypto_format.c')
-rw-r--r-- | src/common/crypto_format.c | 162 |
1 files changed, 161 insertions, 1 deletions
diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c index e825132cb9..d4ecd5b192 100644 --- a/src/common/crypto_format.c +++ b/src/common/crypto_format.c @@ -1,4 +1,7 @@ -/* Copyright (c) 2012-2015, The Tor Project, Inc. */ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2015, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Formatting and parsing code for crypto-related data structures. */ @@ -7,12 +10,115 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif +#include "container.h" #include "crypto.h" #include "crypto_curve25519.h" #include "crypto_ed25519.h" +#include "crypto_format.h" #include "util.h" +#include "util_format.h" #include "torlog.h" +/** Write the <b>datalen</b> bytes from <b>data</b> to the file named + * <b>fname</b> in the tagged-data format. This format contains a + * 32-byte header, followed by the data itself. The header is the + * NUL-padded string "== <b>typestring</b>: <b>tag</b> ==". The length + * of <b>typestring</b> and <b>tag</b> must therefore be no more than + * 24. + **/ +int +crypto_write_tagged_contents_to_file(const char *fname, + const char *typestring, + const char *tag, + const uint8_t *data, + size_t datalen) +{ + char header[32]; + smartlist_t *chunks = smartlist_new(); + sized_chunk_t ch0, ch1; + int r = -1; + + memset(header, 0, sizeof(header)); + if (tor_snprintf(header, sizeof(header), + "== %s: %s ==", typestring, tag) < 0) + goto end; + ch0.bytes = header; + ch0.len = 32; + ch1.bytes = (const char*) data; + ch1.len = datalen; + smartlist_add(chunks, &ch0); + smartlist_add(chunks, &ch1); + + r = write_chunks_to_file(fname, chunks, 1, 0); + + end: + smartlist_free(chunks); + return r; +} + +/** Read a tagged-data file from <b>fname</b> into the + * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the + * typestring matches <b>typestring</b>; store the tag into a newly allocated + * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of + * data on success. Preserves the errno from reading the file. */ +ssize_t +crypto_read_tagged_contents_from_file(const char *fname, + const char *typestring, + char **tag_out, + uint8_t *data_out, + ssize_t data_out_len) +{ + char prefix[33]; + char *content = NULL; + struct stat st; + ssize_t r = -1; + size_t st_size = 0; + int saved_errno = 0; + + *tag_out = NULL; + st.st_size = 0; + content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st); + if (! content) { + saved_errno = errno; + goto end; + } + if (st.st_size < 32 || st.st_size > 32 + data_out_len) { + saved_errno = EINVAL; + goto end; + } + st_size = (size_t)st.st_size; + + memcpy(prefix, content, 32); + prefix[32] = 0; + /* Check type, extract tag. */ + if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") || + ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) { + saved_errno = EINVAL; + goto end; + } + + if (strcmpstart(prefix+3, typestring) || + 3+strlen(typestring) >= 32 || + strcmpstart(prefix+3+strlen(typestring), ": ")) { + saved_errno = EINVAL; + goto end; + } + + *tag_out = tor_strndup(prefix+5+strlen(typestring), + strlen(prefix)-8-strlen(typestring)); + + memcpy(data_out, content+32, st_size-32); + r = st_size - 32; + + end: + if (content) + memwipe(content, 0, st_size); + tor_free(content); + if (saved_errno) + errno = saved_errno; + return r; +} + int curve25519_public_to_base64(char *output, const curve25519_public_key_t *pkey) @@ -104,3 +210,57 @@ ed25519_signature_from_base64(ed25519_signature_t *sig, return 0; } +/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing = + * characters, and store the nul-terminated result in the first + * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */ +/* XXXX unify with crypto_format.c code */ +int +digest_to_base64(char *d64, const char *digest) +{ + char buf[256]; + base64_encode(buf, sizeof(buf), digest, DIGEST_LEN, 0); + buf[BASE64_DIGEST_LEN] = '\0'; + memcpy(d64, buf, BASE64_DIGEST_LEN+1); + return 0; +} + +/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without + * trailing newline or = characters), decode it and store the result in the + * first DIGEST_LEN bytes at <b>digest</b>. */ +/* XXXX unify with crypto_format.c code */ +int +digest_from_base64(char *digest, const char *d64) +{ + if (base64_decode(digest, DIGEST_LEN, d64, strlen(d64)) == DIGEST_LEN) + return 0; + else + return -1; +} + +/** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the + * trailing = characters, and store the nul-terminated result in the first + * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */ + /* XXXX unify with crypto_format.c code */ +int +digest256_to_base64(char *d64, const char *digest) +{ + char buf[256]; + base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN, 0); + buf[BASE64_DIGEST256_LEN] = '\0'; + memcpy(d64, buf, BASE64_DIGEST256_LEN+1); + return 0; +} + +/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without + * trailing newline or = characters), decode it and store the result in the + * first DIGEST256_LEN bytes at <b>digest</b>. */ +/* XXXX unify with crypto_format.c code */ +int +digest256_from_base64(char *digest, const char *d64) +{ + if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN) + return 0; + else + return -1; +} + |