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:
committed by
Alex Chernyakhovsky
parent
2f90addb7c
commit
a563093f16
@@ -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"])
|
||||
|
||||
Vendored
+2
-1
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user