Import AES-OCB3 implementation and driver code

This commit is contained in:
Keith Winstein
2011-08-04 04:07:36 -04:00
parent b84599f263
commit 215c75c6ea
10 changed files with 2506 additions and 4 deletions
+10 -4
View File
@@ -1,11 +1,11 @@
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o
repos = templates.rpo
executables = parse termemu ntester
executables = parse termemu ntester encrypt decrypt
CXX = g++
CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE
LIBS = -lutil
LIBS = -lutil -lssl
all: $(executables)
@@ -18,6 +18,12 @@ termemu: termemu.o $(objects) parse # serialize link steps because of -frepo
ntester: ntester.o $(objects) termemu # serialize link steps because of -frepo
$(CXX) $(CXXFLAGS) -o $@ ntester.o $(objects) $(LIBS)
encrypt: encrypt.o $(objects) ntester # serialize link steps because of -frepo
$(CXX) $(CXXFLAGS) -o $@ encrypt.o $(objects) $(LIBS)
decrypt: decrypt.o $(objects) encrypt # serialize link steps because of -frepo
$(CXX) $(CXXFLAGS) -o $@ decrypt.o $(objects) $(LIBS)
templates.o: templates.cpp
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
+182
View File
@@ -0,0 +1,182 @@
/* ---------------------------------------------------------------------------
*
* AEAD API 0.12 - 13 July 2011
*
* This file gives an interface appropriate for many authenticated
* encryption with associated data (AEAD) implementations. It does not try
* to accommodate all possible options or limitations that an implementation
* might have -- you should consult the documentation of your chosen
* implementation to find things like RFC 5116 constants, alignment
* requirements, whether the incremental interface is supported, etc.
*
* This file is in the public domain. It is provided "as is", without
* warranty of any kind. Use at your own risk.
*
* Comments are welcome: Ted Krovetz <ted@krovetz>.
*
* ------------------------------------------------------------------------ */
#ifndef _AE_H_
#define _AE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------------------------------------------------
*
* Constants
*
* ----------------------------------------------------------------------- */
/* Return status codes: Negative return values indicate an error occurred.
* For full explanations of error values, consult the implementation's
* documentation. */
#define AE_SUCCESS ( 0) /* Indicates successful completion of call */
#define AE_INVALID (-1) /* Indicates bad tag during decryption */
#define AE_NOT_SUPPORTED (-2) /* Indicates unsupported option requested */
/* Flags: When data can be processed "incrementally", these flags are used
* to indicate whether the submitted data is the last or not. */
#define AE_FINALIZE (1) /* This is the last of data */
#define AE_PENDING (0) /* More data of is coming */
/* --------------------------------------------------------------------------
*
* AEAD opaque structure definition
*
* ----------------------------------------------------------------------- */
typedef struct _ae_ctx ae_ctx;
/* --------------------------------------------------------------------------
*
* Data Structure Routines
*
* ----------------------------------------------------------------------- */
ae_ctx* ae_allocate (void *misc); /* Allocate ae_ctx, set optional ptr */
void ae_free (ae_ctx *ctx); /* Deallocate ae_ctx struct */
int ae_clear (ae_ctx *ctx); /* Undo initialization */
int ae_ctx_sizeof(void); /* Return sizeof(ae_ctx) */
/* ae_allocate() allocates an ae_ctx structure, but does not initialize it.
* ae_free() deallocates an ae_ctx structure, but does not zeroize it.
* ae_clear() zeroes sensitive values associated with an ae_ctx structure
* and deallocates any auxiliary structures allocated during ae_init().
* ae_ctx_sizeof() returns sizeof(ae_ctx), to aid in any static allocations.
*/
/* --------------------------------------------------------------------------
*
* AEAD Routines
*
* ----------------------------------------------------------------------- */
int ae_init(ae_ctx *ctx,
const void *key,
int key_len,
int nonce_len,
int tag_len);
/* --------------------------------------------------------------------------
*
* Initialize an ae_ctx context structure.
*
* Parameters:
* ctx - Pointer to an ae_ctx structure to be initialized
* key - Pointer to user-supplied key
* key_len - Length of key supplied, in bytes
* nonce_len - Length of nonces to be used for this key, in bytes
* tag_len - Length of tags to be produced for this key, in bytes
*
* Returns:
* AE_SUCCESS - Success. Ctx ready for use.
* AE_NOT_SUPPORTED - An unsupported length was supplied. Ctx is untouched.
* Otherwise - Error. Check implementation documentation for codes.
*
* ----------------------------------------------------------------------- */
int ae_encrypt(ae_ctx *ctx,
const void *nonce,
const void *pt,
int pt_len,
const void *ad,
int ad_len,
void *ct,
void *tag,
int final);
/* --------------------------------------------------------------------------
*
* Encrypt plaintext; provide for authentication of ciphertext/associated data.
*
* Parameters:
* ctx - Pointer to an ae_ctx structure initialized by ae_init.
* nonce - Pointer to a nonce_len (defined in ae_init) byte nonce.
* pt - Pointer to plaintext bytes to be encrypted.
* pt_len - number of bytes pointed to by pt.
* ad - Pointer to associated data.
* ad_len - number of bytes pointed to by ad.
* ct - Pointer to buffer to receive ciphertext encryption.
* tag - Pointer to receive authentication tag; or NULL
* if tag is to be bundled into the ciphertext.
* final - Non-zero if this call completes the plaintext being encrypted.
*
* If nonce!=NULL then a message is being initiated. If final!=0
* then a message is being finalized. If final==0 or nonce==NULL
* then the incremental interface is being used. If nonce!=NULL and
* ad_len<0, then use same ad as last message.
*
* Returns:
* non-negative - Number of bytes written to ct.
* AE_NOT_SUPPORTED - Usage mode unsupported (eg, incremental and/or sticky).
* Otherwise - Error. Check implementation documentation for codes.
*
* ----------------------------------------------------------------------- */
int ae_decrypt(ae_ctx *ctx,
const void *nonce,
const void *ct,
int ct_len,
const void *ad,
int ad_len,
void *pt,
const void *tag,
int final);
/* --------------------------------------------------------------------------
*
* Decrypt ciphertext; provide authenticity of plaintext and associated data.
*
* Parameters:
* ctx - Pointer to an ae_ctx structure initialized by ae_init.
* nonce - Pointer to a nonce_len (defined in ae_init) byte nonce.
* ct - Pointer to ciphertext bytes to be decrypted.
* ct_len - number of bytes pointed to by ct.
* ad - Pointer to associated data.
* ad_len - number of bytes pointed to by ad.
* pt - Pointer to buffer to receive plaintext decryption.
* tag - Pointer to tag_len (defined in ae_init) bytes; or NULL
* if tag is bundled into the ciphertext. Non-NULL tag is only
* read when final is non-zero.
* final - Non-zero if this call completes the ciphertext being decrypted.
*
* If nonce!=NULL then "ct" points to the start of a ciphertext. If final!=0
* then "in" points to the final piece of ciphertext. If final==0 or nonce==
* NULL then the incremental interface is being used. If nonce!=NULL and
* ad_len<0, then use same ad as last message.
*
* Returns:
* non-negative - Number of bytes written to pt.
* AE_INVALID - Authentication failure.
* AE_NOT_SUPPORTED - Usage mode unsupported (eg, incremental and/or sticky).
* Otherwise - Error. Check implementation documentation for codes.
*
* NOTE !!! NOTE !!! -- The ciphertext should be assumed possibly inauthentic
* until it has been completely written and it is
* verified that this routine did not return AE_INVALID.
*
* ----------------------------------------------------------------------- */
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
#endif /* _AE_H_ */
+577
View File
@@ -0,0 +1,577 @@
/* Taken from GNU coreutils */
/* base64.c -- Encode binary data using printable characters.
Copyright (C) 1999-2001, 2004-2006, 2009-2011 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
*
* See also RFC 3548 <http://www.ietf.org/rfc/rfc3548.txt>.
*
* Be careful with error checking. Here is how you would typically
* use these functions:
*
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
* if (!ok)
* FAIL: input was not valid base64
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN
*
* size_t outlen = base64_encode_alloc (in, inlen, &out);
* if (out == NULL && outlen == 0 && inlen != 0)
* FAIL: input too long
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN.
*
*/
// #include <config.h>
/* Get prototype. */
#include "base64.h"
/* Get malloc. */
#include <stdlib.h>
/* Get UCHAR_MAX. */
#include <limits.h>
#include <string.h>
/* C89 compliant way to cast 'char' to 'unsigned char'. */
static inline unsigned char
to_uchar (char ch)
{
return ch;
}
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
terminate the output buffer. */
void
base64_encode (const char *restrict in, size_t inlen,
char *restrict out, size_t outlen)
{
static const char b64str[65] = /* KJW */
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (inlen && outlen)
{
*out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64str[((to_uchar (in[0]) << 4)
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
& 0x3f];
if (!--outlen)
break;
*out++ =
(inlen
? b64str[((to_uchar (in[1]) << 2)
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
if (outlen)
*out = '\0';
}
/* Allocate a buffer and store zero terminated base64 encoded data
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
the length of the encoded data, excluding the terminating zero. On
return, the OUT variable will hold a pointer to newly allocated
memory that must be deallocated by the caller. If output string
length would overflow, 0 is returned and OUT is set to NULL. If
memory allocation failed, OUT is set to NULL, and the return value
indicates length of the requested memory block, i.e.,
BASE64_LENGTH(inlen) + 1. */
size_t
base64_encode_alloc (const char *in, size_t inlen, char **out)
{
size_t outlen = 1 + BASE64_LENGTH (inlen);
/* Check for overflow in outlen computation.
*
* If there is no overflow, outlen >= inlen.
*
* If the operation (inlen + 2) overflows then it yields at most +1, so
* outlen is 0.
*
* If the multiplication overflows, we lose at least half of the
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
* (inlen > 4).
*/
if (inlen > outlen)
{
*out = NULL;
return 0;
}
*out = (char *) malloc (outlen); /* KJW */
if (!*out)
return outlen;
base64_encode (in, inlen, *out, outlen);
return outlen - 1;
}
/* With this approach this file works independent of the charset used
(think EBCDIC). However, it does assume that the characters in the
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
1003.1-2001 require that char and unsigned char are 8-bit
quantities, though, taking care of that problem. But this may be a
potential problem on non-POSIX C99 platforms.
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
as the formal parameter rather than "x". */
#define B64(_) \
((_) == 'A' ? 0 \
: (_) == 'B' ? 1 \
: (_) == 'C' ? 2 \
: (_) == 'D' ? 3 \
: (_) == 'E' ? 4 \
: (_) == 'F' ? 5 \
: (_) == 'G' ? 6 \
: (_) == 'H' ? 7 \
: (_) == 'I' ? 8 \
: (_) == 'J' ? 9 \
: (_) == 'K' ? 10 \
: (_) == 'L' ? 11 \
: (_) == 'M' ? 12 \
: (_) == 'N' ? 13 \
: (_) == 'O' ? 14 \
: (_) == 'P' ? 15 \
: (_) == 'Q' ? 16 \
: (_) == 'R' ? 17 \
: (_) == 'S' ? 18 \
: (_) == 'T' ? 19 \
: (_) == 'U' ? 20 \
: (_) == 'V' ? 21 \
: (_) == 'W' ? 22 \
: (_) == 'X' ? 23 \
: (_) == 'Y' ? 24 \
: (_) == 'Z' ? 25 \
: (_) == 'a' ? 26 \
: (_) == 'b' ? 27 \
: (_) == 'c' ? 28 \
: (_) == 'd' ? 29 \
: (_) == 'e' ? 30 \
: (_) == 'f' ? 31 \
: (_) == 'g' ? 32 \
: (_) == 'h' ? 33 \
: (_) == 'i' ? 34 \
: (_) == 'j' ? 35 \
: (_) == 'k' ? 36 \
: (_) == 'l' ? 37 \
: (_) == 'm' ? 38 \
: (_) == 'n' ? 39 \
: (_) == 'o' ? 40 \
: (_) == 'p' ? 41 \
: (_) == 'q' ? 42 \
: (_) == 'r' ? 43 \
: (_) == 's' ? 44 \
: (_) == 't' ? 45 \
: (_) == 'u' ? 46 \
: (_) == 'v' ? 47 \
: (_) == 'w' ? 48 \
: (_) == 'x' ? 49 \
: (_) == 'y' ? 50 \
: (_) == 'z' ? 51 \
: (_) == '0' ? 52 \
: (_) == '1' ? 53 \
: (_) == '2' ? 54 \
: (_) == '3' ? 55 \
: (_) == '4' ? 56 \
: (_) == '5' ? 57 \
: (_) == '6' ? 58 \
: (_) == '7' ? 59 \
: (_) == '8' ? 60 \
: (_) == '9' ? 61 \
: (_) == '+' ? 62 \
: (_) == '/' ? 63 \
: -1)
static const signed char b64[0x100] = {
B64 (0), B64 (1), B64 (2), B64 (3),
B64 (4), B64 (5), B64 (6), B64 (7),
B64 (8), B64 (9), B64 (10), B64 (11),
B64 (12), B64 (13), B64 (14), B64 (15),
B64 (16), B64 (17), B64 (18), B64 (19),
B64 (20), B64 (21), B64 (22), B64 (23),
B64 (24), B64 (25), B64 (26), B64 (27),
B64 (28), B64 (29), B64 (30), B64 (31),
B64 (32), B64 (33), B64 (34), B64 (35),
B64 (36), B64 (37), B64 (38), B64 (39),
B64 (40), B64 (41), B64 (42), B64 (43),
B64 (44), B64 (45), B64 (46), B64 (47),
B64 (48), B64 (49), B64 (50), B64 (51),
B64 (52), B64 (53), B64 (54), B64 (55),
B64 (56), B64 (57), B64 (58), B64 (59),
B64 (60), B64 (61), B64 (62), B64 (63),
B64 (64), B64 (65), B64 (66), B64 (67),
B64 (68), B64 (69), B64 (70), B64 (71),
B64 (72), B64 (73), B64 (74), B64 (75),
B64 (76), B64 (77), B64 (78), B64 (79),
B64 (80), B64 (81), B64 (82), B64 (83),
B64 (84), B64 (85), B64 (86), B64 (87),
B64 (88), B64 (89), B64 (90), B64 (91),
B64 (92), B64 (93), B64 (94), B64 (95),
B64 (96), B64 (97), B64 (98), B64 (99),
B64 (100), B64 (101), B64 (102), B64 (103),
B64 (104), B64 (105), B64 (106), B64 (107),
B64 (108), B64 (109), B64 (110), B64 (111),
B64 (112), B64 (113), B64 (114), B64 (115),
B64 (116), B64 (117), B64 (118), B64 (119),
B64 (120), B64 (121), B64 (122), B64 (123),
B64 (124), B64 (125), B64 (126), B64 (127),
B64 (128), B64 (129), B64 (130), B64 (131),
B64 (132), B64 (133), B64 (134), B64 (135),
B64 (136), B64 (137), B64 (138), B64 (139),
B64 (140), B64 (141), B64 (142), B64 (143),
B64 (144), B64 (145), B64 (146), B64 (147),
B64 (148), B64 (149), B64 (150), B64 (151),
B64 (152), B64 (153), B64 (154), B64 (155),
B64 (156), B64 (157), B64 (158), B64 (159),
B64 (160), B64 (161), B64 (162), B64 (163),
B64 (164), B64 (165), B64 (166), B64 (167),
B64 (168), B64 (169), B64 (170), B64 (171),
B64 (172), B64 (173), B64 (174), B64 (175),
B64 (176), B64 (177), B64 (178), B64 (179),
B64 (180), B64 (181), B64 (182), B64 (183),
B64 (184), B64 (185), B64 (186), B64 (187),
B64 (188), B64 (189), B64 (190), B64 (191),
B64 (192), B64 (193), B64 (194), B64 (195),
B64 (196), B64 (197), B64 (198), B64 (199),
B64 (200), B64 (201), B64 (202), B64 (203),
B64 (204), B64 (205), B64 (206), B64 (207),
B64 (208), B64 (209), B64 (210), B64 (211),
B64 (212), B64 (213), B64 (214), B64 (215),
B64 (216), B64 (217), B64 (218), B64 (219),
B64 (220), B64 (221), B64 (222), B64 (223),
B64 (224), B64 (225), B64 (226), B64 (227),
B64 (228), B64 (229), B64 (230), B64 (231),
B64 (232), B64 (233), B64 (234), B64 (235),
B64 (236), B64 (237), B64 (238), B64 (239),
B64 (240), B64 (241), B64 (242), B64 (243),
B64 (244), B64 (245), B64 (246), B64 (247),
B64 (248), B64 (249), B64 (250), B64 (251),
B64 (252), B64 (253), B64 (254), B64 (255)
};
#if UCHAR_MAX == 255
# define uchar_in_range(c) true
#else
# define uchar_in_range(c) ((c) <= 255)
#endif
/* Return true if CH is a character from the Base64 alphabet, and
false otherwise. Note that '=' is padding and not considered to be
part of the alphabet. */
bool
isbase64 (char ch)
{
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
}
/* Initialize decode-context buffer, CTX. */
void
base64_decode_ctx_init (struct base64_decode_context *ctx)
{
ctx->i = 0;
}
/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
none of those four is a newline, then return *IN. Otherwise, copy up to
4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
index CTX->i and setting CTX->i to reflect the number of bytes copied,
and return CTX->buf. In either case, advance *IN to point to the byte
after the last one processed, and set *N_NON_NEWLINE to the number of
verified non-newline bytes accessible through the returned pointer. */
static inline char *
get_4 (struct base64_decode_context *ctx,
char const *restrict *in, char const *restrict in_end,
size_t *n_non_newline)
{
if (ctx->i == 4)
ctx->i = 0;
if (ctx->i == 0)
{
char const *t = *in;
if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
{
/* This is the common case: no newline. */
*in += 4;
*n_non_newline = 4;
return (char *) t;
}
}
{
/* Copy non-newline bytes into BUF. */
char const *p = *in;
while (p < in_end)
{
char c = *p++;
if (c != '\n')
{
ctx->buf[ctx->i++] = c;
if (ctx->i == 4)
break;
}
}
*in = p;
*n_non_newline = ctx->i;
return ctx->buf;
}
}
#define return_false \
do \
{ \
*outp = out; \
return false; \
} \
while (false)
/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
decoding is successful, false otherwise. If *OUTLEN is too small,
as many bytes as possible are written to *OUT. On return, advance
*OUT to point to the byte after the last one written, and decrement
*OUTLEN to reflect the number of bytes remaining in *OUT. */
static inline bool
decode_4 (char const *restrict in, size_t inlen,
char *restrict *outp, size_t *outleft)
{
char *out = *outp;
if (inlen < 2)
return false;
if (!isbase64 (in[0]) || !isbase64 (in[1]))
return false;
if (*outleft)
{
*out++ = ((b64[to_uchar (in[0])] << 2)
| (b64[to_uchar (in[1])] >> 4));
--*outleft;
}
if (inlen == 2)
return_false;
if (in[2] == '=')
{
if (inlen != 4)
return_false;
if (in[3] != '=')
return_false;
}
else
{
if (!isbase64 (in[2]))
return_false;
if (*outleft)
{
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
| (b64[to_uchar (in[2])] >> 2));
--*outleft;
}
if (inlen == 3)
return_false;
if (in[3] == '=')
{
if (inlen != 4)
return_false;
}
else
{
if (!isbase64 (in[3]))
return_false;
if (*outleft)
{
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
| b64[to_uchar (in[3])]);
--*outleft;
}
}
}
*outp = out;
return true;
}
/* Decode base64-encoded input array IN of length INLEN to output array
OUT that can hold *OUTLEN bytes. The input data may be interspersed
with newlines. Return true if decoding was successful, i.e. if the
input was valid base64 data, false otherwise. If *OUTLEN is too
small, as many bytes as possible will be written to OUT. On return,
*OUTLEN holds the length of decoded bytes in OUT. Note that as soon
as any non-alphabet, non-newline character is encountered, decoding
is stopped and false is returned. If INLEN is zero, then process
only whatever data is stored in CTX.
Initially, CTX must have been initialized via base64_decode_ctx_init.
Subsequent calls to this function must reuse whatever state is recorded
in that buffer. It is necessary for when a quadruple of base64 input
bytes spans two input buffers.
If CTX is NULL then newlines are treated as garbage and the input
buffer is processed as a unit. */
bool
base64_decode_ctx (struct base64_decode_context *ctx,
const char *restrict in, size_t inlen,
char *restrict out, size_t *outlen)
{
size_t outleft = *outlen;
bool ignore_newlines = ctx != NULL;
bool flush_ctx = false;
unsigned int ctx_i = 0;
if (ignore_newlines)
{
ctx_i = ctx->i;
flush_ctx = inlen == 0;
}
while (true)
{
size_t outleft_save = outleft;
if (ctx_i == 0 && !flush_ctx)
{
while (true)
{
/* Save a copy of outleft, in case we need to re-parse this
block of four bytes. */
outleft_save = outleft;
if (!decode_4 (in, inlen, &out, &outleft))
break;
in += 4;
inlen -= 4;
}
}
if (inlen == 0 && !flush_ctx)
break;
/* Handle the common case of 72-byte wrapped lines.
This also handles any other multiple-of-4-byte wrapping. */
if (inlen && *in == '\n' && ignore_newlines)
{
++in;
--inlen;
continue;
}
/* Restore OUT and OUTLEFT. */
out -= outleft_save - outleft;
outleft = outleft_save;
{
char const *in_end = in + inlen;
char const *non_nl;
if (ignore_newlines)
non_nl = get_4 (ctx, &in, in_end, &inlen);
else
non_nl = in; /* Might have nl in this case. */
/* If the input is empty or consists solely of newlines (0 non-newlines),
then we're done. Likewise if there are fewer than 4 bytes when not
flushing context and not treating newlines as garbage. */
if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
{
inlen = 0;
break;
}
if (!decode_4 (non_nl, inlen, &out, &outleft))
break;
inlen = in_end - in;
}
}
*outlen -= outleft;
return inlen == 0;
}
/* Allocate an output buffer in *OUT, and decode the base64 encoded
data stored in IN of size INLEN to the *OUT buffer. On return, the
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
if the caller is not interested in the decoded length. *OUT may be
NULL to indicate an out of memory error, in which case *OUTLEN
contains the size of the memory block needed. The function returns
true on successful decoding and memory allocation errors. (Use the
*OUT and *OUTLEN parameters to differentiate between successful
decoding and memory error.) The function returns false if the
input was invalid, in which case *OUT is NULL and *OUTLEN is
undefined. */
bool
base64_decode_alloc_ctx (struct base64_decode_context *ctx,
const char *in, size_t inlen, char **out,
size_t *outlen)
{
/* This may allocate a few bytes too many, depending on input,
but it's not worth the extra CPU time to compute the exact size.
The exact size is 3 * inlen / 4, minus 1 if the input ends
with "=" and minus another 1 if the input ends with "==".
Dividing before multiplying avoids the possibility of overflow. */
size_t needlen = 3 * (inlen / 4) + 2;
*out = (char *) malloc (needlen);
if (!*out)
return true;
if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
{
free (*out);
*out = NULL;
return false;
}
if (outlen)
*outlen = needlen;
return true;
}
+65
View File
@@ -0,0 +1,65 @@
/* Taken from GNU coreutils */
#define restrict
/* base64.h -- Encode binary data using printable characters.
Copyright (C) 2004-2006, 2009-2011 Free Software Foundation, Inc.
Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef BASE64_H
# define BASE64_H
/* Get size_t. */
# include <stddef.h>
/* Get bool. */
# include <stdbool.h>
/* This uses that the expression (n+(k-1))/k means the smallest
integer >= n/k, i.e., the ceiling of n/k. */
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
struct base64_decode_context
{
unsigned int i;
char buf[4];
};
extern bool isbase64 (char ch);
extern void base64_encode (const char *restrict in, size_t inlen,
char *restrict out, size_t outlen);
extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
extern bool base64_decode_ctx (struct base64_decode_context *ctx,
const char *restrict in, size_t inlen,
char *restrict out, size_t *outlen);
extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
const char *in, size_t inlen,
char **out, size_t *outlen);
#define base64_decode(in, inlen, out, outlen) \
base64_decode_ctx (NULL, in, inlen, out, outlen)
#define base64_decode_alloc(in, inlen, out, outlen) \
base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
#endif /* BASE64_H */
+211
View File
@@ -0,0 +1,211 @@
#include <string.h>
#include <stdio.h>
#include "crypto.hpp"
#include "base64.h"
using namespace std;
const char rdev[] = "/dev/urandom";
static void * sse_alloc( int len )
{
void *ptr = NULL;
if( (0 != posix_memalign( (void **)&ptr, 16, len )) || (ptr == NULL) ) {
throw std::bad_alloc();
}
return ptr;
}
Base64Key::Base64Key( string printable_key )
{
if ( printable_key.length() != 22 ) {
throw CryptoException( "Key must be 22 letters long." );
}
string base64 = printable_key + "==";
size_t len = 16;
if ( !base64_decode( base64.data(), 24, (char *)&key[ 0 ], &len ) ) {
throw CryptoException( "Key must be well-formed base64." );
}
if ( len != 16 ) {
throw CryptoException( "Key must represent 16 octets." );
}
/* to catch changes after the first 128 bits */
if ( printable_key != this->printable_key() ) {
throw CryptoException( "Base64 key was not encoded 128-bit key." );
}
}
Base64Key::Base64Key()
{
FILE *devrandom = fopen( rdev, "r" );
if ( devrandom == NULL ) {
throw CryptoException( string( rdev ) + ": " + strerror( errno ) );
}
if ( 1 != fread( key, 16, 1, devrandom ) ) {
throw CryptoException( "Could not read from " + string( rdev ) );
}
if ( 0 != fclose( devrandom ) ) {
throw CryptoException( string( rdev ) + ": " + strerror( errno ) );
}
}
string Base64Key::printable_key( void )
{
char base64[ 25 ];
base64_encode( (char *)key, 16, base64, 25 );
if ( (base64[ 24 ] != 0)
|| (base64[ 23 ] != '=')
|| (base64[ 22 ] != '=') ) {
throw CryptoException( "Unexpected output from base64_encode." );
}
base64[ 22 ] = 0;
return string( base64 );
}
Session::Session( Base64Key s_key )
: key( s_key ), ctx( NULL )
{
ctx = ae_allocate( NULL );
if ( ctx == NULL ) {
throw CryptoException( "Could not allocate AES-OCB context." );
}
if ( AE_SUCCESS != ae_init( ctx, key.data(), 16, 12, 16 ) ) {
throw CryptoException( "Could not initialize AES-OCB context." );
}
}
Session::~Session()
{
if ( ae_clear( ctx ) != AE_SUCCESS ) {
throw CryptoException( "Could not clear AES-OCB context." );
}
ae_free( ctx );
}
Nonce::Nonce( uint64_t val )
{
uint64_t val_net = htobe64( val );
memset( bytes, 0, 4 );
memcpy( bytes + 4, &val_net, 8 );
}
uint64_t Nonce::val( void )
{
uint64_t ret;
memcpy( &ret, bytes + 4, 8 );
return be64toh( ret );
}
Nonce::Nonce( char *s_bytes, size_t len )
{
if ( len != 8 ) {
throw CryptoException( "Nonce representation must be 8 octets long." );
}
memset( bytes, 0, 4 );
memcpy( bytes + 4, s_bytes, 8 );
}
Message::Message( char *nonce_bytes, size_t nonce_len,
char *text_bytes, size_t text_len )
: nonce( nonce_bytes, nonce_len ),
text( (char *)text_bytes, text_len )
{}
Message::Message( Nonce s_nonce, string s_text )
: nonce( s_nonce ),
text( s_text )
{}
string Session::encrypt( Message plaintext )
{
const size_t pt_len = plaintext.text.size();
const int ciphertext_len = pt_len + 16;
char *ciphertext = (char *)sse_alloc( ciphertext_len );
char *pt = (char *)sse_alloc( pt_len );
memcpy( pt, plaintext.text.data(), plaintext.text.size() );
if ( (uint64_t( plaintext.nonce.data() ) & 0xf) != 0 ) {
throw CryptoException( "Bad alignment." );
}
if ( ciphertext_len != ae_encrypt( ctx, /* ctx */
plaintext.nonce.data(), /* nonce */
pt, /* pt */
pt_len, /* pt_len */
NULL, /* ad */
0, /* ad_len */
ciphertext, /* ct */
NULL, /* tag */
AE_FINALIZE ) ) { /* final */
free( pt );
free( ciphertext );
throw CryptoException( "ae_encrypt() returned error." );
}
string text( (char *)ciphertext, ciphertext_len );
free( pt );
free( ciphertext );
return plaintext.nonce.cpp_str() + text;
}
Message Session::decrypt( string ciphertext )
{
if ( ciphertext.size() < 24 ) {
throw CryptoException( "Ciphertext must contain nonce and tag." );
}
char *str = (char *)ciphertext.data();
int body_len = ciphertext.size() - 8;
int pt_len = body_len - 16;
if ( pt_len <= 0 ) { /* super-assertion that does not equal AE_INVALID */
fprintf( stderr, "BUG.\n" );
exit( 1 );
}
Nonce __attribute__((__aligned__ (16))) nonce( str, 8 );
char *body = (char *)sse_alloc( body_len );
memcpy( body, str + 8, body_len );
char *plaintext = (char *)sse_alloc( pt_len );
if ( pt_len != ae_decrypt( ctx, /* ctx */
nonce.data(), /* nonce */
body, /* ct */
body_len, /* ct_len */
NULL, /* ad */
0, /* ad_len */
plaintext, /* pt */
NULL, /* tag */
AE_FINALIZE ) ) { /* final */
free( plaintext );
free( body );
throw CryptoException( "ae_decrypt() returned error." );
}
Message ret( nonce, string( plaintext, pt_len ) );
free( plaintext );
free( body );
return ret;
}
+65
View File
@@ -0,0 +1,65 @@
#ifndef CRYPTO_HPP
#define CRYPTO_HPP
#include "ae.hpp"
#include <string>
using namespace std;
class CryptoException {
public:
string text;
CryptoException( string s_text ) : text( s_text ) {};
};
class Base64Key {
private:
unsigned char key[ 16 ];
public:
Base64Key(); /* random key */
Base64Key( string printable_key );
string printable_key( void );
unsigned char *data( void ) { return key; }
};
class Nonce {
private:
char bytes[ 12 ];
public:
Nonce( uint64_t val );
Nonce( char *s_bytes, size_t len );
string cpp_str( void ) { return string( (char *)( bytes + 4 ), 8 ); }
char *data( void ) { return bytes; }
uint64_t val( void );
};
class Message {
public:
Nonce nonce;
string text;
Message( char *nonce_bytes, size_t nonce_len,
char *text_bytes, size_t text_len );
Message( Nonce s_nonce, string s_text );
};
class Session {
private:
Base64Key key;
ae_ctx *ctx;
public:
Session( Base64Key s_key );
~Session();
string encrypt( Message plaintext );
Message decrypt( string ciphertext );
Session( const Session & );
Session & operator=( const Session & );
};
#endif
+58
View File
@@ -0,0 +1,58 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "crypto.hpp"
int main( int argc, char *argv[] )
{
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s KEY\n", argv[ 0 ] );
return 1;
}
try {
Base64Key key( argv[ 1 ] );
Session session( key );
/* Read input */
char *input = NULL;
int total_size = 0;
while ( 1 ) {
unsigned char buf[ 16384 ];
ssize_t bytes_read = read( STDIN_FILENO, buf, 16384 );
if ( bytes_read == 0 ) { /* EOF */
break;
} else if ( bytes_read < 0 ) {
perror( "read" );
exit( 1 );
} else {
input = (char *)realloc( input, total_size + bytes_read );
assert( input );
memcpy( input + total_size, buf, bytes_read );
total_size += bytes_read;
}
}
string ciphertext( input, total_size );
free( input );
/* Decrypt message */
Message message = session.decrypt( ciphertext );
fprintf( stderr, "Nonce = %ld\n",
message.nonce.val() );
cout << message.text;
} catch ( CryptoException e ) {
cerr << e.text << endl;
exit( 1 );
}
return 0;
}
+74
View File
@@ -0,0 +1,74 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "crypto.hpp"
long int myatoi( char *str )
{
char *end;
errno = 0;
long int ret = strtol( str, &end, 10 );
if ( ( errno != 0 )
|| ( end != str + strlen( str ) ) ) {
throw CryptoException( "Bad integer." );
}
return ret;
}
int main( int argc, char *argv[] )
{
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s NONCE\n", argv[ 0 ] );
return 1;
}
try {
Base64Key key;
Session session( key );
Nonce nonce( myatoi( argv[ 1 ] ) );
/* Read input */
char *input = NULL;
int total_size = 0;
while ( 1 ) {
unsigned char buf[ 16384 ];
ssize_t bytes_read = read( STDIN_FILENO, buf, 16384 );
if ( bytes_read == 0 ) { /* EOF */
break;
} else if ( bytes_read < 0 ) {
perror( "read" );
exit( 1 );
} else {
input = (char *)realloc( input, total_size + bytes_read );
assert( input );
memcpy( input + total_size, buf, bytes_read );
total_size += bytes_read;
}
}
string plaintext( input, total_size );
free( input );
/* Encrypt message */
string ciphertext = session.encrypt( Message( nonce, plaintext ) );
cerr << "Key: " << key.printable_key() << endl;
cout << ciphertext;
} catch ( CryptoException e ) {
cerr << e.text << endl;
exit( 1 );
}
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
<TITLE>OCB - An Authenticated-Encryption Scheme - GPL Patent Grant - Rogaway</TITLE>
<body bgcolor="#FFFFFF">
<H2><a name="ocb-grant"> <font face="Arial, Helvetica, sans-serif" size="6" color="#FF0000">OCB:
Patent Grant for GNU GPL</font> </a> </H2>
Whereas I, Phillip Rogaway (hereinafter "Inventor") have sought
patent protection for certain technology
(hereinafter "Patented Technology"),
and Inventor wishes to aid the Free Software Foundation in achieving its goals,
and Inventor wishes to increase public awareness of Patented Technology,
Inventor hereby grants a fully paid-up, nonexclusive,
royalty-free license to
practice any patents claiming priority to the
patent applications below ("the Patents")
if practiced by
software distributed
under the terms of any version of
the GNU General Public License as published by the Free Software Foundation,
59 Temple Place, Suite 330, Boston, MA 02111.
Inventor reserves all other rights, including without limitation
licensing for software not distributed under the GNU General Public License.
<h4>The patents:</h4>
<ul>
<li> <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO2&Sect2=HITOFF&p=1&u=%2Fnetahtml%2FPTO%2Fsearch-bool.html&r=2&f=G&l=50&co1=AND&d=PG01&s1=rogaway.IN.&OS=IN/rogaway&RS=IN/rogaway">
09/918,615</a> -
Method and Apparatus for Facilitating Efficient Authenticated Encryption.
<li> <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO2&Sect2=HITOFF&p=1&u=%2Fnetahtml%2FPTO%2Fsearch-bool.html&r=3&f=G&l=50&co1=AND&d=PG01&s1=rogaway.IN.&OS=IN/rogaway&RS=IN/rogaway">
09/948,084</a> -
Method and Apparatus for Realizing a Parallelizable Variable-Input-Length
Pseudorandom Function.
</ul>
+1226
View File
File diff suppressed because it is too large Load Diff