Separate OpenSSL-based OCB implementation from others

Split src/crypto/ocb.cc into two files – one containing the AES-OCB
implementation backed by OpenSSL, and the other containing
implementations backed by Apple Common Crypto and Nettle. This paves the
way for a new OpenSSL implementation that uses OpenSSL 1.1’s OCB support
directly, rather than one that merely uses OpenSSL to provide the
underlying block cipher.

Remove support for rijndael-alg-fst.c and compiler-provided AES
intrinsics, since they’re not in use anymore. (Mosh can still use
hardware-accelerated AES if it’s available; it just now relies
exclusively on the underlying cryptography library to accelerate AES if
possible.)

Update the build system to conditionally compile in either
ocb_openssl.cc or ocb_internal.cc, depending on which cryptography
library you pass to ./configure.

To make this commit easy to audit, ocb_openssl.cc and ocb_internal.cc
are trivially diffable against ocb.cc (now deleted). Expected diffs
consist of a copyright notice update, a preprocessor check to ensure the
appropriate cryptography implementation has been selected, and deletions
to remove code that’s no longer in use. This does mean a substantial
amount of code is duplicated between ocb_openssl.cc and ocb_internal.cc;
however, ocb_openssl.cc should be completely replaced soon, so it won’t
be an issue in the long term.

Bug: https://github.com/mobile-shell/mosh/issues/1174
This commit is contained in:
Benjamin Barenblat
2022-06-06 22:00:31 -04:00
committed by Alex Chernyakhovsky
parent 2f90addb7c
commit a563093f16
5 changed files with 1230 additions and 259 deletions
+4
View File
@@ -399,6 +399,10 @@ case "${with_crypto_library}" in
;;
esac
AM_CONDITIONAL([CRYPTO_LIBRARY_OPENSSL], [test x$with_crypto_library = xopenssl])
AM_CONDITIONAL([CRYPTO_LIBRARY_NETTLE], [test x$with_crypto_library = xnettle])
AM_CONDITIONAL([CRYPTO_LIBRARY_APPLE], [test x$with_crypto_library = xapple-common-crypto])
AC_ARG_ENABLE([static-crypto],
[AS_HELP_STRING([--enable-static-crypto], [Link crypto library statically @<:@no@:>@])],
[], [enable_static_crypto="$enable_static_libraries"])
+2 -1
View File
@@ -98,8 +98,9 @@ License: GPL-3+ with Autoconf exception
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
Files: src/crypto/ocb.cc
Files: src/crypto/ocb_internal.cc src/crypto/ocb_openssl.cc
Copyright: 2011 Ted Krovetz
2022 Google LLC
License: ISC
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
+6 -3
View File
@@ -3,9 +3,12 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXF
noinst_LIBRARIES = libmoshcrypto.a
OCB_SRCS = \
ae.h \
ocb.cc
OCB_SRCS = ae.h
if CRYPTO_LIBRARY_OPENSSL
OCB_SRCS += ocb_openssl.cc
else
OCB_SRCS += ocb_internal.cc
endif
libmoshcrypto_a_SOURCES = \
$(OCB_SRCS) \
+12 -255
View File
@@ -2,6 +2,7 @@
/ OCB Version 3 Reference Code (Optimized C) Last modified 08-SEP-2012
/-------------------------------------------------------------------------
/ Copyright (c) 2012 Ted Krovetz.
/ Copyright 2022 Google LLC
/
/ Permission to use, copy, modify, and/or distribute this software for any
/ purpose with or without fee is hereby granted, provided that the above
@@ -23,6 +24,14 @@
/ Comments are welcome: Ted Krovetz <ted@krovetz.net> - Dedicated to Laurel K
/------------------------------------------------------------------------- */
#include "config.h"
/* This module implements the ae.h interface for Apple Common Crypto and
/ Nettle. */
#if !defined(USE_APPLE_COMMON_CRYPTO_AES) && !defined(USE_NETTLE_AES)
#error ocb_internal.cc only works with Apple Common Crypto or Nettle
#endif
/* ----------------------------------------------------------------------- */
/* Usage notes */
/* ----------------------------------------------------------------------- */
@@ -53,9 +62,6 @@
#if 0
#define USE_APPLE_COMMON_CRYPTO_AES 0
#define USE_NETTLE_AES 0
#define USE_OPENSSL_AES 1 /* http://openssl.org */
#define USE_REFERENCE_AES 0 /* Internet search: rijndael-alg-fst.c */
#define USE_AES_NI 0 /* Uses compiler's intrinsics */
#endif
/* During encryption and decryption, various "L values" are required.
@@ -76,7 +82,6 @@
/* Includes and compiler specific definitions */
/* ----------------------------------------------------------------------- */
#include "config.h"
#include "ae.h"
#include <stdlib.h>
#include <string.h>
@@ -175,7 +180,7 @@
#define zero_block() _mm_setzero_si128()
#define unequal_blocks(x,y) \
(_mm_movemask_epi8(_mm_cmpeq_epi8(x,y)) != 0xffff)
#if __SSSE3__ || USE_AES_NI
#if __SSSE3__
#include <tmmintrin.h> /* SSSE3 instructions */
#define swap_if_le(b) \
_mm_shuffle_epi8(b,_mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
@@ -193,7 +198,7 @@
__m128i lshift = _mm_cvtsi32_si128(bot);
__m128i rshift = _mm_cvtsi32_si128(64-bot);
lo = _mm_xor_si128(_mm_sll_epi64(hi,lshift),_mm_srl_epi64(lo,rshift));
#if __SSSE3__ || USE_AES_NI
#if __SSSE3__
return _mm_shuffle_epi8(lo,_mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7));
#else
return swap_if_le(_mm_shuffle_epi32(lo, _MM_SHUFFLE(1,0,3,2)));
@@ -347,31 +352,8 @@
/* AES - Code uses OpenSSL API. Other implementations get mapped to it. */
/* ----------------------------------------------------------------------- */
/*---------------*/
#if USE_OPENSSL_AES
/*---------------*/
#include <openssl/aes.h> /* http://openssl.org/ */
/* How to ECB encrypt an array of blocks, in place */
static inline void AES_ecb_encrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
while (nblks) {
--nblks;
AES_encrypt((unsigned char *)(blks+nblks), (unsigned char *)(blks+nblks), key);
}
}
static inline void AES_ecb_decrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
while (nblks) {
--nblks;
AES_decrypt((unsigned char *)(blks+nblks), (unsigned char *)(blks+nblks), key);
}
}
#define BPI 4 /* Number of blocks in buffer per ECB call */
/*-------------------*/
#elif USE_APPLE_COMMON_CRYPTO_AES
#if USE_APPLE_COMMON_CRYPTO_AES
/*-------------------*/
#include <fatal_assert.h>
@@ -495,219 +477,6 @@ static inline void AES_ecb_decrypt_blks(block *blks, unsigned nblks, AES_KEY *ke
#define BPI 4 /* Number of blocks in buffer per ECB call */
/*-------------------*/
#elif USE_REFERENCE_AES
/*-------------------*/
#include "rijndael-alg-fst.h" /* Barreto's Public-Domain Code */
#if (OCB_KEY_LEN == 0)
typedef struct { uint32_t rd_key[60]; int rounds; } AES_KEY;
#define ROUNDS(ctx) ((ctx)->rounds)
#define AES_set_encrypt_key(x, y, z) \
do {rijndaelKeySetupEnc((z)->rd_key, x, y); (z)->rounds = y/32+6;} while (0)
#define AES_set_decrypt_key(x, y, z) \
do {rijndaelKeySetupDec((z)->rd_key, x, y); (z)->rounds = y/32+6;} while (0)
#else
typedef struct { uint32_t rd_key[OCB_KEY_LEN+28]; } AES_KEY;
#define ROUNDS(ctx) (6+OCB_KEY_LEN/4)
#define AES_set_encrypt_key(x, y, z) rijndaelKeySetupEnc((z)->rd_key, x, y)
#define AES_set_decrypt_key(x, y, z) rijndaelKeySetupDec((z)->rd_key, x, y)
#endif
#define AES_encrypt(x,y,z) rijndaelEncrypt((z)->rd_key, ROUNDS(z), x, y)
#define AES_decrypt(x,y,z) rijndaelDecrypt((z)->rd_key, ROUNDS(z), x, y)
static void AES_ecb_encrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
while (nblks) {
--nblks;
AES_encrypt((unsigned char *)(blks+nblks), (unsigned char *)(blks+nblks), key);
}
}
void AES_ecb_decrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
while (nblks) {
--nblks;
AES_decrypt((unsigned char *)(blks+nblks), (unsigned char *)(blks+nblks), key);
}
}
#define BPI 4 /* Number of blocks in buffer per ECB call */
/*----------*/
#elif USE_AES_NI
/*----------*/
#include <wmmintrin.h>
#if (OCB_KEY_LEN == 0)
typedef struct { __m128i rd_key[15]; int rounds; } AES_KEY;
#define ROUNDS(ctx) ((ctx)->rounds)
#else
typedef struct { __m128i rd_key[7+OCB_KEY_LEN/4]; } AES_KEY;
#define ROUNDS(ctx) (6+OCB_KEY_LEN/4)
#endif
#define EXPAND_ASSIST(v1,v2,v3,v4,shuff_const,aes_const) \
v2 = _mm_aeskeygenassist_si128(v4,aes_const); \
v3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(v3), \
_mm_castsi128_ps(v1), 16)); \
v1 = _mm_xor_si128(v1,v3); \
v3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(v3), \
_mm_castsi128_ps(v1), 140)); \
v1 = _mm_xor_si128(v1,v3); \
v2 = _mm_shuffle_epi32(v2,shuff_const); \
v1 = _mm_xor_si128(v1,v2)
#define EXPAND192_STEP(idx,aes_const) \
EXPAND_ASSIST(x0,x1,x2,x3,85,aes_const); \
x3 = _mm_xor_si128(x3,_mm_slli_si128 (x3, 4)); \
x3 = _mm_xor_si128(x3,_mm_shuffle_epi32(x0, 255)); \
kp[idx] = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(tmp), \
_mm_castsi128_ps(x0), 68)); \
kp[idx+1] = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(x0), \
_mm_castsi128_ps(x3), 78)); \
EXPAND_ASSIST(x0,x1,x2,x3,85,(aes_const*2)); \
x3 = _mm_xor_si128(x3,_mm_slli_si128 (x3, 4)); \
x3 = _mm_xor_si128(x3,_mm_shuffle_epi32(x0, 255)); \
kp[idx+2] = x0; tmp = x3
static void AES_128_Key_Expansion(const unsigned char *userkey, void *key)
{
__m128i x0,x1,x2;
__m128i *kp = (__m128i *)key;
kp[0] = x0 = _mm_loadu_si128((__m128i*)userkey);
x2 = _mm_setzero_si128();
EXPAND_ASSIST(x0,x1,x2,x0,255,1); kp[1] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,2); kp[2] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,4); kp[3] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,8); kp[4] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,16); kp[5] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,32); kp[6] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,64); kp[7] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,128); kp[8] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,27); kp[9] = x0;
EXPAND_ASSIST(x0,x1,x2,x0,255,54); kp[10] = x0;
}
static void AES_192_Key_Expansion(const unsigned char *userkey, void *key)
{
__m128i x0,x1,x2,x3,tmp,*kp = (__m128i *)key;
kp[0] = x0 = _mm_loadu_si128((__m128i*)userkey);
tmp = x3 = _mm_loadu_si128((__m128i*)(userkey+16));
x2 = _mm_setzero_si128();
EXPAND192_STEP(1,1);
EXPAND192_STEP(4,4);
EXPAND192_STEP(7,16);
EXPAND192_STEP(10,64);
}
static void AES_256_Key_Expansion(const unsigned char *userkey, void *key)
{
__m128i x0,x1,x2,x3,*kp = (__m128i *)key;
kp[0] = x0 = _mm_loadu_si128((__m128i*)userkey );
kp[1] = x3 = _mm_loadu_si128((__m128i*)(userkey+16));
x2 = _mm_setzero_si128();
EXPAND_ASSIST(x0,x1,x2,x3,255,1); kp[2] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,1); kp[3] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,2); kp[4] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,2); kp[5] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,4); kp[6] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,4); kp[7] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,8); kp[8] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,8); kp[9] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,16); kp[10] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,16); kp[11] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,32); kp[12] = x0;
EXPAND_ASSIST(x3,x1,x2,x0,170,32); kp[13] = x3;
EXPAND_ASSIST(x0,x1,x2,x3,255,64); kp[14] = x0;
}
static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
{
if (bits == 128) {
AES_128_Key_Expansion (userKey,key);
} else if (bits == 192) {
AES_192_Key_Expansion (userKey,key);
} else if (bits == 256) {
AES_256_Key_Expansion (userKey,key);
}
#if (OCB_KEY_LEN == 0)
key->rounds = 6+bits/32;
#endif
return 0;
}
static void AES_set_decrypt_key_fast(AES_KEY *dkey, const AES_KEY *ekey)
{
int j = 0;
int i = ROUNDS(ekey);
#if (OCB_KEY_LEN == 0)
dkey->rounds = i;
#endif
dkey->rd_key[i--] = ekey->rd_key[j++];
while (i)
dkey->rd_key[i--] = _mm_aesimc_si128(ekey->rd_key[j++]);
dkey->rd_key[i] = ekey->rd_key[j];
}
static int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
{
AES_KEY temp_key;
AES_set_encrypt_key(userKey,bits,&temp_key);
AES_set_decrypt_key_fast(key, &temp_key);
return 0;
}
static inline void AES_encrypt(const unsigned char *in,
unsigned char *out, const AES_KEY *key)
{
int j,rnds=ROUNDS(key);
const __m128i *sched = ((__m128i *)(key->rd_key));
__m128i tmp = _mm_load_si128 ((__m128i*)in);
tmp = _mm_xor_si128 (tmp,sched[0]);
for (j=1; j<rnds; j++) tmp = _mm_aesenc_si128 (tmp,sched[j]);
tmp = _mm_aesenclast_si128 (tmp,sched[j]);
_mm_store_si128 ((__m128i*)out,tmp);
}
static inline void AES_decrypt(const unsigned char *in,
unsigned char *out, const AES_KEY *key)
{
int j,rnds=ROUNDS(key);
const __m128i *sched = ((__m128i *)(key->rd_key));
__m128i tmp = _mm_load_si128 ((__m128i*)in);
tmp = _mm_xor_si128 (tmp,sched[0]);
for (j=1; j<rnds; j++) tmp = _mm_aesdec_si128 (tmp,sched[j]);
tmp = _mm_aesdeclast_si128 (tmp,sched[j]);
_mm_store_si128 ((__m128i*)out,tmp);
}
static inline void AES_ecb_encrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
unsigned i,j,rnds=ROUNDS(key);
const __m128i *sched = ((__m128i *)(key->rd_key));
for (i=0; i<nblks; ++i)
blks[i] =_mm_xor_si128(blks[i], sched[0]);
for(j=1; j<rnds; ++j)
for (i=0; i<nblks; ++i)
blks[i] = _mm_aesenc_si128(blks[i], sched[j]);
for (i=0; i<nblks; ++i)
blks[i] =_mm_aesenclast_si128(blks[i], sched[j]);
}
static inline void AES_ecb_decrypt_blks(block *blks, unsigned nblks, AES_KEY *key) {
unsigned i,j,rnds=ROUNDS(key);
const __m128i *sched = ((__m128i *)(key->rd_key));
for (i=0; i<nblks; ++i)
blks[i] =_mm_xor_si128(blks[i], sched[0]);
for(j=1; j<rnds; ++j)
for (i=0; i<nblks; ++i)
blks[i] = _mm_aesdec_si128(blks[i], sched[j]);
for (i=0; i<nblks; ++i)
blks[i] =_mm_aesdeclast_si128(blks[i], sched[j]);
}
#define BPI 8 /* Number of blocks in buffer per ECB call */
/* Set to 4 for Westmere, 8 for Sandy Bridge */
#else
#error "No AES implementation selected."
#endif
@@ -802,11 +571,7 @@ int ae_init(ae_ctx *ctx, const void *key, int key_len, int nonce_len, int tag_le
key_len = OCB_KEY_LEN;
#endif
AES_set_encrypt_key((unsigned char *)key, key_len*8, &ctx->encrypt_key);
#if USE_AES_NI
AES_set_decrypt_key_fast(&ctx->decrypt_key,&ctx->encrypt_key);
#else
AES_set_decrypt_key((unsigned char *)key, (int)(key_len*8), &ctx->decrypt_key);
#endif
/* Zero things that need zeroing */
ctx->cached_Top = ctx->ad_checksum = zero_block();
@@ -1555,11 +1320,3 @@ int main()
return 0;
}
#endif
#if USE_AES_NI
char infoString[] = "OCB3 (AES-NI)";
#elif USE_REFERENCE_AES
char infoString[] = "OCB3 (Reference)";
#elif USE_OPENSSL_AES
char infoString[] = "OCB3 (OpenSSL)";
#endif
File diff suppressed because it is too large Load Diff