diff options
author | Simon L. B. Nielsen <simon@FreeBSD.org> | 2008-09-21 14:56:30 +0000 |
---|---|---|
committer | Simon L. B. Nielsen <simon@FreeBSD.org> | 2008-09-21 14:56:30 +0000 |
commit | bb1499d2aac1d25a95b8573ff425751f06f159e1 (patch) | |
tree | a136b5b2317abe8eb83b021afe5e088230fd67e2 /crypto | |
parent | ee266f1253f9cc49430572463d26f72910dfb49e (diff) | |
download | src-bb1499d2aac1d25a95b8573ff425751f06f159e1.tar.gz src-bb1499d2aac1d25a95b8573ff425751f06f159e1.zip |
Vendor import of OpenSSL 0.9.8i.vendor/openssl/0.9.8i
Notes
Notes:
svn path=/vendor-crypto/openssl/dist/; revision=183234
svn path=/vendor-crypto/openssl/0.9.8i/; revision=193572; tag=vendor/openssl/0.9.8i
Diffstat (limited to 'crypto')
212 files changed, 19478 insertions, 6663 deletions
diff --git a/crypto/aes/Makefile b/crypto/aes/Makefile index 0f939eb7f8ee..22c7203dbb2e 100644 --- a/crypto/aes/Makefile +++ b/crypto/aes/Makefile @@ -24,8 +24,8 @@ APPS= LIB=$(TOP)/libcrypto.a LIBSRC=aes_core.c aes_misc.c aes_ecb.c aes_cbc.c aes_cfb.c aes_ofb.c \ - aes_ctr.c aes_ige.c -LIBOBJ=aes_misc.o aes_ecb.o aes_cfb.o aes_ofb.o aes_ctr.o aes_ige.o \ + aes_ctr.c aes_ige.c aes_wrap.c +LIBOBJ=aes_misc.o aes_ecb.o aes_cfb.o aes_ofb.o aes_ctr.o aes_ige.o aes_wrap.o \ $(AES_ASM_OBJ) SRC= $(LIBSRC) @@ -57,6 +57,9 @@ ax86-cof.s: asm/aes-586.pl ../perlasm/x86asm.pl ax86-out.s: asm/aes-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) aes-586.pl a.out $(CFLAGS) $(PROCESSOR) > ../$@) +aes-x86_64.s: asm/aes-x86_64.pl + $(PERL) asm/aes-x86_64.pl $@ + files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO @@ -117,3 +120,11 @@ aes_misc.o: ../../include/openssl/opensslconf.h aes_misc.o: ../../include/openssl/opensslv.h aes_locl.h aes_misc.c aes_ofb.o: ../../include/openssl/aes.h ../../include/openssl/e_os2.h aes_ofb.o: ../../include/openssl/opensslconf.h aes_locl.h aes_ofb.c +aes_wrap.o: ../../e_os.h ../../include/openssl/aes.h +aes_wrap.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +aes_wrap.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +aes_wrap.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +aes_wrap.o: ../../include/openssl/opensslconf.h +aes_wrap.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +aes_wrap.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +aes_wrap.o: ../../include/openssl/symhacks.h ../cryptlib.h aes_wrap.c diff --git a/crypto/aes/aes.h b/crypto/aes/aes.h index e6fc44a24d48..baf0222d49d3 100644 --- a/crypto/aes/aes.h +++ b/crypto/aes/aes.h @@ -130,6 +130,12 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key2, const unsigned char *ivec, const int enc); +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); #ifdef __cplusplus } diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c index 2082d060cf94..45d709618187 100644 --- a/crypto/aes/aes_ige.c +++ b/crypto/aes/aes_ige.c @@ -54,21 +54,25 @@ #include <openssl/aes.h> #include "aes_locl.h" -/* -static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) - { - int n=0; +#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) +typedef struct { + unsigned long data[N_WORDS]; +} aes_block_t; - fprintf(f,"%s",title); - for( ; n < l ; ++n) - { - if((n%16) == 0) - fprintf(f,"\n%04x",n); - fprintf(f," %02x",s[n]); - } - fprintf(f,"\n"); - } -*/ +/* XXX: probably some better way to do this */ +#if defined(__i386__) || defined(__x86_64__) +#define UNALIGNED_MEMOPS_ARE_FAST 1 +#else +#define UNALIGNED_MEMOPS_ARE_FAST 0 +#endif + +#if UNALIGNED_MEMOPS_ARE_FAST +#define load_block(d, s) (d) = *(const aes_block_t *)(s) +#define store_block(d, s) *(aes_block_t *)(d) = (s) +#else +#define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) +#define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) +#endif /* N.B. The IV for this mode is _twice_ the block size */ @@ -77,68 +81,125 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, unsigned char *ivec, const int enc) { unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - unsigned char tmp2[AES_BLOCK_SIZE]; - unsigned char prev[AES_BLOCK_SIZE]; - const unsigned char *iv = ivec; - const unsigned char *iv2 = ivec + AES_BLOCK_SIZE; + unsigned long len; OPENSSL_assert(in && out && key && ivec); OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); + len = length / AES_BLOCK_SIZE; + if (AES_ENCRYPT == enc) { - /* XXX: Do a separate case for when in != out (strictly should - check for overlap, too) */ - while (len >= AES_BLOCK_SIZE) + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0)) { - /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ - for(n=0 ; n < AES_BLOCK_SIZE ; ++n) - out[n] = in[n] ^ iv[n]; - /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ - AES_encrypt(out, out, key); - /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ - for(n=0 ; n < AES_BLOCK_SIZE ; ++n) - out[n] ^= iv2[n]; - /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ - iv = out; - memcpy(prev, in, AES_BLOCK_SIZE); - iv2 = prev; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; + aes_block_t *ivp = (aes_block_t *)ivec; + aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); + + while (len) + { + aes_block_t *inp = (aes_block_t *)in; + aes_block_t *outp = (aes_block_t *)out; + + for(n=0 ; n < N_WORDS; ++n) + outp->data[n] = inp->data[n] ^ ivp->data[n]; + AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key); + for(n=0 ; n < N_WORDS; ++n) + outp->data[n] ^= iv2p->data[n]; + ivp = outp; + iv2p = inp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } + else + { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) + { + load_block(tmp, in); + for(n=0 ; n < N_WORDS; ++n) + tmp2.data[n] = tmp.data[n] ^ iv.data[n]; + AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key); + for(n=0 ; n < N_WORDS; ++n) + tmp2.data[n] ^= iv2.data[n]; + store_block(out, tmp2); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } - memcpy(ivec, iv, AES_BLOCK_SIZE); - memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); } else { - while (len >= AES_BLOCK_SIZE) + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0)) { - memcpy(tmp, in, AES_BLOCK_SIZE); - memcpy(tmp2, in, AES_BLOCK_SIZE); - /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ - for(n=0 ; n < AES_BLOCK_SIZE ; ++n) - tmp[n] ^= iv2[n]; - /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ - AES_decrypt(tmp, out, key); - /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ - for(n=0 ; n < AES_BLOCK_SIZE ; ++n) - out[n] ^= ivec[n]; - /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ - memcpy(ivec, tmp2, AES_BLOCK_SIZE); - iv2 = out; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; + aes_block_t *ivp = (aes_block_t *)ivec; + aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); + + while (len) + { + aes_block_t tmp; + aes_block_t *inp = (aes_block_t *)in; + aes_block_t *outp = (aes_block_t *)out; + + for(n=0 ; n < N_WORDS; ++n) + tmp.data[n] = inp->data[n] ^ iv2p->data[n]; + AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key); + for(n=0 ; n < N_WORDS; ++n) + outp->data[n] ^= ivp->data[n]; + ivp = inp; + iv2p = outp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } + else + { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) + { + load_block(tmp, in); + tmp2 = tmp; + for(n=0 ; n < N_WORDS; ++n) + tmp.data[n] ^= iv2.data[n]; + AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key); + for(n=0 ; n < N_WORDS; ++n) + tmp.data[n] ^= iv.data[n]; + store_block(out, tmp); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } - memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); } } @@ -177,17 +238,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, iv2 = ivec + AES_BLOCK_SIZE; while (len >= AES_BLOCK_SIZE) { - /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] = in[n] ^ iv[n]; - /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt(out, out, key); - /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv2[n]; - /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy(prev, in, AES_BLOCK_SIZE); iv2 = prev; @@ -203,8 +258,6 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, while(len >= AES_BLOCK_SIZE) { out -= AES_BLOCK_SIZE; - /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ /* XXX: reduce copies by alternating between buffers */ memcpy(tmp, out, AES_BLOCK_SIZE); for(n=0 ; n < AES_BLOCK_SIZE ; ++n) @@ -235,17 +288,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, out -= AES_BLOCK_SIZE; memcpy(tmp, in, AES_BLOCK_SIZE); memcpy(tmp2, in, AES_BLOCK_SIZE); - /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; - /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); - /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; - /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; @@ -260,17 +307,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, { memcpy(tmp, out, AES_BLOCK_SIZE); memcpy(tmp2, out, AES_BLOCK_SIZE); - /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; - /* hexdump(stdout, "out ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); - /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ - /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; - /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; @@ -278,6 +319,5 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } - } } diff --git a/crypto/aes/aes_wrap.c b/crypto/aes/aes_wrap.c new file mode 100644 index 000000000000..9feacd65d8cd --- /dev/null +++ b/crypto/aes/aes_wrap.c @@ -0,0 +1,259 @@ +/* crypto/aes/aes_wrap.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/aes.h> +#include <openssl/bio.h> + +static const unsigned char default_iv[] = { + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, +}; + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) + { + unsigned char *A, B[16], *R; + unsigned int i, j, t; + if ((inlen & 0x7) || (inlen < 8)) + return -1; + A = B; + t = 1; + memcpy(out + 8, in, inlen); + if (!iv) + iv = default_iv; + + memcpy(A, iv, 8); + + for (j = 0; j < 6; j++) + { + R = out + 8; + for (i = 0; i < inlen; i += 8, t++, R += 8) + { + memcpy(B + 8, R, 8); + AES_encrypt(B, B, key); + A[7] ^= (unsigned char)(t & 0xff); + if (t > 0xff) + { + A[6] ^= (unsigned char)((t & 0xff) >> 8); + A[5] ^= (unsigned char)((t & 0xff) >> 16); + A[4] ^= (unsigned char)((t & 0xff) >> 24); + } + memcpy(R, B + 8, 8); + } + } + memcpy(out, A, 8); + return inlen + 8; + } + +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) + { + unsigned char *A, B[16], *R; + unsigned int i, j, t; + inlen -= 8; + if (inlen & 0x7) + return -1; + if (inlen < 8) + return -1; + A = B; + t = 6 * (inlen >> 3); + memcpy(A, in, 8); + memcpy(out, in + 8, inlen); + for (j = 0; j < 6; j++) + { + R = out + inlen - 8; + for (i = 0; i < inlen; i += 8, t--, R -= 8) + { + A[7] ^= (unsigned char)(t & 0xff); + if (t > 0xff) + { + A[6] ^= (unsigned char)((t & 0xff) >> 8); + A[5] ^= (unsigned char)((t & 0xff) >> 16); + A[4] ^= (unsigned char)((t & 0xff) >> 24); + } + memcpy(B + 8, R, 8); + AES_decrypt(B, B, key); + memcpy(R, B + 8, 8); + } + } + if (!iv) + iv = default_iv; + if (memcmp(A, iv, 8)) + { + OPENSSL_cleanse(out, inlen); + return 0; + } + return inlen; + } + +#ifdef AES_WRAP_TEST + +int AES_wrap_unwrap_test(const unsigned char *kek, int keybits, + const unsigned char *iv, + const unsigned char *eout, + const unsigned char *key, int keylen) + { + unsigned char *otmp = NULL, *ptmp = NULL; + int r, ret = 0; + AES_KEY wctx; + otmp = OPENSSL_malloc(keylen + 8); + ptmp = OPENSSL_malloc(keylen); + if (!otmp || !ptmp) + return 0; + if (AES_set_encrypt_key(kek, keybits, &wctx)) + goto err; + r = AES_wrap_key(&wctx, iv, otmp, key, keylen); + if (r <= 0) + goto err; + + if (eout && memcmp(eout, otmp, keylen)) + goto err; + + if (AES_set_decrypt_key(kek, keybits, &wctx)) + goto err; + r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r); + + if (memcmp(key, ptmp, keylen)) + goto err; + + ret = 1; + + err: + if (otmp) + OPENSSL_free(otmp); + if (ptmp) + OPENSSL_free(ptmp); + + return ret; + + } + + + +int main(int argc, char **argv) +{ + +static const unsigned char kek[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f +}; + +static const unsigned char key[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +static const unsigned char e1[] = { + 0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47, + 0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, + 0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5 +}; + +static const unsigned char e2[] = { + 0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35, + 0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2, + 0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d +}; + +static const unsigned char e3[] = { + 0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2, + 0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a, + 0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7 +}; + +static const unsigned char e4[] = { + 0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32, + 0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc, + 0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93, + 0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2 +}; + +static const unsigned char e5[] = { + 0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f, + 0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4, + 0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95, + 0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1 +}; + +static const unsigned char e6[] = { + 0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4, + 0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26, + 0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26, + 0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b, + 0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21 +}; + + AES_KEY wctx, xctx; + int ret; + ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16); + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16); + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16); + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24); + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24); + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32); + fprintf(stderr, "Key test result %d\n", ret); +} + + +#endif diff --git a/crypto/aes/asm/aes-586.pl b/crypto/aes/asm/aes-586.pl index 2774d1cb49c7..89fa2617944b 100755 --- a/crypto/aes/asm/aes-586.pl +++ b/crypto/aes/asm/aes-586.pl @@ -512,11 +512,11 @@ sub declast() if($i==3) { &mov ($key,&DWP(12,"esp")); } else { &mov ($out,$s[0]); } &and ($out,0xFF); - &movz ($out,&DWP(2048,$td,$out,1)); + &movz ($out,&BP(2048,$td,$out,1)); if ($i==3) { $tmp=$s[1]; } &movz ($tmp,&HB($s[1])); - &movz ($tmp,&DWP(2048,$td,$tmp,1)); + &movz ($tmp,&BP(2048,$td,$tmp,1)); &shl ($tmp,8); &xor ($out,$tmp); @@ -524,14 +524,14 @@ sub declast() else { mov ($tmp,$s[2]); } &shr ($tmp,16); &and ($tmp,0xFF); - &movz ($tmp,&DWP(2048,$td,$tmp,1)); + &movz ($tmp,&BP(2048,$td,$tmp,1)); &shl ($tmp,16); &xor ($out,$tmp); if ($i==3) { $tmp=$s[3]; &mov ($s[2],&DWP(8,"esp")); } else { &mov ($tmp,$s[3]); } &shr ($tmp,24); - &movz ($tmp,&DWP(2048,$td,$tmp,1)); + &movz ($tmp,&BP(2048,$td,$tmp,1)); &shl ($tmp,24); &xor ($out,$tmp); if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } @@ -940,7 +940,6 @@ my $mark=&DWP(60+240,"esp"); #copy of aes_key->rounds &cmp ($mark,0); # was the key schedule copied? &mov ("edi",$_key); - &mov ("esp",$_esp); &je (&label("skip_ezero")); # zero copy of key schedule &mov ("ecx",240/4); @@ -948,6 +947,7 @@ my $mark=&DWP(60+240,"esp"); #copy of aes_key->rounds &align (4); &data_word(0xABF3F689); # rep stosd &set_label("skip_ezero") + &mov ("esp",$_esp); &popf (); &set_label("enc_out"); &function_end_A(); @@ -1197,7 +1197,6 @@ my $mark=&DWP(60+240,"esp"); #copy of aes_key->rounds &set_label("dec_out"); &cmp ($mark,0); # was the key schedule copied? &mov ("edi",$_key); - &mov ("esp",$_esp); &je (&label("skip_dzero")); # zero copy of key schedule &mov ("ecx",240/4); @@ -1205,6 +1204,7 @@ my $mark=&DWP(60+240,"esp"); #copy of aes_key->rounds &align (4); &data_word(0xABF3F689); # rep stosd &set_label("skip_dzero") + &mov ("esp",$_esp); &popf (); &function_end("AES_cbc_encrypt"); } diff --git a/crypto/aes/asm/aes-ia64.S b/crypto/aes/asm/aes-ia64.S index 542cf335e995..7f6c4c366291 100644 --- a/crypto/aes/asm/aes-ia64.S +++ b/crypto/aes/asm/aes-ia64.S @@ -17,14 +17,24 @@ // big-endian input, ECB timing on Itanium 2 is (18 + 13*rounds) // ticks per block, or 9.25 CPU cycles per byte for 128 bit key. -.ident "aes-ia64.S, version 1.1" +// Version 1.2 mitigates the hazard of cache-timing attacks by +// a) compressing S-boxes from 8KB to 2KB+256B, b) scheduling +// references to S-boxes for L2 cache latency, c) prefetching T[ed]4 +// prior last round. As result performance dropped to (26 + 15*rounds) +// ticks per block or 11 cycles per byte processed with 128-bit key. +// This is ~16% deterioration. For reference Itanium 2 L1 cache has +// 64 bytes line size and L2 - 128 bytes... + +.ident "aes-ia64.S, version 1.2" .ident "IA-64 ISA artwork by Andy Polyakov <appro@fy.chalmers.se>" .explicit .text rk0=r8; rk1=r9; -prsave=r10; +pfssave=r2; +lcsave=r10; +prsave=r3; maskff=r11; twenty4=r14; sixteen=r15; @@ -44,12 +54,21 @@ te0=r40; te1=r41; te2=r42; te3=r43; #if defined(_HPUX_SOURCE) && !defined(_LP64) # define ADDP addp4 -# define KSZ 4 -# define LDKEY ld4 #else # define ADDP add #endif +// Offsets from Te0 +#define TE0 0 +#define TE2 2 +#if defined(_HPUX_SOURCE) || defined(B_ENDIAN) +#define TE1 3 +#define TE3 1 +#else +#define TE1 1 +#define TE3 3 +#endif + // This implies that AES_KEY comprises 32-bit key schedule elements // even on LP64 platforms. #ifndef KSZ @@ -67,16 +86,19 @@ te0=r40; te1=r41; te2=r42; te3=r43; // Clobber: r16-r31,rk0-rk1,r32-r43 .align 32 _ia64_AES_encrypt: + .prologue + .altrp b6 + .body { .mmi; alloc r16=ar.pfs,12,0,0,8 LDKEY t0=[rk0],2*KSZ mov pr.rot=1<<16 } { .mmi; LDKEY t1=[rk1],2*KSZ - add te1=1024,te0 + add te1=TE1,te0 add te3=-3,te3 };; { .mib; LDKEY t2=[rk0],2*KSZ - mov ar.ec=3 } + mov ar.ec=2 } { .mib; LDKEY t3=[rk1],2*KSZ - add te2=2048,te0 + add te2=TE2,te0 brp.loop.imp .Le_top,.Le_end-16 };; { .mmi; xor s0=s0,t0 @@ -84,8 +106,8 @@ _ia64_AES_encrypt: mov ar.lc=te3 } { .mmi; xor s2=s2,t2 xor s3=s3,t3 - add te3=3072,te0 };; - + add te3=TE3,te0 };; + .align 32 .Le_top: { .mmi; (p0) LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] @@ -95,105 +117,184 @@ _ia64_AES_encrypt: (p0) and te30=s0,maskff // 0/1:s0&0xff (p0) shr.u te00=s0,twenty4 };; // 0/0:s0>>24 { .mmi; (p0) LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] - (p0) shladd te33=te33,2,te3 // 1/0:te0+s0>>24 + (p0) shladd te33=te33,3,te3 // 1/0:te0+s0>>24 (p0) extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff { .mmi; (p0) LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] - (p0) shladd te30=te30,2,te3 // 1/1:te3+s0 + (p0) shladd te30=te30,3,te3 // 1/1:te3+s0 (p0) shr.u te01=s1,twenty4 };; // 1/1:s1>>24 { .mmi; (p0) ld4 te33=[te33] // 2/0:te3[s3&0xff] - (p0) shladd te22=te22,2,te2 // 2/0:te2+s2>>8&0xff + (p0) shladd te22=te22,3,te2 // 2/0:te2+s2>>8&0xff (p0) extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff { .mmi; (p0) ld4 te30=[te30] // 2/1:te3[s0] - (p0) shladd te23=te23,2,te2 // 2/1:te2+s3>>8 + (p0) shladd te23=te23,3,te2 // 2/1:te2+s3>>8 (p0) shr.u te02=s2,twenty4 };; // 2/2:s2>>24 { .mmi; (p0) ld4 te22=[te22] // 3/0:te2[s2>>8] - (p0) shladd te20=te20,2,te2 // 3/2:te2+s0>>8 + (p0) shladd te20=te20,3,te2 // 3/2:te2+s0>>8 (p0) extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff { .mmi; (p0) ld4 te23=[te23] // 3/1:te2[s3>>8] - (p0) shladd te00=te00,2,te0 // 3/0:te0+s0>>24 + (p0) shladd te00=te00,3,te0 // 3/0:te0+s0>>24 (p0) shr.u te03=s3,twenty4 };; // 3/3:s3>>24 { .mmi; (p0) ld4 te20=[te20] // 4/2:te2[s0>>8] - (p0) shladd te21=te21,2,te2 // 4/3:te3+s2 + (p0) shladd te21=te21,3,te2 // 4/3:te3+s2 (p0) extr.u te11=s1,16,8 } // 4/0:s1>>16&0xff { .mmi; (p0) ld4 te00=[te00] // 4/0:te0[s0>>24] - (p0) shladd te01=te01,2,te0 // 4/1:te0+s1>>24 + (p0) shladd te01=te01,3,te0 // 4/1:te0+s1>>24 (p0) shr.u te13=s3,sixteen };; // 4/2:s3>>16 { .mmi; (p0) ld4 te21=[te21] // 5/3:te2[s1>>8] - (p0) shladd te11=te11,2,te1 // 5/0:te1+s1>>16 + (p0) shladd te11=te11,3,te1 // 5/0:te1+s1>>16 (p0) extr.u te12=s2,16,8 } // 5/1:s2>>16&0xff { .mmi; (p0) ld4 te01=[te01] // 5/1:te0[s1>>24] - (p0) shladd te02=te02,2,te0 // 5/2:te0+s2>>24 + (p0) shladd te02=te02,3,te0 // 5/2:te0+s2>>24 (p0) and te31=s1,maskff };; // 5/2:s1&0xff - { .mmi; (p0) ld4 te11=[te11] // 6/0:te1[s1>>16] - (p0) shladd te12=te12,2,te1 // 6/1:te1+s2>>16 + (p0) shladd te12=te12,3,te1 // 6/1:te1+s2>>16 (p0) extr.u te10=s0,16,8 } // 6/3:s0>>16&0xff { .mmi; (p0) ld4 te02=[te02] // 6/2:te0[s2>>24] - (p0) shladd te03=te03,2,te0 // 6/3:te1+s0>>16 + (p0) shladd te03=te03,3,te0 // 6/3:te1+s0>>16 (p0) and te32=s2,maskff };; // 6/3:s2&0xff + { .mmi; (p0) ld4 te12=[te12] // 7/1:te1[s2>>16] - (p0) shladd te31=te31,2,te3 // 7/2:te3+s1&0xff + (p0) shladd te31=te31,3,te3 // 7/2:te3+s1&0xff (p0) and te13=te13,maskff} // 7/2:s3>>16&0xff { .mmi; (p0) ld4 te03=[te03] // 7/3:te0[s3>>24] - (p0) shladd te32=te32,2,te3 // 7/3:te3+s2 + (p0) shladd te32=te32,3,te3 // 7/3:te3+s2 (p0) xor t0=t0,te33 };; // 7/0: { .mmi; (p0) ld4 te31=[te31] // 8/2:te3[s1] - (p0) shladd te13=te13,2,te1 // 8/2:te1+s3>>16 + (p0) shladd te13=te13,3,te1 // 8/2:te1+s3>>16 (p0) xor t0=t0,te22 } // 8/0: { .mmi; (p0) ld4 te32=[te32] // 8/3:te3[s2] - (p0) shladd te10=te10,2,te1 // 8/3:te1+s0>>16 + (p0) shladd te10=te10,3,te1 // 8/3:te1+s0>>16 (p0) xor t1=t1,te30 };; // 8/1: { .mmi; (p0) ld4 te13=[te13] // 9/2:te1[s3>>16] - (p0) xor t0=t0,te00 // 9/0: - (p0) xor t1=t1,te23 } // 9/1: -{ .mmi; (p0) ld4 te10=[te10] // 9/3:te1[s0>>16] - (p0) xor t2=t2,te20 // 9/2: - (p0) xor t3=t3,te21 };; // 9/3: -{ .mmi; (p0) xor t0=t0,te11 // 10/0:done! - (p0) xor t1=t1,te01 // 10/1: - (p0) xor t2=t2,te02 } // 10/2: -{ .mmi; (p0) xor t3=t3,te03 // 10/3: - (p16) cmp.eq p0,p17=r0,r0 };; // 10/clear (p17) -{ .mmi; (p0) xor t1=t1,te12 // 11/1:done! - (p0) xor t2=t2,te31 // 11/2: - (p0) xor t3=t3,te32 } // 11/3: -{ .mmi; (p17) add te0=4096,te0 // 11/ - (p17) add te1=4096,te1 };; // 11/ -{ .mib; (p0) xor t2=t2,te13 // 12/2:done! - (p0) xor t3=t3,te10 } // 12/3:done! -{ .mib; (p17) add te2=4096,te2 // 12/ - (p17) add te3=4096,te3 // 12/ + (p0) ld4 te10=[te10] // 9/3:te1[s0>>16] + (p0) xor t0=t0,te00 };; // 9/0: !L2 scheduling +{ .mmi; (p0) xor t1=t1,te23 // 10[9]/1: + (p0) xor t2=t2,te20 // 10[9]/2: + (p0) xor t3=t3,te21 };; // 10[9]/3: +{ .mmi; (p0) xor t0=t0,te11 // 11[10]/0:done! + (p0) xor t1=t1,te01 // 11[10]/1: + (p0) xor t2=t2,te02 };; // 11[10]/2: !L2 scheduling +{ .mmi; (p0) xor t3=t3,te03 // 12[10]/3: + (p16) cmp.eq p0,p17=r0,r0 };; // 12[10]/clear (p17) +{ .mmi; (p0) xor t1=t1,te12 // 13[11]/1:done! + (p0) xor t2=t2,te31 // 13[11]/2: + (p0) xor t3=t3,te32 } // 13[11]/3: +{ .mmi; (p17) add te0=2048,te0 // 13[11]/ + (p17) add te1=2048+64-TE1,te1};; // 13[11]/ +{ .mib; (p0) xor t2=t2,te13 // 14[12]/2:done! + (p17) add te2=2048+128-TE2,te2} // 14[12]/ +{ .mib; (p0) xor t3=t3,te10 // 14[12]/3:done! + (p17) add te3=2048+192-TE3,te3 // 14[12]/ br.ctop.sptk .Le_top };; .Le_end: -{ .mib; mov r16=s0 - mov r20=s1 } -{ .mib; mov r24=s2 - mov r28=s3 - br.ret.sptk b6 };; + + +{ .mmi; ld8 te12=[te0] // prefetch Te4 + ld8 te31=[te1] } +{ .mmi; ld8 te10=[te2] + ld8 te32=[te3] } + +{ .mmi; LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + and te33=s3,maskff // 0/0:s3&0xff + extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + and te30=s0,maskff // 0/1:s0&0xff + shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + add te33=te33,te0 // 1/0:te0+s0>>24 + extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + add te30=te30,te0 // 1/1:te0+s0 + shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; ld1 te33=[te33] // 2/0:te0[s3&0xff] + add te22=te22,te0 // 2/0:te0+s2>>8&0xff + extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; ld1 te30=[te30] // 2/1:te0[s0] + add te23=te23,te0 // 2/1:te0+s3>>8 + shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; ld1 te22=[te22] // 3/0:te0[s2>>8] + add te20=te20,te0 // 3/2:te0+s0>>8 + extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; ld1 te23=[te23] // 3/1:te0[s3>>8] + add te00=te00,te0 // 3/0:te0+s0>>24 + shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; ld1 te20=[te20] // 4/2:te0[s0>>8] + add te21=te21,te0 // 4/3:te0+s2 + extr.u te11=s1,16,8 } // 4/0:s1>>16&0xff +{ .mmi; ld1 te00=[te00] // 4/0:te0[s0>>24] + add te01=te01,te0 // 4/1:te0+s1>>24 + shr.u te13=s3,sixteen };; // 4/2:s3>>16 +{ .mmi; ld1 te21=[te21] // 5/3:te0[s1>>8] + add te11=te11,te0 // 5/0:te0+s1>>16 + extr.u te12=s2,16,8 } // 5/1:s2>>16&0xff +{ .mmi; ld1 te01=[te01] // 5/1:te0[s1>>24] + add te02=te02,te0 // 5/2:te0+s2>>24 + and te31=s1,maskff };; // 5/2:s1&0xff +{ .mmi; ld1 te11=[te11] // 6/0:te0[s1>>16] + add te12=te12,te0 // 6/1:te0+s2>>16 + extr.u te10=s0,16,8 } // 6/3:s0>>16&0xff +{ .mmi; ld1 te02=[te02] // 6/2:te0[s2>>24] + add te03=te03,te0 // 6/3:te0+s0>>16 + and te32=s2,maskff };; // 6/3:s2&0xff + +{ .mmi; ld1 te12=[te12] // 7/1:te0[s2>>16] + add te31=te31,te0 // 7/2:te0+s1&0xff + dep te33=te22,te33,8,8} // 7/0: +{ .mmi; ld1 te03=[te03] // 7/3:te0[s3>>24] + add te32=te32,te0 // 7/3:te0+s2 + and te13=te13,maskff};; // 7/2:s3>>16&0xff +{ .mmi; ld1 te31=[te31] // 8/2:te0[s1] + add te13=te13,te0 // 8/2:te0+s3>>16 + dep te30=te23,te30,8,8} // 8/1: +{ .mmi; ld1 te32=[te32] // 8/3:te0[s2] + add te10=te10,te0 // 8/3:te0+s0>>16 + shl te00=te00,twenty4};; // 8/0: +{ .mii; ld1 te13=[te13] // 9/2:te0[s3>>16] + dep te33=te11,te33,16,8 // 9/0: + shl te01=te01,twenty4};; // 9/1: +{ .mii; ld1 te10=[te10] // 10/3:te0[s0>>16] + dep te31=te20,te31,8,8 // 10/2: + shl te02=te02,twenty4};; // 10/2: +{ .mii; xor t0=t0,te33 // 11/0: + dep te32=te21,te32,8,8 // 11/3: + shl te12=te12,sixteen};; // 11/1: +{ .mii; xor r16=t0,te00 // 12/0:done! + dep te31=te13,te31,16,8 // 12/2: + shl te03=te03,twenty4};; // 12/3: +{ .mmi; xor t1=t1,te01 // 13/1: + xor t2=t2,te02 // 13/2: + dep te32=te10,te32,16,8};; // 13/3: +{ .mmi; xor t1=t1,te30 // 14/1: + xor r24=t2,te31 // 14/2:done! + xor t3=t3,te32 };; // 14/3: +{ .mib; xor r20=t1,te12 // 15/1:done! + xor r28=t3,te03 // 15/3:done! + br.ret.sptk b6 };; .endp _ia64_AES_encrypt# // void AES_encrypt (const void *in,void *out,const AES_KEY *key); .global AES_encrypt# .proc AES_encrypt# .align 32 -.skip 16 AES_encrypt: .prologue - .fframe 0 - .save ar.pfs,r2 - .save ar.lc,r3 -{ .mmi; alloc r2=ar.pfs,3,0,12,0 - addl out8=@ltoff(AES_Te#),gp - mov r3=ar.lc } -{ .mmi; and out0=3,in0 - ADDP in0=0,in0 + .save ar.pfs,pfssave +{ .mmi; alloc pfssave=ar.pfs,3,1,12,0 + and out0=3,in0 + mov r3=ip } +{ .mmi; ADDP in0=0,in0 + mov loc0=psr.um ADDP out11=KSZ*60,in2 };; // &AES_KEY->rounds - .body -{ .mmi; ld8 out8=[out8] // Te0 - ld4 out11=[out11] // AES_KEY->rounds +{ .mmi; ld4 out11=[out11] // AES_KEY->rounds + add out8=(AES_Te#-AES_encrypt#),r3 // Te0 + .save pr,prsave mov prsave=pr } +{ .mmi; rum 1<<3 // clear um.ac + .save ar.lc,lcsave + mov lcsave=ar.lc };; + .body #if defined(_HPUX_SOURCE) // HPUX is big-endian, cut 15+15 cycles... { .mib; cmp.ne p6,p0=out0,r0 add out0=4,in0 @@ -216,8 +317,9 @@ AES_encrypt: ADDP in1=0,in1 (p6) br.spnt .Le_o_unaligned };; -{ .mii; mov ar.pfs=r2 - mov ar.lc=r3 } +{ .mii; mov psr.um=loc0 + mov ar.pfs=pfssave + mov ar.lc=lcsave };; { .mmi; st4 [in1]=r16,8 // s0 st4 [in0]=r20,8 // s1 mov pr=prsave,0x1ffff };; @@ -278,13 +380,13 @@ AES_encrypt: shr.u r23=r20,twenty4 }//;; // s1 { .mii; ADDP out2=2,in1 extr.u r21=r20,8,8 - shr.u r22=r20,sixteen }//;; + shr.u r22=r20,sixteen }//;; { .mii; ADDP out3=3,in1 extr.u r25=r24,8,8 // s2 shr.u r27=r24,twenty4 };; { .mii; st1 [out3]=r16,4 extr.u r26=r24,16,8 - shr.u r31=r28,twenty4 }//;; // s3 + shr.u r31=r28,twenty4 }//;; // s3 { .mii; st1 [out2]=r17,4 extr.u r29=r28,8,8 shr.u r30=r28,sixteen }//;; @@ -300,12 +402,13 @@ AES_encrypt: mov pr=prsave,0x1ffff }//;; { .mmi; st1 [out1]=r26,4 st1 [out0]=r27,4 - mov ar.pfs=r2 };; + mov ar.pfs=pfssave };; { .mmi; st1 [out3]=r28 st1 [out2]=r29 - mov ar.lc=r3 }//;; -{ .mmb; st1 [out1]=r30 - st1 [out0]=r31 + mov ar.lc=lcsave }//;; +{ .mmi; st1 [out1]=r30 + st1 [out0]=r31 } +{ .mfb; mov psr.um=loc0 // restore user mask br.ret.sptk.many b0 };; .endp AES_encrypt# @@ -360,16 +463,19 @@ while(<>) { // Clobber: r16-r31,rk0-rk1,r32-r43 .align 32 _ia64_AES_decrypt: + .prologue + .altrp b6 + .body { .mmi; alloc r16=ar.pfs,12,0,0,8 LDKEY t0=[rk0],2*KSZ mov pr.rot=1<<16 } { .mmi; LDKEY t1=[rk1],2*KSZ - add te1=1024,te0 + add te1=TE1,te0 add te3=-3,te3 };; { .mib; LDKEY t2=[rk0],2*KSZ - mov ar.ec=3 } + mov ar.ec=2 } { .mib; LDKEY t3=[rk1],2*KSZ - add te2=2048,te0 + add te2=TE2,te0 brp.loop.imp .Ld_top,.Ld_end-16 };; { .mmi; xor s0=s0,t0 @@ -377,8 +483,8 @@ _ia64_AES_decrypt: mov ar.lc=te3 } { .mmi; xor s2=s2,t2 xor s3=s3,t3 - add te3=3072,te0 };; - + add te3=TE3,te0 };; + .align 32 .Ld_top: { .mmi; (p0) LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] @@ -388,105 +494,184 @@ _ia64_AES_decrypt: (p0) and te32=s2,maskff // 0/1:s0&0xff (p0) shr.u te00=s0,twenty4 };; // 0/0:s0>>24 { .mmi; (p0) LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] - (p0) shladd te31=te31,2,te3 // 1/0:te0+s0>>24 + (p0) shladd te31=te31,3,te3 // 1/0:te0+s0>>24 (p0) extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff { .mmi; (p0) LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] - (p0) shladd te32=te32,2,te3 // 1/1:te3+s0 + (p0) shladd te32=te32,3,te3 // 1/1:te3+s0 (p0) shr.u te01=s1,twenty4 };; // 1/1:s1>>24 { .mmi; (p0) ld4 te31=[te31] // 2/0:te3[s3&0xff] - (p0) shladd te22=te22,2,te2 // 2/0:te2+s2>>8&0xff + (p0) shladd te22=te22,3,te2 // 2/0:te2+s2>>8&0xff (p0) extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff { .mmi; (p0) ld4 te32=[te32] // 2/1:te3[s0] - (p0) shladd te23=te23,2,te2 // 2/1:te2+s3>>8 + (p0) shladd te23=te23,3,te2 // 2/1:te2+s3>>8 (p0) shr.u te02=s2,twenty4 };; // 2/2:s2>>24 { .mmi; (p0) ld4 te22=[te22] // 3/0:te2[s2>>8] - (p0) shladd te20=te20,2,te2 // 3/2:te2+s0>>8 + (p0) shladd te20=te20,3,te2 // 3/2:te2+s0>>8 (p0) extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff { .mmi; (p0) ld4 te23=[te23] // 3/1:te2[s3>>8] - (p0) shladd te00=te00,2,te0 // 3/0:te0+s0>>24 + (p0) shladd te00=te00,3,te0 // 3/0:te0+s0>>24 (p0) shr.u te03=s3,twenty4 };; // 3/3:s3>>24 { .mmi; (p0) ld4 te20=[te20] // 4/2:te2[s0>>8] - (p0) shladd te21=te21,2,te2 // 4/3:te3+s2 + (p0) shladd te21=te21,3,te2 // 4/3:te3+s2 (p0) extr.u te13=s3,16,8 } // 4/0:s1>>16&0xff { .mmi; (p0) ld4 te00=[te00] // 4/0:te0[s0>>24] - (p0) shladd te01=te01,2,te0 // 4/1:te0+s1>>24 + (p0) shladd te01=te01,3,te0 // 4/1:te0+s1>>24 (p0) shr.u te11=s1,sixteen };; // 4/2:s3>>16 { .mmi; (p0) ld4 te21=[te21] // 5/3:te2[s1>>8] - (p0) shladd te13=te13,2,te1 // 5/0:te1+s1>>16 + (p0) shladd te13=te13,3,te1 // 5/0:te1+s1>>16 (p0) extr.u te10=s0,16,8 } // 5/1:s2>>16&0xff { .mmi; (p0) ld4 te01=[te01] // 5/1:te0[s1>>24] - (p0) shladd te02=te02,2,te0 // 5/2:te0+s2>>24 + (p0) shladd te02=te02,3,te0 // 5/2:te0+s2>>24 (p0) and te33=s3,maskff };; // 5/2:s1&0xff - { .mmi; (p0) ld4 te13=[te13] // 6/0:te1[s1>>16] - (p0) shladd te10=te10,2,te1 // 6/1:te1+s2>>16 + (p0) shladd te10=te10,3,te1 // 6/1:te1+s2>>16 (p0) extr.u te12=s2,16,8 } // 6/3:s0>>16&0xff { .mmi; (p0) ld4 te02=[te02] // 6/2:te0[s2>>24] - (p0) shladd te03=te03,2,te0 // 6/3:te1+s0>>16 + (p0) shladd te03=te03,3,te0 // 6/3:te1+s0>>16 (p0) and te30=s0,maskff };; // 6/3:s2&0xff + { .mmi; (p0) ld4 te10=[te10] // 7/1:te1[s2>>16] - (p0) shladd te33=te33,2,te3 // 7/2:te3+s1&0xff + (p0) shladd te33=te33,3,te3 // 7/2:te3+s1&0xff (p0) and te11=te11,maskff} // 7/2:s3>>16&0xff { .mmi; (p0) ld4 te03=[te03] // 7/3:te0[s3>>24] - (p0) shladd te30=te30,2,te3 // 7/3:te3+s2 + (p0) shladd te30=te30,3,te3 // 7/3:te3+s2 (p0) xor t0=t0,te31 };; // 7/0: { .mmi; (p0) ld4 te33=[te33] // 8/2:te3[s1] - (p0) shladd te11=te11,2,te1 // 8/2:te1+s3>>16 + (p0) shladd te11=te11,3,te1 // 8/2:te1+s3>>16 (p0) xor t0=t0,te22 } // 8/0: { .mmi; (p0) ld4 te30=[te30] // 8/3:te3[s2] - (p0) shladd te12=te12,2,te1 // 8/3:te1+s0>>16 + (p0) shladd te12=te12,3,te1 // 8/3:te1+s0>>16 (p0) xor t1=t1,te32 };; // 8/1: { .mmi; (p0) ld4 te11=[te11] // 9/2:te1[s3>>16] - (p0) xor t0=t0,te00 // 9/0: - (p0) xor t1=t1,te23 } // 9/1: -{ .mmi; (p0) ld4 te12=[te12] // 9/3:te1[s0>>16] - (p0) xor t2=t2,te20 // 9/2: - (p0) xor t3=t3,te21 };; // 9/3: -{ .mmi; (p0) xor t0=t0,te13 // 10/0:done! - (p0) xor t1=t1,te01 // 10/1: - (p0) xor t2=t2,te02 } // 10/2: -{ .mmi; (p0) xor t3=t3,te03 // 10/3: - (p16) cmp.eq p0,p17=r0,r0 };; // 10/clear (p17) -{ .mmi; (p0) xor t1=t1,te10 // 11/1:done! - (p0) xor t2=t2,te33 // 11/2: - (p0) xor t3=t3,te30 } // 11/3: -{ .mmi; (p17) add te0=4096,te0 // 11/ - (p17) add te1=4096,te1 };; // 11/ -{ .mib; (p0) xor t2=t2,te11 // 12/2:done! - (p0) xor t3=t3,te12 } // 12/3:done! -{ .mib; (p17) add te2=4096,te2 // 12/ - (p17) add te3=4096,te3 // 12/ + (p0) ld4 te12=[te12] // 9/3:te1[s0>>16] + (p0) xor t0=t0,te00 };; // 9/0: !L2 scheduling +{ .mmi; (p0) xor t1=t1,te23 // 10[9]/1: + (p0) xor t2=t2,te20 // 10[9]/2: + (p0) xor t3=t3,te21 };; // 10[9]/3: +{ .mmi; (p0) xor t0=t0,te13 // 11[10]/0:done! + (p0) xor t1=t1,te01 // 11[10]/1: + (p0) xor t2=t2,te02 };; // 11[10]/2: !L2 scheduling +{ .mmi; (p0) xor t3=t3,te03 // 12[10]/3: + (p16) cmp.eq p0,p17=r0,r0 };; // 12[10]/clear (p17) +{ .mmi; (p0) xor t1=t1,te10 // 13[11]/1:done! + (p0) xor t2=t2,te33 // 13[11]/2: + (p0) xor t3=t3,te30 } // 13[11]/3: +{ .mmi; (p17) add te0=2048,te0 // 13[11]/ + (p17) add te1=2048+64-TE1,te1};; // 13[11]/ +{ .mib; (p0) xor t2=t2,te11 // 14[12]/2:done! + (p17) add te2=2048+128-TE2,te2} // 14[12]/ +{ .mib; (p0) xor t3=t3,te12 // 14[12]/3:done! + (p17) add te3=2048+192-TE3,te3 // 14[12]/ br.ctop.sptk .Ld_top };; .Ld_end: -{ .mib; mov r16=s0 - mov r20=s1 } -{ .mib; mov r24=s2 - mov r28=s3 - br.ret.sptk b6 };; + + +{ .mmi; ld8 te10=[te0] // prefetch Td4 + ld8 te33=[te1] } +{ .mmi; ld8 te12=[te2] + ld8 te30=[te3] } + +{ .mmi; LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + and te31=s1,maskff // 0/0:s3&0xff + extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + and te32=s2,maskff // 0/1:s0&0xff + shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + add te31=te31,te0 // 1/0:te0+s0>>24 + extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + add te32=te32,te0 // 1/1:te0+s0 + shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; ld1 te31=[te31] // 2/0:te0[s3&0xff] + add te22=te22,te0 // 2/0:te0+s2>>8&0xff + extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; ld1 te32=[te32] // 2/1:te0[s0] + add te23=te23,te0 // 2/1:te0+s3>>8 + shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; ld1 te22=[te22] // 3/0:te0[s2>>8] + add te20=te20,te0 // 3/2:te0+s0>>8 + extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; ld1 te23=[te23] // 3/1:te0[s3>>8] + add te00=te00,te0 // 3/0:te0+s0>>24 + shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; ld1 te20=[te20] // 4/2:te0[s0>>8] + add te21=te21,te0 // 4/3:te0+s2 + extr.u te13=s3,16,8 } // 4/0:s1>>16&0xff +{ .mmi; ld1 te00=[te00] // 4/0:te0[s0>>24] + add te01=te01,te0 // 4/1:te0+s1>>24 + shr.u te11=s1,sixteen };; // 4/2:s3>>16 +{ .mmi; ld1 te21=[te21] // 5/3:te0[s1>>8] + add te13=te13,te0 // 5/0:te0+s1>>16 + extr.u te10=s0,16,8 } // 5/1:s2>>16&0xff +{ .mmi; ld1 te01=[te01] // 5/1:te0[s1>>24] + add te02=te02,te0 // 5/2:te0+s2>>24 + and te33=s3,maskff };; // 5/2:s1&0xff +{ .mmi; ld1 te13=[te13] // 6/0:te0[s1>>16] + add te10=te10,te0 // 6/1:te0+s2>>16 + extr.u te12=s2,16,8 } // 6/3:s0>>16&0xff +{ .mmi; ld1 te02=[te02] // 6/2:te0[s2>>24] + add te03=te03,te0 // 6/3:te0+s0>>16 + and te30=s0,maskff };; // 6/3:s2&0xff + +{ .mmi; ld1 te10=[te10] // 7/1:te0[s2>>16] + add te33=te33,te0 // 7/2:te0+s1&0xff + dep te31=te22,te31,8,8} // 7/0: +{ .mmi; ld1 te03=[te03] // 7/3:te0[s3>>24] + add te30=te30,te0 // 7/3:te0+s2 + and te11=te11,maskff};; // 7/2:s3>>16&0xff +{ .mmi; ld1 te33=[te33] // 8/2:te0[s1] + add te11=te11,te0 // 8/2:te0+s3>>16 + dep te32=te23,te32,8,8} // 8/1: +{ .mmi; ld1 te30=[te30] // 8/3:te0[s2] + add te12=te12,te0 // 8/3:te0+s0>>16 + shl te00=te00,twenty4};; // 8/0: +{ .mii; ld1 te11=[te11] // 9/2:te0[s3>>16] + dep te31=te13,te31,16,8 // 9/0: + shl te01=te01,twenty4};; // 9/1: +{ .mii; ld1 te12=[te12] // 10/3:te0[s0>>16] + dep te33=te20,te33,8,8 // 10/2: + shl te02=te02,twenty4};; // 10/2: +{ .mii; xor t0=t0,te31 // 11/0: + dep te30=te21,te30,8,8 // 11/3: + shl te10=te10,sixteen};; // 11/1: +{ .mii; xor r16=t0,te00 // 12/0:done! + dep te33=te11,te33,16,8 // 12/2: + shl te03=te03,twenty4};; // 12/3: +{ .mmi; xor t1=t1,te01 // 13/1: + xor t2=t2,te02 // 13/2: + dep te30=te12,te30,16,8};; // 13/3: +{ .mmi; xor t1=t1,te32 // 14/1: + xor r24=t2,te33 // 14/2:done! + xor t3=t3,te30 };; // 14/3: +{ .mib; xor r20=t1,te10 // 15/1:done! + xor r28=t3,te03 // 15/3:done! + br.ret.sptk b6 };; .endp _ia64_AES_decrypt# // void AES_decrypt (const void *in,void *out,const AES_KEY *key); .global AES_decrypt# .proc AES_decrypt# .align 32 -.skip 16 AES_decrypt: .prologue - .fframe 0 - .save ar.pfs,r2 - .save ar.lc,r3 -{ .mmi; alloc r2=ar.pfs,3,0,12,0 - addl out8=@ltoff(AES_Td#),gp - mov r3=ar.lc } -{ .mmi; and out0=3,in0 - ADDP in0=0,in0 + .save ar.pfs,pfssave +{ .mmi; alloc pfssave=ar.pfs,3,1,12,0 + and out0=3,in0 + mov r3=ip } +{ .mmi; ADDP in0=0,in0 + mov loc0=psr.um ADDP out11=KSZ*60,in2 };; // &AES_KEY->rounds - .body -{ .mmi; ld8 out8=[out8] // Te0 - ld4 out11=[out11] // AES_KEY->rounds +{ .mmi; ld4 out11=[out11] // AES_KEY->rounds + add out8=(AES_Td#-AES_decrypt#),r3 // Te0 + .save pr,prsave mov prsave=pr } +{ .mmi; rum 1<<3 // clear um.ac + .save ar.lc,lcsave + mov lcsave=ar.lc };; + .body #if defined(_HPUX_SOURCE) // HPUX is big-endian, cut 15+15 cycles... { .mib; cmp.ne p6,p0=out0,r0 add out0=4,in0 @@ -509,8 +694,9 @@ AES_decrypt: ADDP in1=0,in1 (p6) br.spnt .Ld_o_unaligned };; -{ .mii; mov ar.pfs=r2 - mov ar.lc=r3 } +{ .mii; mov psr.um=loc0 + mov ar.pfs=pfssave + mov ar.lc=lcsave };; { .mmi; st4 [in1]=r16,8 // s0 st4 [in0]=r20,8 // s1 mov pr=prsave,0x1ffff };; @@ -571,13 +757,13 @@ AES_decrypt: shr.u r23=r20,twenty4 }//;; // s1 { .mii; ADDP out2=2,in1 extr.u r21=r20,8,8 - shr.u r22=r20,sixteen }//;; + shr.u r22=r20,sixteen }//;; { .mii; ADDP out3=3,in1 extr.u r25=r24,8,8 // s2 shr.u r27=r24,twenty4 };; { .mii; st1 [out3]=r16,4 extr.u r26=r24,16,8 - shr.u r31=r28,twenty4 }//;; // s3 + shr.u r31=r28,twenty4 }//;; // s3 { .mii; st1 [out2]=r17,4 extr.u r29=r28,8,8 shr.u r30=r28,sixteen }//;; @@ -593,12 +779,13 @@ AES_decrypt: mov pr=prsave,0x1ffff }//;; { .mmi; st1 [out1]=r26,4 st1 [out0]=r27,4 - mov ar.pfs=r2 };; + mov ar.pfs=pfssave };; { .mmi; st1 [out3]=r28 st1 [out2]=r29 - mov ar.lc=r3 }//;; -{ .mmb; st1 [out1]=r30 - st1 [out0]=r31 + mov ar.lc=lcsave }//;; +{ .mmi; st1 [out1]=r30 + st1 [out0]=r31 } +{ .mfb; mov psr.um=loc0 // restore user mask br.ret.sptk.many b0 };; .endp AES_decrypt# @@ -606,1047 +793,331 @@ AES_decrypt: .align 64 .global AES_Te# .type AES_Te#,@object -AES_Te: data4 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d - data4 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 - data4 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d - data4 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a - data4 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 - data4 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b - data4 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea - data4 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b - data4 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a - data4 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f - data4 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 - data4 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f - data4 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e - data4 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 - data4 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d - data4 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f - data4 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e - data4 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb - data4 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce - data4 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 - data4 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c - data4 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed - data4 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b - data4 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a - data4 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 - data4 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 - data4 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 - data4 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 - data4 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a - data4 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 - data4 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 - data4 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d - data4 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f - data4 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 - data4 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 - data4 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 - data4 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f - data4 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 - data4 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c - data4 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 - data4 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e - data4 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 - data4 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 - data4 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b - data4 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 - data4 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 - data4 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 - data4 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 - data4 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 - data4 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 - data4 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 - data4 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 - data4 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa - data4 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 - data4 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 - data4 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 - data4 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 - data4 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 - data4 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 - data4 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a - data4 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 - data4 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 - data4 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 - data4 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a -// Te1: - data4 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b - data4 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5 - data4 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b - data4 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676 - data4 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d - data4 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0 - data4 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf - data4 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0 - data4 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626 - data4 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc - data4 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1 - data4 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515 - data4 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3 - data4 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a - data4 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2 - data4 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575 - data4 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a - data4 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0 - data4 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3 - data4 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484 - data4 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded - data4 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b - data4 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939 - data4 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf - data4 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb - data4 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585 - data4 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f - data4 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8 - data4 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f - data4 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5 - data4 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121 - data4 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2 - data4 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec - data4 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717 - data4 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d - data4 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373 - data4 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc - data4 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888 - data4 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414 - data4 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb - data4 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a - data4 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c - data4 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262 - data4 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979 - data4 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d - data4 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9 - data4 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea - data4 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808 - data4 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e - data4 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6 - data4 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f - data4 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a - data4 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666 - data4 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e - data4 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9 - data4 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e - data4 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111 - data4 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494 - data4 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9 - data4 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf - data4 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d - data4 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868 - data4 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f - data4 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616 -// Te2: - data4 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b - data4 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5 - data4 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b - data4 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76 - data4 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d - data4 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0 - data4 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af - data4 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0 - data4 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26 - data4 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc - data4 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1 - data4 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15 - data4 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3 - data4 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a - data4 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2 - data4 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75 - data4 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a - data4 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0 - data4 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3 - data4 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384 - data4 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed - data4 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b - data4 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239 - data4 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf - data4 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb - data4 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185 - data4 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f - data4 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8 - data4 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f - data4 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5 - data4 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221 - data4 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2 - data4 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec - data4 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17 - data4 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d - data4 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673 - data4 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc - data4 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88 - data4 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814 - data4 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb - data4 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a - data4 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c - data4 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462 - data4 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279 - data4 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d - data4 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9 - data4 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea - data4 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008 - data4 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e - data4 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6 - data4 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f - data4 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a - data4 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66 - data4 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e - data4 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9 - data4 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e - data4 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211 - data4 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394 - data4 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9 - data4 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df - data4 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d - data4 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068 - data4 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f - data4 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16 -// Te3: - data4 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6 - data4 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491 - data4 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56 - data4 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec - data4 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa - data4 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb - data4 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45 - data4 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b - data4 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c - data4 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83 - data4 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9 - data4 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a - data4 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d - data4 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f - data4 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf - data4 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea - data4 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34 - data4 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b - data4 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d - data4 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713 - data4 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1 - data4 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6 - data4 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72 - data4 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85 - data4 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed - data4 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411 - data4 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe - data4 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b - data4 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05 - data4 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1 - data4 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342 - data4 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf - data4 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3 - data4 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e - data4 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a - data4 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6 - data4 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3 - data4 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b - data4 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28 - data4 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad - data4 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14 - data4 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8 - data4 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4 - data4 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2 - data4 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da - data4 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049 - data4 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf - data4 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810 - data4 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c - data4 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197 - data4 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e - data4 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f - data4 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc - data4 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c - data4 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069 - data4 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927 - data4 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322 - data4 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733 - data4 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9 - data4 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5 - data4 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a - data4 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0 - data4 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e - data4 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c +AES_Te: data4 0xc66363a5,0xc66363a5, 0xf87c7c84,0xf87c7c84 + data4 0xee777799,0xee777799, 0xf67b7b8d,0xf67b7b8d + data4 0xfff2f20d,0xfff2f20d, 0xd66b6bbd,0xd66b6bbd + data4 0xde6f6fb1,0xde6f6fb1, 0x91c5c554,0x91c5c554 + data4 0x60303050,0x60303050, 0x02010103,0x02010103 + data4 0xce6767a9,0xce6767a9, 0x562b2b7d,0x562b2b7d + data4 0xe7fefe19,0xe7fefe19, 0xb5d7d762,0xb5d7d762 + data4 0x4dababe6,0x4dababe6, 0xec76769a,0xec76769a + data4 0x8fcaca45,0x8fcaca45, 0x1f82829d,0x1f82829d + data4 0x89c9c940,0x89c9c940, 0xfa7d7d87,0xfa7d7d87 + data4 0xeffafa15,0xeffafa15, 0xb25959eb,0xb25959eb + data4 0x8e4747c9,0x8e4747c9, 0xfbf0f00b,0xfbf0f00b + data4 0x41adadec,0x41adadec, 0xb3d4d467,0xb3d4d467 + data4 0x5fa2a2fd,0x5fa2a2fd, 0x45afafea,0x45afafea + data4 0x239c9cbf,0x239c9cbf, 0x53a4a4f7,0x53a4a4f7 + data4 0xe4727296,0xe4727296, 0x9bc0c05b,0x9bc0c05b + data4 0x75b7b7c2,0x75b7b7c2, 0xe1fdfd1c,0xe1fdfd1c + data4 0x3d9393ae,0x3d9393ae, 0x4c26266a,0x4c26266a + data4 0x6c36365a,0x6c36365a, 0x7e3f3f41,0x7e3f3f41 + data4 0xf5f7f702,0xf5f7f702, 0x83cccc4f,0x83cccc4f + data4 0x6834345c,0x6834345c, 0x51a5a5f4,0x51a5a5f4 + data4 0xd1e5e534,0xd1e5e534, 0xf9f1f108,0xf9f1f108 + data4 0xe2717193,0xe2717193, 0xabd8d873,0xabd8d873 + data4 0x62313153,0x62313153, 0x2a15153f,0x2a15153f + data4 0x0804040c,0x0804040c, 0x95c7c752,0x95c7c752 + data4 0x46232365,0x46232365, 0x9dc3c35e,0x9dc3c35e + data4 0x30181828,0x30181828, 0x379696a1,0x379696a1 + data4 0x0a05050f,0x0a05050f, 0x2f9a9ab5,0x2f9a9ab5 + data4 0x0e070709,0x0e070709, 0x24121236,0x24121236 + data4 0x1b80809b,0x1b80809b, 0xdfe2e23d,0xdfe2e23d + data4 0xcdebeb26,0xcdebeb26, 0x4e272769,0x4e272769 + data4 0x7fb2b2cd,0x7fb2b2cd, 0xea75759f,0xea75759f + data4 0x1209091b,0x1209091b, 0x1d83839e,0x1d83839e + data4 0x582c2c74,0x582c2c74, 0x341a1a2e,0x341a1a2e + data4 0x361b1b2d,0x361b1b2d, 0xdc6e6eb2,0xdc6e6eb2 + data4 0xb45a5aee,0xb45a5aee, 0x5ba0a0fb,0x5ba0a0fb + data4 0xa45252f6,0xa45252f6, 0x763b3b4d,0x763b3b4d + data4 0xb7d6d661,0xb7d6d661, 0x7db3b3ce,0x7db3b3ce + data4 0x5229297b,0x5229297b, 0xdde3e33e,0xdde3e33e + data4 0x5e2f2f71,0x5e2f2f71, 0x13848497,0x13848497 + data4 0xa65353f5,0xa65353f5, 0xb9d1d168,0xb9d1d168 + data4 0x00000000,0x00000000, 0xc1eded2c,0xc1eded2c + data4 0x40202060,0x40202060, 0xe3fcfc1f,0xe3fcfc1f + data4 0x79b1b1c8,0x79b1b1c8, 0xb65b5bed,0xb65b5bed + data4 0xd46a6abe,0xd46a6abe, 0x8dcbcb46,0x8dcbcb46 + data4 0x67bebed9,0x67bebed9, 0x7239394b,0x7239394b + data4 0x944a4ade,0x944a4ade, 0x984c4cd4,0x984c4cd4 + data4 0xb05858e8,0xb05858e8, 0x85cfcf4a,0x85cfcf4a + data4 0xbbd0d06b,0xbbd0d06b, 0xc5efef2a,0xc5efef2a + data4 0x4faaaae5,0x4faaaae5, 0xedfbfb16,0xedfbfb16 + data4 0x864343c5,0x864343c5, 0x9a4d4dd7,0x9a4d4dd7 + data4 0x66333355,0x66333355, 0x11858594,0x11858594 + data4 0x8a4545cf,0x8a4545cf, 0xe9f9f910,0xe9f9f910 + data4 0x04020206,0x04020206, 0xfe7f7f81,0xfe7f7f81 + data4 0xa05050f0,0xa05050f0, 0x783c3c44,0x783c3c44 + data4 0x259f9fba,0x259f9fba, 0x4ba8a8e3,0x4ba8a8e3 + data4 0xa25151f3,0xa25151f3, 0x5da3a3fe,0x5da3a3fe + data4 0x804040c0,0x804040c0, 0x058f8f8a,0x058f8f8a + data4 0x3f9292ad,0x3f9292ad, 0x219d9dbc,0x219d9dbc + data4 0x70383848,0x70383848, 0xf1f5f504,0xf1f5f504 + data4 0x63bcbcdf,0x63bcbcdf, 0x77b6b6c1,0x77b6b6c1 + data4 0xafdada75,0xafdada75, 0x42212163,0x42212163 + data4 0x20101030,0x20101030, 0xe5ffff1a,0xe5ffff1a + data4 0xfdf3f30e,0xfdf3f30e, 0xbfd2d26d,0xbfd2d26d + data4 0x81cdcd4c,0x81cdcd4c, 0x180c0c14,0x180c0c14 + data4 0x26131335,0x26131335, 0xc3ecec2f,0xc3ecec2f + data4 0xbe5f5fe1,0xbe5f5fe1, 0x359797a2,0x359797a2 + data4 0x884444cc,0x884444cc, 0x2e171739,0x2e171739 + data4 0x93c4c457,0x93c4c457, 0x55a7a7f2,0x55a7a7f2 + data4 0xfc7e7e82,0xfc7e7e82, 0x7a3d3d47,0x7a3d3d47 + data4 0xc86464ac,0xc86464ac, 0xba5d5de7,0xba5d5de7 + data4 0x3219192b,0x3219192b, 0xe6737395,0xe6737395 + data4 0xc06060a0,0xc06060a0, 0x19818198,0x19818198 + data4 0x9e4f4fd1,0x9e4f4fd1, 0xa3dcdc7f,0xa3dcdc7f + data4 0x44222266,0x44222266, 0x542a2a7e,0x542a2a7e + data4 0x3b9090ab,0x3b9090ab, 0x0b888883,0x0b888883 + data4 0x8c4646ca,0x8c4646ca, 0xc7eeee29,0xc7eeee29 + data4 0x6bb8b8d3,0x6bb8b8d3, 0x2814143c,0x2814143c + data4 0xa7dede79,0xa7dede79, 0xbc5e5ee2,0xbc5e5ee2 + data4 0x160b0b1d,0x160b0b1d, 0xaddbdb76,0xaddbdb76 + data4 0xdbe0e03b,0xdbe0e03b, 0x64323256,0x64323256 + data4 0x743a3a4e,0x743a3a4e, 0x140a0a1e,0x140a0a1e + data4 0x924949db,0x924949db, 0x0c06060a,0x0c06060a + data4 0x4824246c,0x4824246c, 0xb85c5ce4,0xb85c5ce4 + data4 0x9fc2c25d,0x9fc2c25d, 0xbdd3d36e,0xbdd3d36e + data4 0x43acacef,0x43acacef, 0xc46262a6,0xc46262a6 + data4 0x399191a8,0x399191a8, 0x319595a4,0x319595a4 + data4 0xd3e4e437,0xd3e4e437, 0xf279798b,0xf279798b + data4 0xd5e7e732,0xd5e7e732, 0x8bc8c843,0x8bc8c843 + data4 0x6e373759,0x6e373759, 0xda6d6db7,0xda6d6db7 + data4 0x018d8d8c,0x018d8d8c, 0xb1d5d564,0xb1d5d564 + data4 0x9c4e4ed2,0x9c4e4ed2, 0x49a9a9e0,0x49a9a9e0 + data4 0xd86c6cb4,0xd86c6cb4, 0xac5656fa,0xac5656fa + data4 0xf3f4f407,0xf3f4f407, 0xcfeaea25,0xcfeaea25 + data4 0xca6565af,0xca6565af, 0xf47a7a8e,0xf47a7a8e + data4 0x47aeaee9,0x47aeaee9, 0x10080818,0x10080818 + data4 0x6fbabad5,0x6fbabad5, 0xf0787888,0xf0787888 + data4 0x4a25256f,0x4a25256f, 0x5c2e2e72,0x5c2e2e72 + data4 0x381c1c24,0x381c1c24, 0x57a6a6f1,0x57a6a6f1 + data4 0x73b4b4c7,0x73b4b4c7, 0x97c6c651,0x97c6c651 + data4 0xcbe8e823,0xcbe8e823, 0xa1dddd7c,0xa1dddd7c + data4 0xe874749c,0xe874749c, 0x3e1f1f21,0x3e1f1f21 + data4 0x964b4bdd,0x964b4bdd, 0x61bdbddc,0x61bdbddc + data4 0x0d8b8b86,0x0d8b8b86, 0x0f8a8a85,0x0f8a8a85 + data4 0xe0707090,0xe0707090, 0x7c3e3e42,0x7c3e3e42 + data4 0x71b5b5c4,0x71b5b5c4, 0xcc6666aa,0xcc6666aa + data4 0x904848d8,0x904848d8, 0x06030305,0x06030305 + data4 0xf7f6f601,0xf7f6f601, 0x1c0e0e12,0x1c0e0e12 + data4 0xc26161a3,0xc26161a3, 0x6a35355f,0x6a35355f + data4 0xae5757f9,0xae5757f9, 0x69b9b9d0,0x69b9b9d0 + data4 0x17868691,0x17868691, 0x99c1c158,0x99c1c158 + data4 0x3a1d1d27,0x3a1d1d27, 0x279e9eb9,0x279e9eb9 + data4 0xd9e1e138,0xd9e1e138, 0xebf8f813,0xebf8f813 + data4 0x2b9898b3,0x2b9898b3, 0x22111133,0x22111133 + data4 0xd26969bb,0xd26969bb, 0xa9d9d970,0xa9d9d970 + data4 0x078e8e89,0x078e8e89, 0x339494a7,0x339494a7 + data4 0x2d9b9bb6,0x2d9b9bb6, 0x3c1e1e22,0x3c1e1e22 + data4 0x15878792,0x15878792, 0xc9e9e920,0xc9e9e920 + data4 0x87cece49,0x87cece49, 0xaa5555ff,0xaa5555ff + data4 0x50282878,0x50282878, 0xa5dfdf7a,0xa5dfdf7a + data4 0x038c8c8f,0x038c8c8f, 0x59a1a1f8,0x59a1a1f8 + data4 0x09898980,0x09898980, 0x1a0d0d17,0x1a0d0d17 + data4 0x65bfbfda,0x65bfbfda, 0xd7e6e631,0xd7e6e631 + data4 0x844242c6,0x844242c6, 0xd06868b8,0xd06868b8 + data4 0x824141c3,0x824141c3, 0x299999b0,0x299999b0 + data4 0x5a2d2d77,0x5a2d2d77, 0x1e0f0f11,0x1e0f0f11 + data4 0x7bb0b0cb,0x7bb0b0cb, 0xa85454fc,0xa85454fc + data4 0x6dbbbbd6,0x6dbbbbd6, 0x2c16163a,0x2c16163a // Te4: - data4 0x63000000, 0x7c000000, 0x77000000, 0x7b000000 - data4 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000 - data4 0x30000000, 0x01000000, 0x67000000, 0x2b000000 - data4 0xfe000000, 0xd7000000, 0xab000000, 0x76000000 - data4 0xca000000, 0x82000000, 0xc9000000, 0x7d000000 - data4 0xfa000000, 0x59000000, 0x47000000, 0xf0000000 - data4 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000 - data4 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000 - data4 0xb7000000, 0xfd000000, 0x93000000, 0x26000000 - data4 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000 - data4 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000 - data4 0x71000000, 0xd8000000, 0x31000000, 0x15000000 - data4 0x04000000, 0xc7000000, 0x23000000, 0xc3000000 - data4 0x18000000, 0x96000000, 0x05000000, 0x9a000000 - data4 0x07000000, 0x12000000, 0x80000000, 0xe2000000 - data4 0xeb000000, 0x27000000, 0xb2000000, 0x75000000 - data4 0x09000000, 0x83000000, 0x2c000000, 0x1a000000 - data4 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000 - data4 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000 - data4 0x29000000, 0xe3000000, 0x2f000000, 0x84000000 - data4 0x53000000, 0xd1000000, 0x00000000, 0xed000000 - data4 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000 - data4 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000 - data4 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000 - data4 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000 - data4 0x43000000, 0x4d000000, 0x33000000, 0x85000000 - data4 0x45000000, 0xf9000000, 0x02000000, 0x7f000000 - data4 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000 - data4 0x51000000, 0xa3000000, 0x40000000, 0x8f000000 - data4 0x92000000, 0x9d000000, 0x38000000, 0xf5000000 - data4 0xbc000000, 0xb6000000, 0xda000000, 0x21000000 - data4 0x10000000, 0xff000000, 0xf3000000, 0xd2000000 - data4 0xcd000000, 0x0c000000, 0x13000000, 0xec000000 - data4 0x5f000000, 0x97000000, 0x44000000, 0x17000000 - data4 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000 - data4 0x64000000, 0x5d000000, 0x19000000, 0x73000000 - data4 0x60000000, 0x81000000, 0x4f000000, 0xdc000000 - data4 0x22000000, 0x2a000000, 0x90000000, 0x88000000 - data4 0x46000000, 0xee000000, 0xb8000000, 0x14000000 - data4 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000 - data4 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000 - data4 0x49000000, 0x06000000, 0x24000000, 0x5c000000 - data4 0xc2000000, 0xd3000000, 0xac000000, 0x62000000 - data4 0x91000000, 0x95000000, 0xe4000000, 0x79000000 - data4 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000 - data4 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000 - data4 0x6c000000, 0x56000000, 0xf4000000, 0xea000000 - data4 0x65000000, 0x7a000000, 0xae000000, 0x08000000 - data4 0xba000000, 0x78000000, 0x25000000, 0x2e000000 - data4 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000 - data4 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000 - data4 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000 - data4 0x70000000, 0x3e000000, 0xb5000000, 0x66000000 - data4 0x48000000, 0x03000000, 0xf6000000, 0x0e000000 - data4 0x61000000, 0x35000000, 0x57000000, 0xb9000000 - data4 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000 - data4 0xe1000000, 0xf8000000, 0x98000000, 0x11000000 - data4 0x69000000, 0xd9000000, 0x8e000000, 0x94000000 - data4 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000 - data4 0xce000000, 0x55000000, 0x28000000, 0xdf000000 - data4 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000 - data4 0xbf000000, 0xe6000000, 0x42000000, 0x68000000 - data4 0x41000000, 0x99000000, 0x2d000000, 0x0f000000 - data4 0xb0000000, 0x54000000, 0xbb000000, 0x16000000 -// Te5: - data4 0x00630000, 0x007c0000, 0x00770000, 0x007b0000 - data4 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000 - data4 0x00300000, 0x00010000, 0x00670000, 0x002b0000 - data4 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000 - data4 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000 - data4 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000 - data4 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000 - data4 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000 - data4 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000 - data4 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000 - data4 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000 - data4 0x00710000, 0x00d80000, 0x00310000, 0x00150000 - data4 0x00040000, 0x00c70000, 0x00230000, 0x00c30000 - data4 0x00180000, 0x00960000, 0x00050000, 0x009a0000 - data4 0x00070000, 0x00120000, 0x00800000, 0x00e20000 - data4 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000 - data4 0x00090000, 0x00830000, 0x002c0000, 0x001a0000 - data4 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000 - data4 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000 - data4 0x00290000, 0x00e30000, 0x002f0000, 0x00840000 - data4 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000 - data4 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000 - data4 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000 - data4 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000 - data4 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000 - data4 0x00430000, 0x004d0000, 0x00330000, 0x00850000 - data4 0x00450000, 0x00f90000, 0x00020000, 0x007f0000 - data4 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000 - data4 0x00510000, 0x00a30000, 0x00400000, 0x008f0000 - data4 0x00920000, 0x009d0000, 0x00380000, 0x00f50000 - data4 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000 - data4 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000 - data4 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000 - data4 0x005f0000, 0x00970000, 0x00440000, 0x00170000 - data4 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000 - data4 0x00640000, 0x005d0000, 0x00190000, 0x00730000 - data4 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000 - data4 0x00220000, 0x002a0000, 0x00900000, 0x00880000 - data4 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000 - data4 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000 - data4 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000 - data4 0x00490000, 0x00060000, 0x00240000, 0x005c0000 - data4 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000 - data4 0x00910000, 0x00950000, 0x00e40000, 0x00790000 - data4 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000 - data4 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000 - data4 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000 - data4 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000 - data4 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000 - data4 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000 - data4 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000 - data4 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000 - data4 0x00700000, 0x003e0000, 0x00b50000, 0x00660000 - data4 0x00480000, 0x00030000, 0x00f60000, 0x000e0000 - data4 0x00610000, 0x00350000, 0x00570000, 0x00b90000 - data4 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000 - data4 0x00e10000, 0x00f80000, 0x00980000, 0x00110000 - data4 0x00690000, 0x00d90000, 0x008e0000, 0x00940000 - data4 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000 - data4 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000 - data4 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000 - data4 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000 - data4 0x00410000, 0x00990000, 0x002d0000, 0x000f0000 - data4 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000 -// Te6: - data4 0x00006300, 0x00007c00, 0x00007700, 0x00007b00 - data4 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500 - data4 0x00003000, 0x00000100, 0x00006700, 0x00002b00 - data4 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600 - data4 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00 - data4 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000 - data4 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00 - data4 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000 - data4 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600 - data4 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00 - data4 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100 - data4 0x00007100, 0x0000d800, 0x00003100, 0x00001500 - data4 0x00000400, 0x0000c700, 0x00002300, 0x0000c300 - data4 0x00001800, 0x00009600, 0x00000500, 0x00009a00 - data4 0x00000700, 0x00001200, 0x00008000, 0x0000e200 - data4 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500 - data4 0x00000900, 0x00008300, 0x00002c00, 0x00001a00 - data4 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000 - data4 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300 - data4 0x00002900, 0x0000e300, 0x00002f00, 0x00008400 - data4 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00 - data4 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00 - data4 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900 - data4 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00 - data4 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00 - data4 0x00004300, 0x00004d00, 0x00003300, 0x00008500 - data4 0x00004500, 0x0000f900, 0x00000200, 0x00007f00 - data4 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800 - data4 0x00005100, 0x0000a300, 0x00004000, 0x00008f00 - data4 0x00009200, 0x00009d00, 0x00003800, 0x0000f500 - data4 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100 - data4 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200 - data4 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00 - data4 0x00005f00, 0x00009700, 0x00004400, 0x00001700 - data4 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00 - data4 0x00006400, 0x00005d00, 0x00001900, 0x00007300 - data4 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00 - data4 0x00002200, 0x00002a00, 0x00009000, 0x00008800 - data4 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400 - data4 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00 - data4 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00 - data4 0x00004900, 0x00000600, 0x00002400, 0x00005c00 - data4 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200 - data4 0x00009100, 0x00009500, 0x0000e400, 0x00007900 - data4 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00 - data4 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900 - data4 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00 - data4 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800 - data4 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00 - data4 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600 - data4 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00 - data4 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00 - data4 0x00007000, 0x00003e00, 0x0000b500, 0x00006600 - data4 0x00004800, 0x00000300, 0x0000f600, 0x00000e00 - data4 0x00006100, 0x00003500, 0x00005700, 0x0000b900 - data4 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00 - data4 0x0000e100, 0x0000f800, 0x00009800, 0x00001100 - data4 0x00006900, 0x0000d900, 0x00008e00, 0x00009400 - data4 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900 - data4 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00 - data4 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00 - data4 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800 - data4 0x00004100, 0x00009900, 0x00002d00, 0x00000f00 - data4 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600 -// Te7: - data4 0x00000063, 0x0000007c, 0x00000077, 0x0000007b - data4 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5 - data4 0x00000030, 0x00000001, 0x00000067, 0x0000002b - data4 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076 - data4 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d - data4 0x000000fa, 0x00000059, 0x00000047, 0x000000f0 - data4 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af - data4 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0 - data4 0x000000b7, 0x000000fd, 0x00000093, 0x00000026 - data4 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc - data4 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1 - data4 0x00000071, 0x000000d8, 0x00000031, 0x00000015 - data4 0x00000004, 0x000000c7, 0x00000023, 0x000000c3 - data4 0x00000018, 0x00000096, 0x00000005, 0x0000009a - data4 0x00000007, 0x00000012, 0x00000080, 0x000000e2 - data4 0x000000eb, 0x00000027, 0x000000b2, 0x00000075 - data4 0x00000009, 0x00000083, 0x0000002c, 0x0000001a - data4 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0 - data4 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3 - data4 0x00000029, 0x000000e3, 0x0000002f, 0x00000084 - data4 0x00000053, 0x000000d1, 0x00000000, 0x000000ed - data4 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b - data4 0x0000006a, 0x000000cb, 0x000000be, 0x00000039 - data4 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf - data4 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb - data4 0x00000043, 0x0000004d, 0x00000033, 0x00000085 - data4 0x00000045, 0x000000f9, 0x00000002, 0x0000007f - data4 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8 - data4 0x00000051, 0x000000a3, 0x00000040, 0x0000008f - data4 0x00000092, 0x0000009d, 0x00000038, 0x000000f5 - data4 0x000000bc, 0x000000b6, 0x000000da, 0x00000021 - data4 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2 - data4 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec - data4 0x0000005f, 0x00000097, 0x00000044, 0x00000017 - data4 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d - data4 0x00000064, 0x0000005d, 0x00000019, 0x00000073 - data4 0x00000060, 0x00000081, 0x0000004f, 0x000000dc - data4 0x00000022, 0x0000002a, 0x00000090, 0x00000088 - data4 0x00000046, 0x000000ee, 0x000000b8, 0x00000014 - data4 0x000000de, 0x0000005e, 0x0000000b, 0x000000db - data4 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a - data4 0x00000049, 0x00000006, 0x00000024, 0x0000005c - data4 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062 - data4 0x00000091, 0x00000095, 0x000000e4, 0x00000079 - data4 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d - data4 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9 - data4 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea - data4 0x00000065, 0x0000007a, 0x000000ae, 0x00000008 - data4 0x000000ba, 0x00000078, 0x00000025, 0x0000002e - data4 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6 - data4 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f - data4 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a - data4 0x00000070, 0x0000003e, 0x000000b5, 0x00000066 - data4 0x00000048, 0x00000003, 0x000000f6, 0x0000000e - data4 0x00000061, 0x00000035, 0x00000057, 0x000000b9 - data4 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e - data4 0x000000e1, 0x000000f8, 0x00000098, 0x00000011 - data4 0x00000069, 0x000000d9, 0x0000008e, 0x00000094 - data4 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9 - data4 0x000000ce, 0x00000055, 0x00000028, 0x000000df - data4 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d - data4 0x000000bf, 0x000000e6, 0x00000042, 0x00000068 - data4 0x00000041, 0x00000099, 0x0000002d, 0x0000000f - data4 0x000000b0, 0x00000054, 0x000000bb, 0x00000016 -.size AES_Te#,8*256*4 // HP-UX assembler fails to ".-AES_Te#" + data1 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 + data1 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 + data1 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 + data1 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 + data1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc + data1 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 + data1 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a + data1 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 + data1 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 + data1 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 + data1 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b + data1 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf + data1 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 + data1 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 + data1 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 + data1 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 + data1 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 + data1 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 + data1 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 + data1 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb + data1 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c + data1 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 + data1 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 + data1 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 + data1 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 + data1 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a + data1 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e + data1 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e + data1 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 + data1 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf + data1 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 + data1 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +.size AES_Te#,2048+256 // HP-UX assembler fails to ".-AES_Te#" .align 64 .global AES_Td# .type AES_Td#,@object -AES_Td: data4 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 - data4 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 - data4 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 - data4 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f - data4 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 - data4 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 - data4 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da - data4 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 - data4 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd - data4 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 - data4 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 - data4 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 - data4 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 - data4 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a - data4 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 - data4 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c - data4 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 - data4 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a - data4 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 - data4 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 - data4 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 - data4 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff - data4 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 - data4 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb - data4 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 - data4 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e - data4 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 - data4 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a - data4 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e - data4 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 - data4 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d - data4 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 - data4 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd - data4 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 - data4 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 - data4 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 - data4 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d - data4 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 - data4 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 - data4 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef - data4 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 - data4 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 - data4 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 - data4 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 - data4 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 - data4 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b - data4 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 - data4 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 - data4 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 - data4 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 - data4 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 - data4 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f - data4 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df - data4 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f - data4 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e - data4 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 - data4 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 - data4 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c - data4 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf - data4 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 - data4 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f - data4 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 - data4 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 - data4 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 -// Td1: - data4 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e - data4 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303 - data4 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c - data4 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3 - data4 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0 - data4 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9 - data4 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259 - data4 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8 - data4 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971 - data4 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a - data4 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f - data4 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b - data4 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8 - data4 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab - data4 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708 - data4 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682 - data4 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2 - data4 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe - data4 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb - data4 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10 - data4 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd - data4 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015 - data4 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e - data4 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee - data4 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000 - data4 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72 - data4 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39 - data4 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e - data4 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91 - data4 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a - data4 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17 - data4 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9 - data4 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60 - data4 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e - data4 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1 - data4 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611 - data4 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1 - data4 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3 - data4 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964 - data4 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390 - data4 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b - data4 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf - data4 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46 - data4 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af - data4 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512 - data4 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb - data4 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a - data4 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8 - data4 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c - data4 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266 - data4 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8 - data4 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6 - data4 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604 - data4 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551 - data4 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41 - data4 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647 - data4 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c - data4 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1 - data4 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737 - data4 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db - data4 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340 - data4 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95 - data4 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1 - data4 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857 -// Td2: - data4 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27 - data4 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3 - data4 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502 - data4 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562 - data4 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe - data4 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3 - data4 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552 - data4 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9 - data4 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9 - data4 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce - data4 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253 - data4 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908 - data4 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b - data4 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655 - data4 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337 - data4 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16 - data4 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69 - data4 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6 - data4 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6 - data4 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e - data4 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6 - data4 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050 - data4 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9 - data4 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8 - data4 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000 - data4 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a - data4 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d - data4 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436 - data4 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b - data4 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12 - data4 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b - data4 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e - data4 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f - data4 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb - data4 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4 - data4 0xdccad731, 0x85104263, 0x22401397, 0x112084c6 - data4 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729 - data4 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1 - data4 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9 - data4 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233 - data4 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4 - data4 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad - data4 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e - data4 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3 - data4 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25 - data4 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b - data4 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f - data4 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15 - data4 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0 - data4 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2 - data4 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7 - data4 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791 - data4 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496 - data4 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665 - data4 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b - data4 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6 - data4 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13 - data4 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47 - data4 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7 - data4 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844 - data4 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3 - data4 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d - data4 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456 - data4 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8 -// Td3: - data4 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a - data4 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b - data4 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5 - data4 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5 - data4 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d - data4 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b - data4 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95 - data4 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e - data4 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27 - data4 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d - data4 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562 - data4 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9 - data4 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752 - data4 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66 - data4 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3 - data4 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced - data4 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e - data4 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4 - data4 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4 - data4 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd - data4 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d - data4 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60 - data4 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767 - data4 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79 - data4 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000 - data4 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c - data4 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736 - data4 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24 - data4 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b - data4 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c - data4 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12 - data4 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814 - data4 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3 - data4 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b - data4 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8 - data4 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084 - data4 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7 - data4 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077 - data4 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247 - data4 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22 - data4 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698 - data4 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f - data4 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254 - data4 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582 - data4 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf - data4 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb - data4 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883 - data4 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef - data4 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629 - data4 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035 - data4 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533 - data4 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17 - data4 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4 - data4 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46 - data4 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb - data4 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d - data4 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb - data4 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a - data4 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73 - data4 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678 - data4 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2 - data4 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff - data4 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064 - data4 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0 +AES_Td: data4 0x51f4a750,0x51f4a750, 0x7e416553,0x7e416553 + data4 0x1a17a4c3,0x1a17a4c3, 0x3a275e96,0x3a275e96 + data4 0x3bab6bcb,0x3bab6bcb, 0x1f9d45f1,0x1f9d45f1 + data4 0xacfa58ab,0xacfa58ab, 0x4be30393,0x4be30393 + data4 0x2030fa55,0x2030fa55, 0xad766df6,0xad766df6 + data4 0x88cc7691,0x88cc7691, 0xf5024c25,0xf5024c25 + data4 0x4fe5d7fc,0x4fe5d7fc, 0xc52acbd7,0xc52acbd7 + data4 0x26354480,0x26354480, 0xb562a38f,0xb562a38f + data4 0xdeb15a49,0xdeb15a49, 0x25ba1b67,0x25ba1b67 + data4 0x45ea0e98,0x45ea0e98, 0x5dfec0e1,0x5dfec0e1 + data4 0xc32f7502,0xc32f7502, 0x814cf012,0x814cf012 + data4 0x8d4697a3,0x8d4697a3, 0x6bd3f9c6,0x6bd3f9c6 + data4 0x038f5fe7,0x038f5fe7, 0x15929c95,0x15929c95 + data4 0xbf6d7aeb,0xbf6d7aeb, 0x955259da,0x955259da + data4 0xd4be832d,0xd4be832d, 0x587421d3,0x587421d3 + data4 0x49e06929,0x49e06929, 0x8ec9c844,0x8ec9c844 + data4 0x75c2896a,0x75c2896a, 0xf48e7978,0xf48e7978 + data4 0x99583e6b,0x99583e6b, 0x27b971dd,0x27b971dd + data4 0xbee14fb6,0xbee14fb6, 0xf088ad17,0xf088ad17 + data4 0xc920ac66,0xc920ac66, 0x7dce3ab4,0x7dce3ab4 + data4 0x63df4a18,0x63df4a18, 0xe51a3182,0xe51a3182 + data4 0x97513360,0x97513360, 0x62537f45,0x62537f45 + data4 0xb16477e0,0xb16477e0, 0xbb6bae84,0xbb6bae84 + data4 0xfe81a01c,0xfe81a01c, 0xf9082b94,0xf9082b94 + data4 0x70486858,0x70486858, 0x8f45fd19,0x8f45fd19 + data4 0x94de6c87,0x94de6c87, 0x527bf8b7,0x527bf8b7 + data4 0xab73d323,0xab73d323, 0x724b02e2,0x724b02e2 + data4 0xe31f8f57,0xe31f8f57, 0x6655ab2a,0x6655ab2a + data4 0xb2eb2807,0xb2eb2807, 0x2fb5c203,0x2fb5c203 + data4 0x86c57b9a,0x86c57b9a, 0xd33708a5,0xd33708a5 + data4 0x302887f2,0x302887f2, 0x23bfa5b2,0x23bfa5b2 + data4 0x02036aba,0x02036aba, 0xed16825c,0xed16825c + data4 0x8acf1c2b,0x8acf1c2b, 0xa779b492,0xa779b492 + data4 0xf307f2f0,0xf307f2f0, 0x4e69e2a1,0x4e69e2a1 + data4 0x65daf4cd,0x65daf4cd, 0x0605bed5,0x0605bed5 + data4 0xd134621f,0xd134621f, 0xc4a6fe8a,0xc4a6fe8a + data4 0x342e539d,0x342e539d, 0xa2f355a0,0xa2f355a0 + data4 0x058ae132,0x058ae132, 0xa4f6eb75,0xa4f6eb75 + data4 0x0b83ec39,0x0b83ec39, 0x4060efaa,0x4060efaa + data4 0x5e719f06,0x5e719f06, 0xbd6e1051,0xbd6e1051 + data4 0x3e218af9,0x3e218af9, 0x96dd063d,0x96dd063d + data4 0xdd3e05ae,0xdd3e05ae, 0x4de6bd46,0x4de6bd46 + data4 0x91548db5,0x91548db5, 0x71c45d05,0x71c45d05 + data4 0x0406d46f,0x0406d46f, 0x605015ff,0x605015ff + data4 0x1998fb24,0x1998fb24, 0xd6bde997,0xd6bde997 + data4 0x894043cc,0x894043cc, 0x67d99e77,0x67d99e77 + data4 0xb0e842bd,0xb0e842bd, 0x07898b88,0x07898b88 + data4 0xe7195b38,0xe7195b38, 0x79c8eedb,0x79c8eedb + data4 0xa17c0a47,0xa17c0a47, 0x7c420fe9,0x7c420fe9 + data4 0xf8841ec9,0xf8841ec9, 0x00000000,0x00000000 + data4 0x09808683,0x09808683, 0x322bed48,0x322bed48 + data4 0x1e1170ac,0x1e1170ac, 0x6c5a724e,0x6c5a724e + data4 0xfd0efffb,0xfd0efffb, 0x0f853856,0x0f853856 + data4 0x3daed51e,0x3daed51e, 0x362d3927,0x362d3927 + data4 0x0a0fd964,0x0a0fd964, 0x685ca621,0x685ca621 + data4 0x9b5b54d1,0x9b5b54d1, 0x24362e3a,0x24362e3a + data4 0x0c0a67b1,0x0c0a67b1, 0x9357e70f,0x9357e70f + data4 0xb4ee96d2,0xb4ee96d2, 0x1b9b919e,0x1b9b919e + data4 0x80c0c54f,0x80c0c54f, 0x61dc20a2,0x61dc20a2 + data4 0x5a774b69,0x5a774b69, 0x1c121a16,0x1c121a16 + data4 0xe293ba0a,0xe293ba0a, 0xc0a02ae5,0xc0a02ae5 + data4 0x3c22e043,0x3c22e043, 0x121b171d,0x121b171d + data4 0x0e090d0b,0x0e090d0b, 0xf28bc7ad,0xf28bc7ad + data4 0x2db6a8b9,0x2db6a8b9, 0x141ea9c8,0x141ea9c8 + data4 0x57f11985,0x57f11985, 0xaf75074c,0xaf75074c + data4 0xee99ddbb,0xee99ddbb, 0xa37f60fd,0xa37f60fd + data4 0xf701269f,0xf701269f, 0x5c72f5bc,0x5c72f5bc + data4 0x44663bc5,0x44663bc5, 0x5bfb7e34,0x5bfb7e34 + data4 0x8b432976,0x8b432976, 0xcb23c6dc,0xcb23c6dc + data4 0xb6edfc68,0xb6edfc68, 0xb8e4f163,0xb8e4f163 + data4 0xd731dcca,0xd731dcca, 0x42638510,0x42638510 + data4 0x13972240,0x13972240, 0x84c61120,0x84c61120 + data4 0x854a247d,0x854a247d, 0xd2bb3df8,0xd2bb3df8 + data4 0xaef93211,0xaef93211, 0xc729a16d,0xc729a16d + data4 0x1d9e2f4b,0x1d9e2f4b, 0xdcb230f3,0xdcb230f3 + data4 0x0d8652ec,0x0d8652ec, 0x77c1e3d0,0x77c1e3d0 + data4 0x2bb3166c,0x2bb3166c, 0xa970b999,0xa970b999 + data4 0x119448fa,0x119448fa, 0x47e96422,0x47e96422 + data4 0xa8fc8cc4,0xa8fc8cc4, 0xa0f03f1a,0xa0f03f1a + data4 0x567d2cd8,0x567d2cd8, 0x223390ef,0x223390ef + data4 0x87494ec7,0x87494ec7, 0xd938d1c1,0xd938d1c1 + data4 0x8ccaa2fe,0x8ccaa2fe, 0x98d40b36,0x98d40b36 + data4 0xa6f581cf,0xa6f581cf, 0xa57ade28,0xa57ade28 + data4 0xdab78e26,0xdab78e26, 0x3fadbfa4,0x3fadbfa4 + data4 0x2c3a9de4,0x2c3a9de4, 0x5078920d,0x5078920d + data4 0x6a5fcc9b,0x6a5fcc9b, 0x547e4662,0x547e4662 + data4 0xf68d13c2,0xf68d13c2, 0x90d8b8e8,0x90d8b8e8 + data4 0x2e39f75e,0x2e39f75e, 0x82c3aff5,0x82c3aff5 + data4 0x9f5d80be,0x9f5d80be, 0x69d0937c,0x69d0937c + data4 0x6fd52da9,0x6fd52da9, 0xcf2512b3,0xcf2512b3 + data4 0xc8ac993b,0xc8ac993b, 0x10187da7,0x10187da7 + data4 0xe89c636e,0xe89c636e, 0xdb3bbb7b,0xdb3bbb7b + data4 0xcd267809,0xcd267809, 0x6e5918f4,0x6e5918f4 + data4 0xec9ab701,0xec9ab701, 0x834f9aa8,0x834f9aa8 + data4 0xe6956e65,0xe6956e65, 0xaaffe67e,0xaaffe67e + data4 0x21bccf08,0x21bccf08, 0xef15e8e6,0xef15e8e6 + data4 0xbae79bd9,0xbae79bd9, 0x4a6f36ce,0x4a6f36ce + data4 0xea9f09d4,0xea9f09d4, 0x29b07cd6,0x29b07cd6 + data4 0x31a4b2af,0x31a4b2af, 0x2a3f2331,0x2a3f2331 + data4 0xc6a59430,0xc6a59430, 0x35a266c0,0x35a266c0 + data4 0x744ebc37,0x744ebc37, 0xfc82caa6,0xfc82caa6 + data4 0xe090d0b0,0xe090d0b0, 0x33a7d815,0x33a7d815 + data4 0xf104984a,0xf104984a, 0x41ecdaf7,0x41ecdaf7 + data4 0x7fcd500e,0x7fcd500e, 0x1791f62f,0x1791f62f + data4 0x764dd68d,0x764dd68d, 0x43efb04d,0x43efb04d + data4 0xccaa4d54,0xccaa4d54, 0xe49604df,0xe49604df + data4 0x9ed1b5e3,0x9ed1b5e3, 0x4c6a881b,0x4c6a881b + data4 0xc12c1fb8,0xc12c1fb8, 0x4665517f,0x4665517f + data4 0x9d5eea04,0x9d5eea04, 0x018c355d,0x018c355d + data4 0xfa877473,0xfa877473, 0xfb0b412e,0xfb0b412e + data4 0xb3671d5a,0xb3671d5a, 0x92dbd252,0x92dbd252 + data4 0xe9105633,0xe9105633, 0x6dd64713,0x6dd64713 + data4 0x9ad7618c,0x9ad7618c, 0x37a10c7a,0x37a10c7a + data4 0x59f8148e,0x59f8148e, 0xeb133c89,0xeb133c89 + data4 0xcea927ee,0xcea927ee, 0xb761c935,0xb761c935 + data4 0xe11ce5ed,0xe11ce5ed, 0x7a47b13c,0x7a47b13c + data4 0x9cd2df59,0x9cd2df59, 0x55f2733f,0x55f2733f + data4 0x1814ce79,0x1814ce79, 0x73c737bf,0x73c737bf + data4 0x53f7cdea,0x53f7cdea, 0x5ffdaa5b,0x5ffdaa5b + data4 0xdf3d6f14,0xdf3d6f14, 0x7844db86,0x7844db86 + data4 0xcaaff381,0xcaaff381, 0xb968c43e,0xb968c43e + data4 0x3824342c,0x3824342c, 0xc2a3405f,0xc2a3405f + data4 0x161dc372,0x161dc372, 0xbce2250c,0xbce2250c + data4 0x283c498b,0x283c498b, 0xff0d9541,0xff0d9541 + data4 0x39a80171,0x39a80171, 0x080cb3de,0x080cb3de + data4 0xd8b4e49c,0xd8b4e49c, 0x6456c190,0x6456c190 + data4 0x7bcb8461,0x7bcb8461, 0xd532b670,0xd532b670 + data4 0x486c5c74,0x486c5c74, 0xd0b85742,0xd0b85742 // Td4: - data4 0x52000000, 0x09000000, 0x6a000000, 0xd5000000 - data4 0x30000000, 0x36000000, 0xa5000000, 0x38000000 - data4 0xbf000000, 0x40000000, 0xa3000000, 0x9e000000 - data4 0x81000000, 0xf3000000, 0xd7000000, 0xfb000000 - data4 0x7c000000, 0xe3000000, 0x39000000, 0x82000000 - data4 0x9b000000, 0x2f000000, 0xff000000, 0x87000000 - data4 0x34000000, 0x8e000000, 0x43000000, 0x44000000 - data4 0xc4000000, 0xde000000, 0xe9000000, 0xcb000000 - data4 0x54000000, 0x7b000000, 0x94000000, 0x32000000 - data4 0xa6000000, 0xc2000000, 0x23000000, 0x3d000000 - data4 0xee000000, 0x4c000000, 0x95000000, 0x0b000000 - data4 0x42000000, 0xfa000000, 0xc3000000, 0x4e000000 - data4 0x08000000, 0x2e000000, 0xa1000000, 0x66000000 - data4 0x28000000, 0xd9000000, 0x24000000, 0xb2000000 - data4 0x76000000, 0x5b000000, 0xa2000000, 0x49000000 - data4 0x6d000000, 0x8b000000, 0xd1000000, 0x25000000 - data4 0x72000000, 0xf8000000, 0xf6000000, 0x64000000 - data4 0x86000000, 0x68000000, 0x98000000, 0x16000000 - data4 0xd4000000, 0xa4000000, 0x5c000000, 0xcc000000 - data4 0x5d000000, 0x65000000, 0xb6000000, 0x92000000 - data4 0x6c000000, 0x70000000, 0x48000000, 0x50000000 - data4 0xfd000000, 0xed000000, 0xb9000000, 0xda000000 - data4 0x5e000000, 0x15000000, 0x46000000, 0x57000000 - data4 0xa7000000, 0x8d000000, 0x9d000000, 0x84000000 - data4 0x90000000, 0xd8000000, 0xab000000, 0x00000000 - data4 0x8c000000, 0xbc000000, 0xd3000000, 0x0a000000 - data4 0xf7000000, 0xe4000000, 0x58000000, 0x05000000 - data4 0xb8000000, 0xb3000000, 0x45000000, 0x06000000 - data4 0xd0000000, 0x2c000000, 0x1e000000, 0x8f000000 - data4 0xca000000, 0x3f000000, 0x0f000000, 0x02000000 - data4 0xc1000000, 0xaf000000, 0xbd000000, 0x03000000 - data4 0x01000000, 0x13000000, 0x8a000000, 0x6b000000 - data4 0x3a000000, 0x91000000, 0x11000000, 0x41000000 - data4 0x4f000000, 0x67000000, 0xdc000000, 0xea000000 - data4 0x97000000, 0xf2000000, 0xcf000000, 0xce000000 - data4 0xf0000000, 0xb4000000, 0xe6000000, 0x73000000 - data4 0x96000000, 0xac000000, 0x74000000, 0x22000000 - data4 0xe7000000, 0xad000000, 0x35000000, 0x85000000 - data4 0xe2000000, 0xf9000000, 0x37000000, 0xe8000000 - data4 0x1c000000, 0x75000000, 0xdf000000, 0x6e000000 - data4 0x47000000, 0xf1000000, 0x1a000000, 0x71000000 - data4 0x1d000000, 0x29000000, 0xc5000000, 0x89000000 - data4 0x6f000000, 0xb7000000, 0x62000000, 0x0e000000 - data4 0xaa000000, 0x18000000, 0xbe000000, 0x1b000000 - data4 0xfc000000, 0x56000000, 0x3e000000, 0x4b000000 - data4 0xc6000000, 0xd2000000, 0x79000000, 0x20000000 - data4 0x9a000000, 0xdb000000, 0xc0000000, 0xfe000000 - data4 0x78000000, 0xcd000000, 0x5a000000, 0xf4000000 - data4 0x1f000000, 0xdd000000, 0xa8000000, 0x33000000 - data4 0x88000000, 0x07000000, 0xc7000000, 0x31000000 - data4 0xb1000000, 0x12000000, 0x10000000, 0x59000000 - data4 0x27000000, 0x80000000, 0xec000000, 0x5f000000 - data4 0x60000000, 0x51000000, 0x7f000000, 0xa9000000 - data4 0x19000000, 0xb5000000, 0x4a000000, 0x0d000000 - data4 0x2d000000, 0xe5000000, 0x7a000000, 0x9f000000 - data4 0x93000000, 0xc9000000, 0x9c000000, 0xef000000 - data4 0xa0000000, 0xe0000000, 0x3b000000, 0x4d000000 - data4 0xae000000, 0x2a000000, 0xf5000000, 0xb0000000 - data4 0xc8000000, 0xeb000000, 0xbb000000, 0x3c000000 - data4 0x83000000, 0x53000000, 0x99000000, 0x61000000 - data4 0x17000000, 0x2b000000, 0x04000000, 0x7e000000 - data4 0xba000000, 0x77000000, 0xd6000000, 0x26000000 - data4 0xe1000000, 0x69000000, 0x14000000, 0x63000000 - data4 0x55000000, 0x21000000, 0x0c000000, 0x7d000000 -// Td5: - data4 0x00520000, 0x00090000, 0x006a0000, 0x00d50000 - data4 0x00300000, 0x00360000, 0x00a50000, 0x00380000 - data4 0x00bf0000, 0x00400000, 0x00a30000, 0x009e0000 - data4 0x00810000, 0x00f30000, 0x00d70000, 0x00fb0000 - data4 0x007c0000, 0x00e30000, 0x00390000, 0x00820000 - data4 0x009b0000, 0x002f0000, 0x00ff0000, 0x00870000 - data4 0x00340000, 0x008e0000, 0x00430000, 0x00440000 - data4 0x00c40000, 0x00de0000, 0x00e90000, 0x00cb0000 - data4 0x00540000, 0x007b0000, 0x00940000, 0x00320000 - data4 0x00a60000, 0x00c20000, 0x00230000, 0x003d0000 - data4 0x00ee0000, 0x004c0000, 0x00950000, 0x000b0000 - data4 0x00420000, 0x00fa0000, 0x00c30000, 0x004e0000 - data4 0x00080000, 0x002e0000, 0x00a10000, 0x00660000 - data4 0x00280000, 0x00d90000, 0x00240000, 0x00b20000 - data4 0x00760000, 0x005b0000, 0x00a20000, 0x00490000 - data4 0x006d0000, 0x008b0000, 0x00d10000, 0x00250000 - data4 0x00720000, 0x00f80000, 0x00f60000, 0x00640000 - data4 0x00860000, 0x00680000, 0x00980000, 0x00160000 - data4 0x00d40000, 0x00a40000, 0x005c0000, 0x00cc0000 - data4 0x005d0000, 0x00650000, 0x00b60000, 0x00920000 - data4 0x006c0000, 0x00700000, 0x00480000, 0x00500000 - data4 0x00fd0000, 0x00ed0000, 0x00b90000, 0x00da0000 - data4 0x005e0000, 0x00150000, 0x00460000, 0x00570000 - data4 0x00a70000, 0x008d0000, 0x009d0000, 0x00840000 - data4 0x00900000, 0x00d80000, 0x00ab0000, 0x00000000 - data4 0x008c0000, 0x00bc0000, 0x00d30000, 0x000a0000 - data4 0x00f70000, 0x00e40000, 0x00580000, 0x00050000 - data4 0x00b80000, 0x00b30000, 0x00450000, 0x00060000 - data4 0x00d00000, 0x002c0000, 0x001e0000, 0x008f0000 - data4 0x00ca0000, 0x003f0000, 0x000f0000, 0x00020000 - data4 0x00c10000, 0x00af0000, 0x00bd0000, 0x00030000 - data4 0x00010000, 0x00130000, 0x008a0000, 0x006b0000 - data4 0x003a0000, 0x00910000, 0x00110000, 0x00410000 - data4 0x004f0000, 0x00670000, 0x00dc0000, 0x00ea0000 - data4 0x00970000, 0x00f20000, 0x00cf0000, 0x00ce0000 - data4 0x00f00000, 0x00b40000, 0x00e60000, 0x00730000 - data4 0x00960000, 0x00ac0000, 0x00740000, 0x00220000 - data4 0x00e70000, 0x00ad0000, 0x00350000, 0x00850000 - data4 0x00e20000, 0x00f90000, 0x00370000, 0x00e80000 - data4 0x001c0000, 0x00750000, 0x00df0000, 0x006e0000 - data4 0x00470000, 0x00f10000, 0x001a0000, 0x00710000 - data4 0x001d0000, 0x00290000, 0x00c50000, 0x00890000 - data4 0x006f0000, 0x00b70000, 0x00620000, 0x000e0000 - data4 0x00aa0000, 0x00180000, 0x00be0000, 0x001b0000 - data4 0x00fc0000, 0x00560000, 0x003e0000, 0x004b0000 - data4 0x00c60000, 0x00d20000, 0x00790000, 0x00200000 - data4 0x009a0000, 0x00db0000, 0x00c00000, 0x00fe0000 - data4 0x00780000, 0x00cd0000, 0x005a0000, 0x00f40000 - data4 0x001f0000, 0x00dd0000, 0x00a80000, 0x00330000 - data4 0x00880000, 0x00070000, 0x00c70000, 0x00310000 - data4 0x00b10000, 0x00120000, 0x00100000, 0x00590000 - data4 0x00270000, 0x00800000, 0x00ec0000, 0x005f0000 - data4 0x00600000, 0x00510000, 0x007f0000, 0x00a90000 - data4 0x00190000, 0x00b50000, 0x004a0000, 0x000d0000 - data4 0x002d0000, 0x00e50000, 0x007a0000, 0x009f0000 - data4 0x00930000, 0x00c90000, 0x009c0000, 0x00ef0000 - data4 0x00a00000, 0x00e00000, 0x003b0000, 0x004d0000 - data4 0x00ae0000, 0x002a0000, 0x00f50000, 0x00b00000 - data4 0x00c80000, 0x00eb0000, 0x00bb0000, 0x003c0000 - data4 0x00830000, 0x00530000, 0x00990000, 0x00610000 - data4 0x00170000, 0x002b0000, 0x00040000, 0x007e0000 - data4 0x00ba0000, 0x00770000, 0x00d60000, 0x00260000 - data4 0x00e10000, 0x00690000, 0x00140000, 0x00630000 - data4 0x00550000, 0x00210000, 0x000c0000, 0x007d0000 -// Td6: - data4 0x00005200, 0x00000900, 0x00006a00, 0x0000d500 - data4 0x00003000, 0x00003600, 0x0000a500, 0x00003800 - data4 0x0000bf00, 0x00004000, 0x0000a300, 0x00009e00 - data4 0x00008100, 0x0000f300, 0x0000d700, 0x0000fb00 - data4 0x00007c00, 0x0000e300, 0x00003900, 0x00008200 - data4 0x00009b00, 0x00002f00, 0x0000ff00, 0x00008700 - data4 0x00003400, 0x00008e00, 0x00004300, 0x00004400 - data4 0x0000c400, 0x0000de00, 0x0000e900, 0x0000cb00 - data4 0x00005400, 0x00007b00, 0x00009400, 0x00003200 - data4 0x0000a600, 0x0000c200, 0x00002300, 0x00003d00 - data4 0x0000ee00, 0x00004c00, 0x00009500, 0x00000b00 - data4 0x00004200, 0x0000fa00, 0x0000c300, 0x00004e00 - data4 0x00000800, 0x00002e00, 0x0000a100, 0x00006600 - data4 0x00002800, 0x0000d900, 0x00002400, 0x0000b200 - data4 0x00007600, 0x00005b00, 0x0000a200, 0x00004900 - data4 0x00006d00, 0x00008b00, 0x0000d100, 0x00002500 - data4 0x00007200, 0x0000f800, 0x0000f600, 0x00006400 - data4 0x00008600, 0x00006800, 0x00009800, 0x00001600 - data4 0x0000d400, 0x0000a400, 0x00005c00, 0x0000cc00 - data4 0x00005d00, 0x00006500, 0x0000b600, 0x00009200 - data4 0x00006c00, 0x00007000, 0x00004800, 0x00005000 - data4 0x0000fd00, 0x0000ed00, 0x0000b900, 0x0000da00 - data4 0x00005e00, 0x00001500, 0x00004600, 0x00005700 - data4 0x0000a700, 0x00008d00, 0x00009d00, 0x00008400 - data4 0x00009000, 0x0000d800, 0x0000ab00, 0x00000000 - data4 0x00008c00, 0x0000bc00, 0x0000d300, 0x00000a00 - data4 0x0000f700, 0x0000e400, 0x00005800, 0x00000500 - data4 0x0000b800, 0x0000b300, 0x00004500, 0x00000600 - data4 0x0000d000, 0x00002c00, 0x00001e00, 0x00008f00 - data4 0x0000ca00, 0x00003f00, 0x00000f00, 0x00000200 - data4 0x0000c100, 0x0000af00, 0x0000bd00, 0x00000300 - data4 0x00000100, 0x00001300, 0x00008a00, 0x00006b00 - data4 0x00003a00, 0x00009100, 0x00001100, 0x00004100 - data4 0x00004f00, 0x00006700, 0x0000dc00, 0x0000ea00 - data4 0x00009700, 0x0000f200, 0x0000cf00, 0x0000ce00 - data4 0x0000f000, 0x0000b400, 0x0000e600, 0x00007300 - data4 0x00009600, 0x0000ac00, 0x00007400, 0x00002200 - data4 0x0000e700, 0x0000ad00, 0x00003500, 0x00008500 - data4 0x0000e200, 0x0000f900, 0x00003700, 0x0000e800 - data4 0x00001c00, 0x00007500, 0x0000df00, 0x00006e00 - data4 0x00004700, 0x0000f100, 0x00001a00, 0x00007100 - data4 0x00001d00, 0x00002900, 0x0000c500, 0x00008900 - data4 0x00006f00, 0x0000b700, 0x00006200, 0x00000e00 - data4 0x0000aa00, 0x00001800, 0x0000be00, 0x00001b00 - data4 0x0000fc00, 0x00005600, 0x00003e00, 0x00004b00 - data4 0x0000c600, 0x0000d200, 0x00007900, 0x00002000 - data4 0x00009a00, 0x0000db00, 0x0000c000, 0x0000fe00 - data4 0x00007800, 0x0000cd00, 0x00005a00, 0x0000f400 - data4 0x00001f00, 0x0000dd00, 0x0000a800, 0x00003300 - data4 0x00008800, 0x00000700, 0x0000c700, 0x00003100 - data4 0x0000b100, 0x00001200, 0x00001000, 0x00005900 - data4 0x00002700, 0x00008000, 0x0000ec00, 0x00005f00 - data4 0x00006000, 0x00005100, 0x00007f00, 0x0000a900 - data4 0x00001900, 0x0000b500, 0x00004a00, 0x00000d00 - data4 0x00002d00, 0x0000e500, 0x00007a00, 0x00009f00 - data4 0x00009300, 0x0000c900, 0x00009c00, 0x0000ef00 - data4 0x0000a000, 0x0000e000, 0x00003b00, 0x00004d00 - data4 0x0000ae00, 0x00002a00, 0x0000f500, 0x0000b000 - data4 0x0000c800, 0x0000eb00, 0x0000bb00, 0x00003c00 - data4 0x00008300, 0x00005300, 0x00009900, 0x00006100 - data4 0x00001700, 0x00002b00, 0x00000400, 0x00007e00 - data4 0x0000ba00, 0x00007700, 0x0000d600, 0x00002600 - data4 0x0000e100, 0x00006900, 0x00001400, 0x00006300 - data4 0x00005500, 0x00002100, 0x00000c00, 0x00007d00 -// Td7: - data4 0x00000052, 0x00000009, 0x0000006a, 0x000000d5 - data4 0x00000030, 0x00000036, 0x000000a5, 0x00000038 - data4 0x000000bf, 0x00000040, 0x000000a3, 0x0000009e - data4 0x00000081, 0x000000f3, 0x000000d7, 0x000000fb - data4 0x0000007c, 0x000000e3, 0x00000039, 0x00000082 - data4 0x0000009b, 0x0000002f, 0x000000ff, 0x00000087 - data4 0x00000034, 0x0000008e, 0x00000043, 0x00000044 - data4 0x000000c4, 0x000000de, 0x000000e9, 0x000000cb - data4 0x00000054, 0x0000007b, 0x00000094, 0x00000032 - data4 0x000000a6, 0x000000c2, 0x00000023, 0x0000003d - data4 0x000000ee, 0x0000004c, 0x00000095, 0x0000000b - data4 0x00000042, 0x000000fa, 0x000000c3, 0x0000004e - data4 0x00000008, 0x0000002e, 0x000000a1, 0x00000066 - data4 0x00000028, 0x000000d9, 0x00000024, 0x000000b2 - data4 0x00000076, 0x0000005b, 0x000000a2, 0x00000049 - data4 0x0000006d, 0x0000008b, 0x000000d1, 0x00000025 - data4 0x00000072, 0x000000f8, 0x000000f6, 0x00000064 - data4 0x00000086, 0x00000068, 0x00000098, 0x00000016 - data4 0x000000d4, 0x000000a4, 0x0000005c, 0x000000cc - data4 0x0000005d, 0x00000065, 0x000000b6, 0x00000092 - data4 0x0000006c, 0x00000070, 0x00000048, 0x00000050 - data4 0x000000fd, 0x000000ed, 0x000000b9, 0x000000da - data4 0x0000005e, 0x00000015, 0x00000046, 0x00000057 - data4 0x000000a7, 0x0000008d, 0x0000009d, 0x00000084 - data4 0x00000090, 0x000000d8, 0x000000ab, 0x00000000 - data4 0x0000008c, 0x000000bc, 0x000000d3, 0x0000000a - data4 0x000000f7, 0x000000e4, 0x00000058, 0x00000005 - data4 0x000000b8, 0x000000b3, 0x00000045, 0x00000006 - data4 0x000000d0, 0x0000002c, 0x0000001e, 0x0000008f - data4 0x000000ca, 0x0000003f, 0x0000000f, 0x00000002 - data4 0x000000c1, 0x000000af, 0x000000bd, 0x00000003 - data4 0x00000001, 0x00000013, 0x0000008a, 0x0000006b - data4 0x0000003a, 0x00000091, 0x00000011, 0x00000041 - data4 0x0000004f, 0x00000067, 0x000000dc, 0x000000ea - data4 0x00000097, 0x000000f2, 0x000000cf, 0x000000ce - data4 0x000000f0, 0x000000b4, 0x000000e6, 0x00000073 - data4 0x00000096, 0x000000ac, 0x00000074, 0x00000022 - data4 0x000000e7, 0x000000ad, 0x00000035, 0x00000085 - data4 0x000000e2, 0x000000f9, 0x00000037, 0x000000e8 - data4 0x0000001c, 0x00000075, 0x000000df, 0x0000006e - data4 0x00000047, 0x000000f1, 0x0000001a, 0x00000071 - data4 0x0000001d, 0x00000029, 0x000000c5, 0x00000089 - data4 0x0000006f, 0x000000b7, 0x00000062, 0x0000000e - data4 0x000000aa, 0x00000018, 0x000000be, 0x0000001b - data4 0x000000fc, 0x00000056, 0x0000003e, 0x0000004b - data4 0x000000c6, 0x000000d2, 0x00000079, 0x00000020 - data4 0x0000009a, 0x000000db, 0x000000c0, 0x000000fe - data4 0x00000078, 0x000000cd, 0x0000005a, 0x000000f4 - data4 0x0000001f, 0x000000dd, 0x000000a8, 0x00000033 - data4 0x00000088, 0x00000007, 0x000000c7, 0x00000031 - data4 0x000000b1, 0x00000012, 0x00000010, 0x00000059 - data4 0x00000027, 0x00000080, 0x000000ec, 0x0000005f - data4 0x00000060, 0x00000051, 0x0000007f, 0x000000a9 - data4 0x00000019, 0x000000b5, 0x0000004a, 0x0000000d - data4 0x0000002d, 0x000000e5, 0x0000007a, 0x0000009f - data4 0x00000093, 0x000000c9, 0x0000009c, 0x000000ef - data4 0x000000a0, 0x000000e0, 0x0000003b, 0x0000004d - data4 0x000000ae, 0x0000002a, 0x000000f5, 0x000000b0 - data4 0x000000c8, 0x000000eb, 0x000000bb, 0x0000003c - data4 0x00000083, 0x00000053, 0x00000099, 0x00000061 - data4 0x00000017, 0x0000002b, 0x00000004, 0x0000007e - data4 0x000000ba, 0x00000077, 0x000000d6, 0x00000026 - data4 0x000000e1, 0x00000069, 0x00000014, 0x00000063 - data4 0x00000055, 0x00000021, 0x0000000c, 0x0000007d -.size AES_Td#,8*256*4 // HP-UX assembler fails to ".-AES_Td#" + data1 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 + data1 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + data1 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 + data1 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + data1 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d + data1 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + data1 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 + data1 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + data1 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 + data1 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + data1 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda + data1 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + data1 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a + data1 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + data1 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 + data1 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + data1 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea + data1 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + data1 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 + data1 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + data1 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 + data1 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + data1 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 + data1 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + data1 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 + data1 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + data1 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d + data1 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + data1 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 + data1 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + data1 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 + data1 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td#,2048+256 // HP-UX assembler fails to ".-AES_Td#" diff --git a/crypto/aes/asm/aes-x86_64.pl b/crypto/aes/asm/aes-x86_64.pl new file mode 100755 index 000000000000..44e0bf8cae3a --- /dev/null +++ b/crypto/aes/asm/aes-x86_64.pl @@ -0,0 +1,1578 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# Version 1.2. +# +# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on +# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version +# [you'll notice a lot of resemblance], such as compressed S-boxes +# in little-endian byte order, prefetch of these tables in CBC mode, +# as well as avoiding L1 cache aliasing between stack frame and key +# schedule and already mentioned tables, compressed Td4... +# +# Performance in number of cycles per processed byte for 128-bit key: +# +# ECB CBC encrypt +# AMD64 13.7 13.0(*) +# EM64T 20.2 18.6(*) +# +# (*) CBC benchmarks are better than ECB thanks to custom ABI used +# by the private block encryption function. + +$verticalspin=1; # unlike 32-bit version $verticalspin performs + # ~15% better on both AMD and Intel cores +$output=shift; +open STDOUT,"| $^X ../perlasm/x86_64-xlate.pl $output"; + +$code=".text\n"; + +$s0="%eax"; +$s1="%ebx"; +$s2="%ecx"; +$s3="%edx"; +$acc0="%esi"; +$acc1="%edi"; +$acc2="%ebp"; +$inp="%r8"; +$out="%r9"; +$t0="%r10d"; +$t1="%r11d"; +$t2="%r12d"; +$rnds="%r13d"; +$sbox="%r14"; +$key="%r15"; + +sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } +sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; + $r =~ s/%[er]([sd]i)/%\1l/; + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; } +} +sub data_word() +{ my $i; + my $last=pop(@_); + $code.=".long\t"; + while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; } + $code.=sprintf"0x%08x\n",$last; +} + +sub data_byte() +{ my $i; + my $last=pop(@_); + $code.=".byte\t"; + while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; } + $code.=sprintf"0x%02x\n",$last&0xff; +} + +sub encvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + shr \$16,$s2 + movzb `&hi("$s0")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + mov 12($key),$s3 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + mov 0($key),$s0 + xor 1($sbox,$acc1,8),$t2 + xor 1($sbox,$acc2,8),$t3 + + mov 4($key),$s1 + mov 8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enclastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 2($sbox,$acc0,8),$t0 + mov 2($sbox,$acc1,8),$t1 + mov 2($sbox,$acc2,8),$t2 + + and \$0x000000ff,$t0 + and \$0x000000ff,$t1 + and \$0x000000ff,$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + mov 2($sbox,$acc0,8),$t3 + mov 0($sbox,$acc1,8),$acc1 #$t0 + mov 0($sbox,$acc2,8),$acc2 #$t1 + + and \$0x000000ff,$t3 + and \$0x0000ff00,$acc1 + and \$0x0000ff00,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + mov 0($sbox,$acc0,8),$acc0 #$t2 + mov 0($sbox,$acc1,8),$acc1 #$t3 + + and \$0x0000ff00,$acc0 + and \$0x0000ff00,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t0 + mov 0($sbox,$acc1,8),$acc1 #$t1 + mov 0($sbox,$acc2,8),$acc2 #$t2 + + and \$0x00ff0000,$acc0 + and \$0x00ff0000,$acc1 + and \$0x00ff0000,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t3 + mov 2($sbox,$acc1,8),$acc1 #$t0 + mov 2($sbox,$acc2,8),$acc2 #$t1 + + and \$0x00ff0000,$acc0 + and \$0xff000000,$acc1 + and \$0xff000000,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + mov 16+12($key),$s3 + mov 2($sbox,$acc0,8),$acc0 #$t2 + mov 2($sbox,$acc1,8),$acc1 #$t3 + mov 16+0($key),$s0 + + and \$0xff000000,$acc0 + and \$0xff000000,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub encstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" lea 16($key),$key\n" if ($i==0); + + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" mov 0($sbox,$out,8),$out\n"; + + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + $code.=" xor 4*$i($key),$out\n"; + + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub enclast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + + $code.=" mov 2($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $code.=" and \$0x000000ff,$out\n"; + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" mov 0($sbox,$tmp0,8),$tmp0\n"; + $code.=" mov 0($sbox,$tmp1,8),$tmp1\n"; + $code.=" mov 2($sbox,$tmp2,8),$tmp2\n"; + + $code.=" and \$0x0000ff00,$tmp0\n"; + $code.=" and \$0x00ff0000,$tmp1\n"; + $code.=" and \$0xff000000,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_encrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Lenc_loop +.align 16 +.Lenc_loop: +___ + if ($verticalspin) { &encvert(); } + else { &encstep(0,$s0,$s1,$s2,$s3); + &encstep(1,$s1,$s2,$s3,$s0); + &encstep(2,$s2,$s3,$s0,$s1); + &encstep(3,$s3,$s0,$s1,$s2); + } +$code.=<<___; + sub \$1,$rnds + jnz .Lenc_loop +___ + if ($verticalspin) { &enclastvert(); } + else { &enclast(0,$s0,$s1,$s2,$s3); + &enclast(1,$s1,$s2,$s3,$s0); + &enclast(2,$s2,$s3,$s0,$s1); + &enclast(3,$s3,$s0,$s1,$s2); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt +___ + +# void AES_encrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_encrypt +.type AES_encrypt,\@function,3 +.align 16 +AES_encrypt: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov %rdx,$key + mov %rdi,$inp + mov %rsi,$out + + .picmeup $sbox + lea AES_Te-.($sbox),$sbox + + mov 0($inp),$s0 + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + + call _x86_64_AES_encrypt + + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret +.size AES_encrypt,.-AES_encrypt +___ + +#------------------------------------------------------------------# + +sub decvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s1")`,$acc0 + shr \$16,$s0 + movzb `&hi("$s2")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + mov 12($key),$s3 + movzb `&hi("$s0")`,$acc2 + xor 1($sbox,$acc0,8),$t2 + mov 0($key),$s0 + xor 1($sbox,$acc2,8),$t3 + + xor $t0,$s0 + mov 4($key),$s1 + mov 8($key),$s2 + xor $t2,$s2 + xor $t1,$s1 + xor $t3,$s3 +___ +} + +sub declastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb 2048($sbox,$acc0,1),$t0 + movzb 2048($sbox,$acc1,1),$t1 + movzb 2048($sbox,$acc2,1),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + movzb 2048($sbox,$acc0,1),$t3 + movzb 2048($sbox,$acc1,1),$acc1 #$t0 + movzb 2048($sbox,$acc2,1),$acc2 #$t1 + + shl \$8,$acc1 + shl \$8,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s3 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s0 + movzb 2048($sbox,$acc0,1),$acc0 #$t2 + movzb 2048($sbox,$acc1,1),$acc1 #$t3 + + shl \$8,$acc0 + shl \$8,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + movzb 2048($sbox,$acc0,1),$acc0 #$t0 + movzb 2048($sbox,$acc1,1),$acc1 #$t1 + movzb 2048($sbox,$acc2,1),$acc2 #$t2 + + shl \$16,$acc0 + shl \$16,$acc1 + shl \$16,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb 2048($sbox,$acc0,1),$acc0 #$t3 + movzb 2048($sbox,$acc1,1),$acc1 #$t0 + movzb 2048($sbox,$acc2,1),$acc2 #$t1 + + shl \$16,$acc0 + shl \$24,$acc1 + shl \$24,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + mov 16+12($key),$s3 + movzb 2048($sbox,$acc0,1),$acc0 #$t2 + movzb 2048($sbox,$acc1,1),$acc1 #$t3 + mov 16+0($key),$s0 + + shl \$24,$acc0 + shl \$24,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub decstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" mov 0($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub declast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" movzb 2048($sbox,$out,1),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n"; + $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n"; + $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n"; + + $code.=" shl \$8,$tmp0\n"; + $code.=" shl \$16,$tmp1\n"; + $code.=" shl \$24,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_decrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Ldec_loop +.align 16 +.Ldec_loop: +___ + if ($verticalspin) { &decvert(); } + else { &decstep(0,$s0,$s3,$s2,$s1); + &decstep(1,$s1,$s0,$s3,$s2); + &decstep(2,$s2,$s1,$s0,$s3); + &decstep(3,$s3,$s2,$s1,$s0); + $code.=<<___; + lea 16($key),$key + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 +___ + } +$code.=<<___; + sub \$1,$rnds + jnz .Ldec_loop +___ + if ($verticalspin) { &declastvert(); } + else { &declast(0,$s0,$s3,$s2,$s1); + &declast(1,$s1,$s0,$s3,$s2); + &declast(2,$s2,$s1,$s0,$s3); + &declast(3,$s3,$s2,$s1,$s0); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt +___ + +# void AES_decrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_decrypt +.type AES_decrypt,\@function,3 +.align 16 +AES_decrypt: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov %rdx,$key + mov %rdi,$inp + mov %rsi,$out + + .picmeup $sbox + lea AES_Td-.($sbox),$sbox + + # prefetch Td4 + lea 2048+128($sbox),$sbox; + mov 0-128($sbox),$s0 + mov 32-128($sbox),$s1 + mov 64-128($sbox),$s2 + mov 96-128($sbox),$s3 + mov 128-128($sbox),$s0 + mov 160-128($sbox),$s1 + mov 192-128($sbox),$s2 + mov 224-128($sbox),$s3 + lea -2048-128($sbox),$sbox; + + mov 0($inp),$s0 + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + + call _x86_64_AES_decrypt + + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret +.size AES_decrypt,.-AES_decrypt +___ +#------------------------------------------------------------------# + +sub enckey() +{ +$code.=<<___; + movz %dl,%esi # rk[i]>>0 + mov 2(%rbp,%rsi,8),%ebx + movz %dh,%esi # rk[i]>>8 + and \$0xFF000000,%ebx + xor %ebx,%eax + + mov 2(%rbp,%rsi,8),%ebx + shr \$16,%edx + and \$0x000000FF,%ebx + movz %dl,%esi # rk[i]>>16 + xor %ebx,%eax + + mov 0(%rbp,%rsi,8),%ebx + movz %dh,%esi # rk[i]>>24 + and \$0x0000FF00,%ebx + xor %ebx,%eax + + mov 0(%rbp,%rsi,8),%ebx + and \$0x00FF0000,%ebx + xor %ebx,%eax + + xor 2048(%rbp,%rcx,4),%eax # rcon +___ +} + +# int AES_set_encrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_encrypt_key +.type AES_set_encrypt_key,\@function,3 +.align 16 +AES_set_encrypt_key: + push %rbx + push %rbp + + mov %esi,%ecx # %ecx=bits + mov %rdi,%rsi # %rsi=userKey + mov %rdx,%rdi # %rdi=key + + test \$-1,%rsi + jz .Lbadpointer + test \$-1,%rdi + jz .Lbadpointer + + .picmeup %rbp + lea AES_Te-.(%rbp),%rbp + + cmp \$128,%ecx + je .L10rounds + cmp \$192,%ecx + je .L12rounds + cmp \$256,%ecx + je .L14rounds + mov \$-2,%rax # invalid number of bits + jmp .Lexit + +.L10rounds: + mov 0(%rsi),%eax # copy first 4 dwords + mov 4(%rsi),%ebx + mov 8(%rsi),%ecx + mov 12(%rsi),%edx + mov %eax,0(%rdi) + mov %ebx,4(%rdi) + mov %ecx,8(%rdi) + mov %edx,12(%rdi) + + xor %ecx,%ecx + jmp .L10shortcut +.align 4 +.L10loop: + mov 0(%rdi),%eax # rk[0] + mov 12(%rdi),%edx # rk[3] +.L10shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,16(%rdi) # rk[4] + xor 4(%rdi),%eax + mov %eax,20(%rdi) # rk[5] + xor 8(%rdi),%eax + mov %eax,24(%rdi) # rk[6] + xor 12(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + add \$1,%ecx + lea 16(%rdi),%rdi + cmp \$10,%ecx + jl .L10loop + + movl \$10,80(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L12rounds: + mov 0(%rsi),%eax # copy first 6 dwords + mov 4(%rsi),%ebx + mov 8(%rsi),%ecx + mov 12(%rsi),%edx + mov %eax,0(%rdi) + mov %ebx,4(%rdi) + mov %ecx,8(%rdi) + mov %edx,12(%rdi) + mov 16(%rsi),%ecx + mov 20(%rsi),%edx + mov %ecx,16(%rdi) + mov %edx,20(%rdi) + + xor %ecx,%ecx + jmp .L12shortcut +.align 4 +.L12loop: + mov 0(%rdi),%eax # rk[0] + mov 20(%rdi),%edx # rk[5] +.L12shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,24(%rdi) # rk[6] + xor 4(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + xor 8(%rdi),%eax + mov %eax,32(%rdi) # rk[8] + xor 12(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + + cmp \$7,%ecx + je .L12break + add \$1,%ecx + + xor 16(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 20(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + lea 24(%rdi),%rdi + jmp .L12loop +.L12break: + movl \$12,72(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L14rounds: + mov 0(%rsi),%eax # copy first 8 dwords + mov 4(%rsi),%ebx + mov 8(%rsi),%ecx + mov 12(%rsi),%edx + mov %eax,0(%rdi) + mov %ebx,4(%rdi) + mov %ecx,8(%rdi) + mov %edx,12(%rdi) + mov 16(%rsi),%eax + mov 20(%rsi),%ebx + mov 24(%rsi),%ecx + mov 28(%rsi),%edx + mov %eax,16(%rdi) + mov %ebx,20(%rdi) + mov %ecx,24(%rdi) + mov %edx,28(%rdi) + + xor %ecx,%ecx + jmp .L14shortcut +.align 4 +.L14loop: + mov 28(%rdi),%edx # rk[4] +.L14shortcut: + mov 0(%rdi),%eax # rk[0] +___ + &enckey (); +$code.=<<___; + mov %eax,32(%rdi) # rk[8] + xor 4(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + xor 8(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 12(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + cmp \$6,%ecx + je .L14break + add \$1,%ecx + + mov %eax,%edx + mov 16(%rdi),%eax # rk[4] + movz %dl,%esi # rk[11]>>0 + mov 2(%rbp,%rsi,8),%ebx + movz %dh,%esi # rk[11]>>8 + and \$0x000000FF,%ebx + xor %ebx,%eax + + mov 0(%rbp,%rsi,8),%ebx + shr \$16,%edx + and \$0x0000FF00,%ebx + movz %dl,%esi # rk[11]>>16 + xor %ebx,%eax + + mov 0(%rbp,%rsi,8),%ebx + movz %dh,%esi # rk[11]>>24 + and \$0x00FF0000,%ebx + xor %ebx,%eax + + mov 2(%rbp,%rsi,8),%ebx + and \$0xFF000000,%ebx + xor %ebx,%eax + + mov %eax,48(%rdi) # rk[12] + xor 20(%rdi),%eax + mov %eax,52(%rdi) # rk[13] + xor 24(%rdi),%eax + mov %eax,56(%rdi) # rk[14] + xor 28(%rdi),%eax + mov %eax,60(%rdi) # rk[15] + + lea 32(%rdi),%rdi + jmp .L14loop +.L14break: + movl \$14,48(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.Lbadpointer: + mov \$-1,%rax +.Lexit: + pop %rbp + pop %rbx + ret +.size AES_set_encrypt_key,.-AES_set_encrypt_key +___ + +sub deckey() +{ my ($i,$ptr,$te,$td) = @_; +$code.=<<___; + mov $i($ptr),%eax + mov %eax,%edx + movz %ah,%ebx + shr \$16,%edx + and \$0xFF,%eax + movzb 2($te,%rax,8),%rax + movzb 2($te,%rbx,8),%rbx + mov 0($td,%rax,8),%eax + xor 3($td,%rbx,8),%eax + movzb %dh,%ebx + and \$0xFF,%edx + movzb 2($te,%rdx,8),%rdx + movzb 2($te,%rbx,8),%rbx + xor 2($td,%rdx,8),%eax + xor 1($td,%rbx,8),%eax + mov %eax,$i($ptr) +___ +} + +# int AES_set_decrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_decrypt_key +.type AES_set_decrypt_key,\@function,3 +.align 16 +AES_set_decrypt_key: + push %rdx + call AES_set_encrypt_key + cmp \$0,%eax + je .Lproceed + lea 24(%rsp),%rsp + ret +.Lproceed: + mov (%rsp),%r8 # restore key schedule + mov %rbx,(%rsp) + + mov 240(%r8),%ecx # pull number of rounds + xor %rdi,%rdi + lea (%rdi,%rcx,4),%rcx + mov %r8,%rsi + lea (%r8,%rcx,4),%rdi # pointer to last chunk +.align 4 +.Linvert: + mov 0(%rsi),%rax + mov 8(%rsi),%rbx + mov 0(%rdi),%rcx + mov 8(%rdi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,0(%rsi) + mov %rdx,8(%rsi) + lea 16(%rsi),%rsi + lea -16(%rdi),%rdi + cmp %rsi,%rdi + jne .Linvert + + .picmeup %r9 + lea AES_Td-.(%r9),%rdi + lea AES_Te-AES_Td(%rdi),%r9 + + mov %r8,%rsi + mov 240(%r8),%ecx # pull number of rounds + sub \$1,%ecx +.align 4 +.Lpermute: + lea 16(%rsi),%rsi +___ + &deckey (0,"%rsi","%r9","%rdi"); + &deckey (4,"%rsi","%r9","%rdi"); + &deckey (8,"%rsi","%r9","%rdi"); + &deckey (12,"%rsi","%r9","%rdi"); +$code.=<<___; + sub \$1,%ecx + jnz .Lpermute + + xor %rax,%rax + pop %rbx + ret +.size AES_set_decrypt_key,.-AES_set_decrypt_key +___ + +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -8(%rsp) return address +my $_rsp="0(%rsp)"; # saved %rsp +my $_len="8(%rsp)"; # copy of 3rd parameter, length +my $_key="16(%rsp)"; # copy of 4th parameter, key +my $_ivp="24(%rsp)"; # copy of 5th parameter, ivp +my $keyp="32(%rsp)"; # one to pass as $key +my $ivec="40(%rsp)"; # ivec[16] +my $aes_key="56(%rsp)"; # copy of aes_key +my $mark="56+240(%rsp)"; # copy of aes_key->rounds + +$code.=<<___; +.globl AES_cbc_encrypt +.type AES_cbc_encrypt,\@function,6 +.align 16 +AES_cbc_encrypt: + cmp \$0,%rdx # check length + je .Lcbc_just_ret + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + cld + mov %r9d,%r9d # clear upper half of enc + + .picmeup $sbox +.Lcbc_pic_point: + + cmp \$0,%r9 + je .LDECRYPT + + lea AES_Te-.Lcbc_pic_point($sbox),$sbox + + # allocate aligned stack frame... + lea -64-248(%rsp),$key + and \$-64,$key + + # ... and make it doesn't alias with AES_Te modulo 4096 + mov $sbox,%r10 + lea 2048($sbox),%r11 + mov $key,%r12 + and \$0xFFF,%r10 # s = $sbox&0xfff + and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff + and \$0xFFF,%r12 # p = %rsp&0xfff + + cmp %r11,%r12 # if (p=>e) %rsp =- (p-e); + jb .Lcbc_te_break_out + sub %r11,%r12 + sub %r12,$key + jmp .Lcbc_te_ok +.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz + sub %r10,%r12 + and \$0xFFF,%r12 + add \$320,%r12 + sub %r12,$key +.align 4 +.Lcbc_te_ok: + + xchg %rsp,$key + add \$8,%rsp # reserve for return address! + mov $key,$_rsp # save %rsp + mov %rdx,$_len # save copy of len + mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + movl \$0,$mark # copy of aes_key->rounds = 0; + mov %r8,%rbp # rearrange input arguments + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + + # do we copy key schedule to stack? + mov $key,%r10 + sub $sbox,%r10 + and \$0xfff,%r10 + cmp \$2048,%r10 + jb .Lcbc_do_ecopy + cmp \$4096-248,%r10 + jb .Lcbc_skip_ecopy +.align 4 +.Lcbc_do_ecopy: + mov $key,%rsi + lea $aes_key,%rdi + lea $aes_key,$key + mov \$240/8,%ecx + .long 0x90A548F3 # rep movsq + mov (%rsi),%eax # copy aes_key->rounds + mov %eax,(%rdi) +.Lcbc_skip_ecopy: + mov $key,$keyp # save key pointer + + mov \$16,%ecx +.align 4 +.Lcbc_prefetch_te: + mov 0($sbox),%r10 + mov 32($sbox),%r11 + mov 64($sbox),%r12 + mov 96($sbox),%r13 + lea 128($sbox),$sbox + sub \$1,%ecx + jnz .Lcbc_prefetch_te + sub \$2048,$sbox + + test \$-16,%rdx # check upon length + mov %rdx,%r10 + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + jz .Lcbc_enc_tail # short input... + +.align 4 +.Lcbc_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $inp,$ivec # if ($verticalspin) save inp + + mov $keyp,$key # restore key + call _x86_64_AES_encrypt + + mov $ivec,$inp # if ($verticalspin) restore inp + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov $_len,%r10 + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + mov %r10,$_len + jnz .Lcbc_enc_loop + test \$15,%r10 + jnz .Lcbc_enc_tail + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + +.align 4 +.Lcbc_cleanup: + cmpl \$0,$mark # was the key schedule copied? + lea $aes_key,%rdi + mov $_rsp,%rsp + je .Lcbc_exit + mov \$240/8,%ecx + xor %rax,%rax + .long 0x90AB48F3 # rep stosq +.Lcbc_exit: + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx +.Lcbc_just_ret: + ret +.align 4 +.Lcbc_enc_tail: + cmp $inp,$out + je .Lcbc_enc_in_place + mov %r10,%rcx + mov $inp,%rsi + mov $out,%rdi + .long 0xF689A4F3 # rep movsb +.Lcbc_enc_in_place: + mov \$16,%rcx # zero tail + sub %r10,%rcx + xor %rax,%rax + .long 0xF689AAF3 # rep stosb + mov $out,$inp # this is not a mistake! + movq \$16,$_len # len=16 + jmp .Lcbc_enc_loop # one more spin... +#----------------------------- DECRYPT -----------------------------# +.align 16 +.LDECRYPT: + lea AES_Td-.Lcbc_pic_point($sbox),$sbox + + # allocate aligned stack frame... + lea -64-248(%rsp),$key + and \$-64,$key + + # ... and make it doesn't alias with AES_Td modulo 4096 + mov $sbox,%r10 + lea 2304($sbox),%r11 + mov $key,%r12 + and \$0xFFF,%r10 # s = $sbox&0xfff + and \$0xFFF,%r11 # e = ($sbox+2048+256)&0xfff + and \$0xFFF,%r12 # p = %rsp&0xfff + + cmp %r11,%r12 # if (p=>e) %rsp =- (p-e); + jb .Lcbc_td_break_out + sub %r11,%r12 + sub %r12,$key + jmp .Lcbc_td_ok +.Lcbc_td_break_out: # else %rsp -= (p-s)&0xfff + framesz + sub %r10,%r12 + and \$0xFFF,%r12 + add \$320,%r12 + sub %r12,$key +.align 4 +.Lcbc_td_ok: + + xchg %rsp,$key + add \$8,%rsp # reserve for return address! + mov $key,$_rsp # save %rsp + mov %rdx,$_len # save copy of len + mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + movl \$0,$mark # copy of aes_key->rounds = 0; + mov %r8,%rbp # rearrange input arguments + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + + # do we copy key schedule to stack? + mov $key,%r10 + sub $sbox,%r10 + and \$0xfff,%r10 + cmp \$2304,%r10 + jb .Lcbc_do_dcopy + cmp \$4096-248,%r10 + jb .Lcbc_skip_dcopy +.align 4 +.Lcbc_do_dcopy: + mov $key,%rsi + lea $aes_key,%rdi + lea $aes_key,$key + mov \$240/8,%ecx + .long 0x90A548F3 # rep movsq + mov (%rsi),%eax # copy aes_key->rounds + mov %eax,(%rdi) +.Lcbc_skip_dcopy: + mov $key,$keyp # save key pointer + + mov \$18,%ecx +.align 4 +.Lcbc_prefetch_td: + mov 0($sbox),%r10 + mov 32($sbox),%r11 + mov 64($sbox),%r12 + mov 96($sbox),%r13 + lea 128($sbox),$sbox + sub \$1,%ecx + jnz .Lcbc_prefetch_td + sub \$2304,$sbox + + cmp $inp,$out + je .Lcbc_dec_in_place + + mov %rbp,$ivec +.align 4 +.Lcbc_dec_loop: + mov 0($inp),$s0 # read input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $inp,8+$ivec # if ($verticalspin) save inp + + mov $keyp,$key # restore key + call _x86_64_AES_decrypt + + mov $ivec,%rbp # load ivp + mov 8+$ivec,$inp # if ($verticalspin) restore inp + xor 0(%rbp),$s0 # xor iv + xor 4(%rbp),$s1 + xor 8(%rbp),$s2 + xor 12(%rbp),$s3 + mov $inp,%rbp # current input, next iv + + mov $_len,%r10 # load len + sub \$16,%r10 + jc .Lcbc_dec_partial + mov %r10,$_len # update len + mov %rbp,$ivec # update ivp + + mov $s0,0($out) # write output + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jnz .Lcbc_dec_loop +.Lcbc_dec_end: + mov $_ivp,%r12 # load user ivp + mov 0(%rbp),%r10 # load iv + mov 8(%rbp),%r11 + mov %r10,0(%r12) # copy back to user + mov %r11,8(%r12) + jmp .Lcbc_cleanup + +.align 4 +.Lcbc_dec_partial: + mov $s0,0+$ivec # dump output to stack + mov $s1,4+$ivec + mov $s2,8+$ivec + mov $s3,12+$ivec + mov $out,%rdi + lea $ivec,%rsi + mov \$16,%rcx + add %r10,%rcx # number of bytes to copy + .long 0xF689A4F3 # rep movsb + jmp .Lcbc_dec_end + +.align 16 +.Lcbc_dec_in_place: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + + mov $inp,$ivec # if ($verticalspin) save inp + mov $keyp,$key + call _x86_64_AES_decrypt + + mov $ivec,$inp # if ($verticalspin) restore inp + mov $_ivp,%rbp + xor 0(%rbp),$s0 + xor 4(%rbp),$s1 + xor 8(%rbp),$s2 + xor 12(%rbp),$s3 + + mov 0($inp),%r10 # copy input to iv + mov 8($inp),%r11 + mov %r10,0(%rbp) + mov %r11,8(%rbp) + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov $_len,%rcx + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%rcx + jc .Lcbc_dec_in_place_partial + mov %rcx,$_len + jnz .Lcbc_dec_in_place + jmp .Lcbc_cleanup + +.align 4 +.Lcbc_dec_in_place_partial: + # one can argue if this is actually required + lea ($out,%rcx),%rdi + lea (%rbp,%rcx),%rsi + neg %rcx + .long 0xF689A4F3 # rep movsb # restore tail + jmp .Lcbc_cleanup +.size AES_cbc_encrypt,.-AES_cbc_encrypt +___ +} + +$code.=<<___; +.globl AES_Te +.align 64 +AES_Te: +___ + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); +#rcon: +$code.=<<___; + .long 0x00000001, 0x00000002, 0x00000004, 0x00000008 + .long 0x00000010, 0x00000020, 0x00000040, 0x00000080 + .long 0x0000001b, 0x00000036, 0, 0, 0, 0, 0, 0 +___ +$code.=<<___; +.globl AES_Td +.align 64 +AES_Td: +___ + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); +#Td4: + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/crypto/asn1/Makefile b/crypto/asn1/Makefile index f67c5ebd711a..63066899d0bd 100644 --- a/crypto/asn1/Makefile +++ b/crypto/asn1/Makefile @@ -26,7 +26,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ t_req.c t_x509.c t_x509a.c t_crl.c t_pkey.c t_spki.c t_bitst.c \ tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ f_int.c f_string.c n_pkey.c \ - f_enum.c a_hdr.c x_pkey.c a_bool.c x_exten.c \ + f_enum.c a_hdr.c x_pkey.c a_bool.c x_exten.c asn_mime.c \ asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_meth.c a_bytes.c a_strnid.c \ evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ @@ -38,7 +38,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ t_req.o t_x509.o t_x509a.o t_crl.o t_pkey.o t_spki.o t_bitst.o \ tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \ f_int.o f_string.o n_pkey.o \ - f_enum.o a_hdr.o x_pkey.o a_bool.o x_exten.o \ + f_enum.o a_hdr.o x_pkey.o a_bool.o x_exten.o asn_mime.o \ asn1_gen.o asn1_par.o asn1_lib.o asn1_err.o a_meth.o a_bytes.o a_strnid.o \ evp_asn1.o asn_pack.o p5_pbe.o p5_pbev2.o p8_pkey.o asn_moid.o @@ -213,11 +213,11 @@ a_meth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h a_meth.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h a_meth.o: ../../include/openssl/symhacks.h ../cryptlib.h a_meth.c a_object.o: ../../e_os.h ../../include/openssl/asn1.h -a_object.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -a_object.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -a_object.o: ../../include/openssl/err.h ../../include/openssl/lhash.h -a_object.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -a_object.o: ../../include/openssl/opensslconf.h +a_object.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +a_object.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +a_object.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +a_object.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +a_object.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h a_object.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h a_object.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h a_object.o: ../../include/openssl/symhacks.h ../cryptlib.h a_object.c @@ -292,7 +292,8 @@ a_type.o: ../../e_os.h ../../include/openssl/asn1.h a_type.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h a_type.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h a_type.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -a_type.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h +a_type.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +a_type.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h a_type.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h a_type.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h a_type.o: ../../include/openssl/symhacks.h ../cryptlib.h a_type.c @@ -362,6 +363,20 @@ asn1_par.o: ../../include/openssl/opensslconf.h asn1_par.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h asn1_par.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h asn1_par.o: ../../include/openssl/symhacks.h ../cryptlib.h asn1_par.c +asn_mime.o: ../../e_os.h ../../include/openssl/asn1.h +asn_mime.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h +asn_mime.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +asn_mime.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +asn_mime.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +asn_mime.o: ../../include/openssl/err.h ../../include/openssl/evp.h +asn_mime.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +asn_mime.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +asn_mime.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +asn_mime.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +asn_mime.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +asn_mime.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +asn_mime.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +asn_mime.o: ../cryptlib.h asn_mime.c asn_moid.o: ../../e_os.h ../../include/openssl/asn1.h asn_moid.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h asn_moid.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index a36356e34474..dc980421d098 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -62,6 +62,7 @@ #include <openssl/buffer.h> #include <openssl/asn1.h> #include <openssl/objects.h> +#include <openssl/bn.h> int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) { diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index a6acef16f3b3..36beceacdb07 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -59,6 +59,7 @@ #include <stdio.h> #include "cryptlib.h" #include <openssl/asn1t.h> +#include <openssl/objects.h> int ASN1_TYPE_get(ASN1_TYPE *a) { @@ -79,6 +80,31 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) a->value.ptr=value; } +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) + { + if (!value || (type == V_ASN1_BOOLEAN)) + { + void *p = (void *)value; + ASN1_TYPE_set(a, type, p); + } + else if (type == V_ASN1_OBJECT) + { + ASN1_OBJECT *odup; + odup = OBJ_dup(value); + if (!odup) + return 0; + ASN1_TYPE_set(a, type, odup); + } + else + { + ASN1_STRING *sdup; + sdup = ASN1_STRING_dup((ASN1_STRING *)value); + if (!sdup) + return 0; + ASN1_TYPE_set(a, type, sdup); + } + return 1; + } IMPLEMENT_STACK_OF(ASN1_TYPE) IMPLEMENT_ASN1_SET_OF(ASN1_TYPE) diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 30f1eecd5b90..424cd348bb5e 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -158,7 +158,12 @@ extern "C" { #define MBSTRING_BMP (MBSTRING_FLAG|2) #define MBSTRING_UNIV (MBSTRING_FLAG|4) +#define SMIME_OLDMIME 0x400 +#define SMIME_CRLFEOL 0x800 +#define SMIME_STREAM 0x1000 + struct X509_algor_st; +DECLARE_STACK_OF(X509_ALGOR) #define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */ #define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */ @@ -218,6 +223,13 @@ typedef struct asn1_object_st * be inserted in the memory buffer */ #define ASN1_STRING_FLAG_NDEF 0x010 + +/* This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been + * accessed. The flag will be reset when content has been written to it. + */ +#define ASN1_STRING_FLAG_CONT 0x020 + /* This is the base type that holds just about everything :-) */ typedef struct asn1_string_st { @@ -311,8 +323,8 @@ typedef struct ASN1_VALUE_st ASN1_VALUE; int i2d_##name##_NDEF(name *a, unsigned char **out); #define DECLARE_ASN1_FUNCTIONS_const(name) \ - name *name##_new(void); \ - void name##_free(name *a); + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) #define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ type *name##_new(void); \ @@ -322,6 +334,17 @@ typedef struct ASN1_VALUE_st ASN1_VALUE; #define I2D_OF(type) int (*)(type *,unsigned char **) #define I2D_OF_const(type) int (*)(const type *,unsigned char **) +#define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +#define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +#define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +#define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +#define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + #define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) #define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **) #define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) @@ -511,6 +534,7 @@ typedef struct asn1_type_st * contain the set or sequence bytes */ ASN1_STRING * set; ASN1_STRING * sequence; + ASN1_VALUE * asn1_value; } value; } ASN1_TYPE; @@ -741,6 +765,7 @@ DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) int ASN1_TYPE_get(ASN1_TYPE *a); void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); ASN1_OBJECT * ASN1_OBJECT_new(void ); void ASN1_OBJECT_free(ASN1_OBJECT *a); @@ -763,6 +788,7 @@ int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b); /* Since this is used to store all sorts of things, via macros, for now, make its data void * */ int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); int ASN1_STRING_length(ASN1_STRING *x); void ASN1_STRING_length_set(ASN1_STRING *x, int n); int ASN1_STRING_type(ASN1_STRING *x); @@ -902,23 +928,47 @@ int ASN1_object_size(int constructed, int length, int tag); /* Used to implement other functions */ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x); + #define ASN1_dup_of(type,i2d,d2i,x) \ - ((type *(*)(I2D_OF(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x) + ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(type, x))) + #define ASN1_dup_of_const(type,i2d,d2i,x) \ - ((type *(*)(I2D_OF_const(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x) + ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(const type, x))) void *ASN1_item_dup(const ASN1_ITEM *it, void *x); +/* ASN1 alloc/free macros for when a type is only used internally */ + +#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) +#define M_ASN1_free_of(x, type) \ + ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) + #ifndef OPENSSL_NO_FP_API void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x); + #define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ - ((type *(*)(type *(*)(void),D2I_OF(type),FILE *,type **))openssl_fcast(ASN1_d2i_fp))(xnew,d2i,in,x) + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x); + #define ASN1_i2d_fp_of(type,i2d,out,x) \ - ((int (*)(I2D_OF(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x) + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + #define ASN1_i2d_fp_of_const(type,i2d,out,x) \ - ((int (*)(I2D_OF_const(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x) + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags); #endif @@ -927,14 +977,26 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); #ifndef OPENSSL_NO_BIO void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x); + #define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ - ((type *(*)(type *(*)(void),D2I_OF(type),BIO *,type **))openssl_fcast(ASN1_d2i_bio))(xnew,d2i,in,x) + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x); + #define ASN1_i2d_bio_of(type,i2d,out,x) \ - ((int (*)(I2D_OF(type),BIO *,type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x) + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + #define ASN1_i2d_bio_of_const(type,i2d,out,x) \ - ((int (*)(I2D_OF_const(type),BIO *,const type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x) + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a); int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a); @@ -977,8 +1039,12 @@ void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i); void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it); ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_OCTET_STRING **oct); + #define ASN1_pack_string_of(type,obj,i2d,oct) \ - ((ASN1_STRING *(*)(type *,I2D_OF(type),ASN1_OCTET_STRING **))openssl_fcast(ASN1_pack_string))(obj,i2d,oct) + (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \ + CHECKED_I2D_OF(type, i2d), \ + oct)) + ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct); void ASN1_STRING_set_default_mask(unsigned long mask); @@ -1009,7 +1075,17 @@ void ASN1_add_oid_module(void); ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf); ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf); - + +typedef int asn1_output_data_fn(BIO *out, BIO *data, ASN1_VALUE *val, int flags, + const ASN1_ITEM *it); + +int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, + asn1_output_data_fn *data_fn, + const ASN1_ITEM *it); +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -1059,6 +1135,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_ASN1_ITEM_VERIFY 197 #define ASN1_F_ASN1_MBSTRING_NCOPY 122 #define ASN1_F_ASN1_OBJECT_NEW 123 +#define ASN1_F_ASN1_OUTPUT_DATA 207 #define ASN1_F_ASN1_PACK_STRING 124 #define ASN1_F_ASN1_PCTX_NEW 205 #define ASN1_F_ASN1_PKCS5_PBE_SET 125 @@ -1078,6 +1155,8 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_ASN1_UNPACK_STRING 136 #define ASN1_F_ASN1_UTCTIME_SET 187 #define ASN1_F_ASN1_VERIFY 137 +#define ASN1_F_B64_READ_ASN1 208 +#define ASN1_F_B64_WRITE_ASN1 209 #define ASN1_F_BITSTR_CB 180 #define ASN1_F_BN_TO_ASN1_ENUMERATED 138 #define ASN1_F_BN_TO_ASN1_INTEGER 139 @@ -1118,6 +1197,8 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_PARSE_TAGGING 182 #define ASN1_F_PKCS5_PBE2_SET 167 #define ASN1_F_PKCS5_PBE_SET 202 +#define ASN1_F_SMIME_READ_ASN1 210 +#define ASN1_F_SMIME_TEXT 211 #define ASN1_F_X509_CINF_NEW 168 #define ASN1_F_X509_CRL_ADD0_REVOKED 169 #define ASN1_F_X509_INFO_NEW 170 @@ -1129,6 +1210,8 @@ void ERR_load_ASN1_strings(void); /* Reason codes. */ #define ASN1_R_ADDING_OBJECT 171 +#define ASN1_R_ASN1_PARSE_ERROR 198 +#define ASN1_R_ASN1_SIG_PARSE_ERROR 199 #define ASN1_R_AUX_ERROR 100 #define ASN1_R_BAD_CLASS 101 #define ASN1_R_BAD_OBJECT_HEADER 102 @@ -1175,6 +1258,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 #define ASN1_R_INVALID_BMPSTRING_LENGTH 129 #define ASN1_R_INVALID_DIGIT 130 +#define ASN1_R_INVALID_MIME_TYPE 200 #define ASN1_R_INVALID_MODIFIER 186 #define ASN1_R_INVALID_NUMBER 187 #define ASN1_R_INVALID_SEPARATOR 131 @@ -1184,6 +1268,9 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_IV_TOO_LARGE 135 #define ASN1_R_LENGTH_ERROR 136 #define ASN1_R_LIST_ERROR 188 +#define ASN1_R_MIME_NO_CONTENT_TYPE 201 +#define ASN1_R_MIME_PARSE_ERROR 202 +#define ASN1_R_MIME_SIG_PARSE_ERROR 203 #define ASN1_R_MISSING_EOC 137 #define ASN1_R_MISSING_SECOND_NUMBER 138 #define ASN1_R_MISSING_VALUE 189 @@ -1193,7 +1280,11 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_NON_HEX_CHARACTERS 141 #define ASN1_R_NOT_ASCII_FORMAT 190 #define ASN1_R_NOT_ENOUGH_DATA 142 +#define ASN1_R_NO_CONTENT_TYPE 204 #define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +#define ASN1_R_NO_MULTIPART_BODY_FAILURE 205 +#define ASN1_R_NO_MULTIPART_BOUNDARY 206 +#define ASN1_R_NO_SIG_CONTENT_TYPE 207 #define ASN1_R_NULL_IS_WRONG_LENGTH 144 #define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 #define ASN1_R_ODD_NUMBER_OF_CHARS 145 @@ -1203,6 +1294,8 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 #define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192 #define ASN1_R_SHORT_LINE 150 +#define ASN1_R_SIG_INVALID_MIME_TYPE 208 +#define ASN1_R_STREAMING_NOT_SUPPORTED 209 #define ASN1_R_STRING_TOO_LONG 151 #define ASN1_R_STRING_TOO_SHORT 152 #define ASN1_R_TAG_VALUE_TOO_HIGH 153 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index f6b5c3f3dd77..f8a3e2e6cd01 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -1,6 +1,6 @@ /* crypto/asn1/asn1_err.c */ /* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,6 +110,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"}, {ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"}, {ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW), "ASN1_OBJECT_new"}, +{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA), "ASN1_OUTPUT_DATA"}, {ERR_FUNC(ASN1_F_ASN1_PACK_STRING), "ASN1_pack_string"}, {ERR_FUNC(ASN1_F_ASN1_PCTX_NEW), "ASN1_PCTX_NEW"}, {ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET), "ASN1_PKCS5_PBE_SET"}, @@ -129,6 +130,8 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING), "ASN1_unpack_string"}, {ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET), "ASN1_UTCTIME_set"}, {ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"}, +{ERR_FUNC(ASN1_F_B64_READ_ASN1), "B64_READ_ASN1"}, +{ERR_FUNC(ASN1_F_B64_WRITE_ASN1), "B64_WRITE_ASN1"}, {ERR_FUNC(ASN1_F_BITSTR_CB), "BITSTR_CB"}, {ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED), "BN_to_ASN1_ENUMERATED"}, {ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER), "BN_to_ASN1_INTEGER"}, @@ -169,6 +172,8 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_FUNC(ASN1_F_PARSE_TAGGING), "PARSE_TAGGING"}, {ERR_FUNC(ASN1_F_PKCS5_PBE2_SET), "PKCS5_pbe2_set"}, {ERR_FUNC(ASN1_F_PKCS5_PBE_SET), "PKCS5_pbe_set"}, +{ERR_FUNC(ASN1_F_SMIME_READ_ASN1), "SMIME_read_ASN1"}, +{ERR_FUNC(ASN1_F_SMIME_TEXT), "SMIME_text"}, {ERR_FUNC(ASN1_F_X509_CINF_NEW), "X509_CINF_NEW"}, {ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED), "X509_CRL_add0_revoked"}, {ERR_FUNC(ASN1_F_X509_INFO_NEW), "X509_INFO_new"}, @@ -183,6 +188,8 @@ static ERR_STRING_DATA ASN1_str_functs[]= static ERR_STRING_DATA ASN1_str_reasons[]= { {ERR_REASON(ASN1_R_ADDING_OBJECT) ,"adding object"}, +{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR) ,"asn1 parse error"}, +{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) ,"asn1 sig parse error"}, {ERR_REASON(ASN1_R_AUX_ERROR) ,"aux error"}, {ERR_REASON(ASN1_R_BAD_CLASS) ,"bad class"}, {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER) ,"bad object header"}, @@ -229,6 +236,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),"integer too large for long"}, {ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH),"invalid bmpstring length"}, {ERR_REASON(ASN1_R_INVALID_DIGIT) ,"invalid digit"}, +{ERR_REASON(ASN1_R_INVALID_MIME_TYPE) ,"invalid mime type"}, {ERR_REASON(ASN1_R_INVALID_MODIFIER) ,"invalid modifier"}, {ERR_REASON(ASN1_R_INVALID_NUMBER) ,"invalid number"}, {ERR_REASON(ASN1_R_INVALID_SEPARATOR) ,"invalid separator"}, @@ -238,6 +246,9 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_IV_TOO_LARGE) ,"iv too large"}, {ERR_REASON(ASN1_R_LENGTH_ERROR) ,"length error"}, {ERR_REASON(ASN1_R_LIST_ERROR) ,"list error"}, +{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) ,"mime no content type"}, +{ERR_REASON(ASN1_R_MIME_PARSE_ERROR) ,"mime parse error"}, +{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) ,"mime sig parse error"}, {ERR_REASON(ASN1_R_MISSING_EOC) ,"missing eoc"}, {ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER),"missing second number"}, {ERR_REASON(ASN1_R_MISSING_VALUE) ,"missing value"}, @@ -247,7 +258,11 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) ,"non hex characters"}, {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) ,"not ascii format"}, {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) ,"not enough data"}, +{ERR_REASON(ASN1_R_NO_CONTENT_TYPE) ,"no content type"}, {ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"}, +{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"}, +{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"}, +{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE) ,"no sig content type"}, {ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"}, {ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"}, {ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS) ,"odd number of chars"}, @@ -257,6 +272,8 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED),"sequence not constructed"}, {ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),"sequence or set needs config"}, {ERR_REASON(ASN1_R_SHORT_LINE) ,"short line"}, +{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"}, +{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED),"streaming not supported"}, {ERR_REASON(ASN1_R_STRING_TOO_LONG) ,"string too long"}, {ERR_REASON(ASN1_R_STRING_TOO_SHORT) ,"string too short"}, {ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) ,"tag value too high"}, diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index d5ae5b2258a4..5af559ef8da7 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -393,6 +393,14 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) return(1); } +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) + { + if (str->data) + OPENSSL_free(str->data); + str->data = data; + str->length = len; + } + ASN1_STRING *ASN1_STRING_new(void) { return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); diff --git a/crypto/asn1/asn1t.h b/crypto/asn1/asn1t.h index adbc2a63dd0f..bf315e65ed38 100644 --- a/crypto/asn1/asn1t.h +++ b/crypto/asn1/asn1t.h @@ -169,6 +169,9 @@ extern "C" { #define ASN1_NDEF_SEQUENCE(tname) \ ASN1_SEQUENCE(tname) +#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + #define ASN1_SEQUENCE_cb(tname, cb) \ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ ASN1_SEQUENCE(tname) @@ -368,6 +371,10 @@ extern "C" { #define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) +/* EXPLICIT using indefinite length constructed form */ +#define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + /* EXPLICIT OPTIONAL using indefinite length constructed form */ #define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c new file mode 100644 index 000000000000..bc80b20d6323 --- /dev/null +++ b/crypto/asn1/asn_mime.c @@ -0,0 +1,876 @@ +/* asn_mime.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#include <stdio.h> +#include <ctype.h> +#include "cryptlib.h" +#include <openssl/rand.h> +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> + +/* Generalised MIME like utilities for streaming ASN1. Although many + * have a PKCS7/CMS like flavour others are more general purpose. + */ + +/* MIME format structures + * Note that all are translated to lower case apart from + * parameter values. Quotes are stripped off + */ + +typedef struct { +char *param_name; /* Param name e.g. "micalg" */ +char *param_value; /* Param value e.g. "sha1" */ +} MIME_PARAM; + +DECLARE_STACK_OF(MIME_PARAM) +IMPLEMENT_STACK_OF(MIME_PARAM) + +typedef struct { +char *name; /* Name of line e.g. "content-type" */ +char *value; /* Value of line e.g. "text/plain" */ +STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ +} MIME_HEADER; + +DECLARE_STACK_OF(MIME_HEADER) +IMPLEMENT_STACK_OF(MIME_HEADER) + +static char * strip_ends(char *name); +static char * strip_start(char *name); +static char * strip_end(char *name); +static MIME_HEADER *mime_hdr_new(char *name, char *value); +static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); +static int mime_hdr_cmp(const MIME_HEADER * const *a, + const MIME_HEADER * const *b); +static int mime_param_cmp(const MIME_PARAM * const *a, + const MIME_PARAM * const *b); +static void mime_param_free(MIME_PARAM *param); +static int mime_bound_check(char *line, int linelen, char *bound, int blen); +static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); +static int strip_eol(char *linebuf, int *plen); +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name); +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name); +static void mime_hdr_free(MIME_HEADER *hdr); + +#define MAX_SMLEN 1024 +#define mime_debug(x) /* x */ + +/* Base 64 read and write of ASN1 structure */ + +static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it) + { + BIO *b64; + int r; + b64 = BIO_new(BIO_f_base64()); + if(!b64) + { + ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE); + return 0; + } + /* prepend the b64 BIO so all data is base64 encoded. + */ + out = BIO_push(b64, out); + r = ASN1_item_i2d_bio(it, out, val); + (void)BIO_flush(out); + BIO_pop(out); + BIO_free(b64); + return r; + } + +static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) +{ + BIO *b64; + ASN1_VALUE *val; + if(!(b64 = BIO_new(BIO_f_base64()))) { + ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE); + return 0; + } + bio = BIO_push(b64, bio); + val = ASN1_item_d2i_bio(it, bio, NULL); + if(!val) + ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR); + (void)BIO_flush(bio); + bio = BIO_pop(bio); + BIO_free(b64); + return val; +} + +/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */ + +static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) + { + const EVP_MD *md; + int i, have_unknown = 0, write_comma, md_nid; + have_unknown = 0; + write_comma = 0; + for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) + { + if (write_comma) + BIO_write(out, ",", 1); + write_comma = 1; + md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm); + md = EVP_get_digestbynid(md_nid); + switch(md_nid) + { + case NID_sha1: + BIO_puts(out, "sha1"); + break; + + case NID_md5: + BIO_puts(out, "md5"); + break; + + case NID_sha256: + BIO_puts(out, "sha-256"); + break; + + case NID_sha384: + BIO_puts(out, "sha-384"); + break; + + case NID_sha512: + BIO_puts(out, "sha-512"); + break; + + default: + if (have_unknown) + write_comma = 0; + else + { + BIO_puts(out, "unknown"); + have_unknown = 1; + } + break; + + } + } + + return 1; + + } + +/* SMIME sender */ + +int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, + asn1_output_data_fn *data_fn, + const ASN1_ITEM *it) +{ + char bound[33], c; + int i; + const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; + const char *msg_type=NULL; + if (flags & SMIME_OLDMIME) + mime_prefix = "application/x-pkcs7-"; + else + mime_prefix = "application/pkcs7-"; + + if (flags & SMIME_CRLFEOL) + mime_eol = "\r\n"; + else + mime_eol = "\n"; + if((flags & SMIME_DETACHED) && data) { + /* We want multipart/signed */ + /* Generate a random boundary */ + RAND_pseudo_bytes((unsigned char *)bound, 32); + for(i = 0; i < 32; i++) { + c = bound[i] & 0xf; + if(c < 10) c += '0'; + else c += 'A' - 10; + bound[i] = c; + } + bound[32] = 0; + BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); + BIO_printf(bio, "Content-Type: multipart/signed;"); + BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix); + BIO_puts(bio, " micalg=\""); + asn1_write_micalg(bio, mdalgs); + BIO_printf(bio, "\"; boundary=\"----%s\"%s%s", + bound, mime_eol, mime_eol); + BIO_printf(bio, "This is an S/MIME signed message%s%s", + mime_eol, mime_eol); + /* Now write out the first part */ + BIO_printf(bio, "------%s%s", bound, mime_eol); + if (!data_fn(bio, data, val, flags, it)) + return 0; + BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol); + + /* Headers for signature */ + + BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix); + BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol); + BIO_printf(bio, "Content-Transfer-Encoding: base64%s", + mime_eol); + BIO_printf(bio, "Content-Disposition: attachment;"); + BIO_printf(bio, " filename=\"smime.p7s\"%s%s", + mime_eol, mime_eol); + B64_write_ASN1(bio, val, NULL, 0, it); + BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound, + mime_eol, mime_eol); + return 1; + } + + /* Determine smime-type header */ + + if (ctype_nid == NID_pkcs7_enveloped) + msg_type = "enveloped-data"; + else if (ctype_nid == NID_pkcs7_signed) + { + if (econt_nid == NID_id_smime_ct_receipt) + msg_type = "signed-receipt"; + else if (sk_X509_ALGOR_num(mdalgs) >= 0) + msg_type = "signed-data"; + else + msg_type = "certs-only"; + } + else if (ctype_nid == NID_id_smime_ct_compressedData) + { + msg_type = "compressed-data"; + cname = "smime.p7z"; + } + /* MIME headers */ + BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); + BIO_printf(bio, "Content-Disposition: attachment;"); + BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol); + BIO_printf(bio, "Content-Type: %smime;", mime_prefix); + if (msg_type) + BIO_printf(bio, " smime-type=%s;", msg_type); + BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol); + BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s", + mime_eol, mime_eol); + if (!B64_write_ASN1(bio, val, data, flags, it)) + return 0; + BIO_printf(bio, "%s", mime_eol); + return 1; +} + +#if 0 + +/* Handle output of ASN1 data */ + + +static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, + const ASN1_ITEM *it) + { + BIO *tmpbio; + const ASN1_AUX *aux = it->funcs; + ASN1_STREAM_ARG sarg; + + if (!(flags & SMIME_DETACHED)) + { + SMIME_crlf_copy(data, out, flags); + return 1; + } + + if (!aux || !aux->asn1_cb) + { + ASN1err(ASN1_F_ASN1_OUTPUT_DATA, + ASN1_R_STREAMING_NOT_SUPPORTED); + return 0; + } + + sarg.out = out; + sarg.ndef_bio = NULL; + sarg.boundary = NULL; + + /* Let ASN1 code prepend any needed BIOs */ + + if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0) + return 0; + + /* Copy data across, passing through filter BIOs for processing */ + SMIME_crlf_copy(data, sarg.ndef_bio, flags); + + /* Finalize structure */ + if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0) + return 0; + + /* Now remove any digests prepended to the BIO */ + + while (sarg.ndef_bio != out) + { + tmpbio = BIO_pop(sarg.ndef_bio); + BIO_free(sarg.ndef_bio); + sarg.ndef_bio = tmpbio; + } + + return 1; + + } + +#endif + +/* SMIME reader: handle multipart/signed and opaque signing. + * in multipart case the content is placed in a memory BIO + * pointed to by "bcont". In opaque this is set to NULL + */ + +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) +{ + BIO *asnin; + STACK_OF(MIME_HEADER) *headers = NULL; + STACK_OF(BIO) *parts = NULL; + MIME_HEADER *hdr; + MIME_PARAM *prm; + ASN1_VALUE *val; + int ret; + + if(bcont) *bcont = NULL; + + if (!(headers = mime_parse_hdr(bio))) { + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR); + return NULL; + } + + if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); + return NULL; + } + + /* Handle multipart/signed */ + + if(!strcmp(hdr->value, "multipart/signed")) { + /* Split into two parts */ + prm = mime_param_find(hdr, "boundary"); + if(!prm || !prm->param_value) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); + return NULL; + } + ret = multi_split(bio, prm->param_value, &parts); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + if(!ret || (sk_BIO_num(parts) != 2) ) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + /* Parse the signature piece */ + asnin = sk_BIO_value(parts, 1); + + if (!(headers = mime_parse_hdr(asnin))) { + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + /* Get content type */ + + if(!(hdr = mime_hdr_find(headers, "content-type")) || + !hdr->value) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); + return NULL; + } + + if(strcmp(hdr->value, "application/x-pkcs7-signature") && + strcmp(hdr->value, "application/pkcs7-signature")) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + /* Read in ASN1 */ + if(!(val = b64_read_asn1(asnin, it))) { + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + if(bcont) { + *bcont = sk_BIO_value(parts, 0); + BIO_free(asnin); + sk_BIO_free(parts); + } else sk_BIO_pop_free(parts, BIO_vfree); + return val; + } + + /* OK, if not multipart/signed try opaque signature */ + + if (strcmp (hdr->value, "application/x-pkcs7-mime") && + strcmp (hdr->value, "application/pkcs7-mime")) { + ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return NULL; + } + + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + + if(!(val = b64_read_asn1(bio, it))) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); + return NULL; + } + return val; + +} + +/* Copy text from one BIO to another making the output CRLF at EOL */ +int SMIME_crlf_copy(BIO *in, BIO *out, int flags) +{ + BIO *bf; + char eol; + int len; + char linebuf[MAX_SMLEN]; + /* Buffer output so we don't write one line at a time. This is + * useful when streaming as we don't end up with one OCTET STRING + * per line. + */ + bf = BIO_new(BIO_f_buffer()); + if (!bf) + return 0; + out = BIO_push(bf, out); + if(flags & SMIME_BINARY) + { + while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) + BIO_write(out, linebuf, len); + } + else + { + if(flags & SMIME_TEXT) + BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); + while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) + { + eol = strip_eol(linebuf, &len); + if (len) + BIO_write(out, linebuf, len); + if(eol) BIO_write(out, "\r\n", 2); + } + } + (void)BIO_flush(out); + BIO_pop(out); + BIO_free(bf); + return 1; +} + +/* Strip off headers if they are text/plain */ +int SMIME_text(BIO *in, BIO *out) +{ + char iobuf[4096]; + int len; + STACK_OF(MIME_HEADER) *headers; + MIME_HEADER *hdr; + + if (!(headers = mime_parse_hdr(in))) { + ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR); + return 0; + } + if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return 0; + } + if (strcmp (hdr->value, "text/plain")) { + ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return 0; + } + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) + BIO_write(out, iobuf, len); + if (len < 0) + return 0; + return 1; +} + +/* Split a multipart/XXX message body into component parts: result is + * canonical parts in a STACK of bios + */ + +static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) +{ + char linebuf[MAX_SMLEN]; + int len, blen; + int eol = 0, next_eol = 0; + BIO *bpart = NULL; + STACK_OF(BIO) *parts; + char state, part, first; + + blen = strlen(bound); + part = 0; + state = 0; + first = 1; + parts = sk_BIO_new_null(); + *ret = parts; + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + state = mime_bound_check(linebuf, len, bound, blen); + if(state == 1) { + first = 1; + part++; + } else if(state == 2) { + sk_BIO_push(parts, bpart); + return 1; + } else if(part) { + /* Strip CR+LF from linebuf */ + next_eol = strip_eol(linebuf, &len); + if(first) { + first = 0; + if(bpart) sk_BIO_push(parts, bpart); + bpart = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(bpart, 0); + } else if (eol) + BIO_write(bpart, "\r\n", 2); + eol = next_eol; + if (len) + BIO_write(bpart, linebuf, len); + } + } + return 0; +} + +/* This is the big one: parse MIME header lines up to message body */ + +#define MIME_INVALID 0 +#define MIME_START 1 +#define MIME_TYPE 2 +#define MIME_NAME 3 +#define MIME_VALUE 4 +#define MIME_QUOTE 5 +#define MIME_COMMENT 6 + + +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) +{ + char *p, *q, c; + char *ntmp; + char linebuf[MAX_SMLEN]; + MIME_HEADER *mhdr = NULL; + STACK_OF(MIME_HEADER) *headers; + int len, state, save_state = 0; + + headers = sk_MIME_HEADER_new(mime_hdr_cmp); + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + /* If whitespace at line start then continuation line */ + if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME; + else state = MIME_START; + ntmp = NULL; + /* Go through all characters */ + for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { + + /* State machine to handle MIME headers + * if this looks horrible that's because it *is* + */ + + switch(state) { + case MIME_START: + if(c == ':') { + state = MIME_TYPE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break; + + case MIME_TYPE: + if(c == ';') { + mime_debug("Found End Value\n"); + *p = 0; + mhdr = mime_hdr_new(ntmp, strip_ends(q)); + sk_MIME_HEADER_push(headers, mhdr); + ntmp = NULL; + q = p + 1; + state = MIME_NAME; + } else if(c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_COMMENT: + if(c == ')') { + state = save_state; + } + break; + + case MIME_NAME: + if(c == '=') { + state = MIME_VALUE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break ; + + case MIME_VALUE: + if(c == ';') { + state = MIME_NAME; + *p = 0; + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + ntmp = NULL; + q = p + 1; + } else if (c == '"') { + mime_debug("Found Quote\n"); + state = MIME_QUOTE; + } else if(c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_QUOTE: + if(c == '"') { + mime_debug("Found Match Quote\n"); + state = MIME_VALUE; + } + break; + } + } + + if(state == MIME_TYPE) { + mhdr = mime_hdr_new(ntmp, strip_ends(q)); + sk_MIME_HEADER_push(headers, mhdr); + } else if(state == MIME_VALUE) + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + if(p == linebuf) break; /* Blank line means end of headers */ +} + +return headers; + +} + +static char *strip_ends(char *name) +{ + return strip_end(strip_start(name)); +} + +/* Strip a parameter of whitespace from start of param */ +static char *strip_start(char *name) +{ + char *p, c; + /* Look for first non white space or quote */ + for(p = name; (c = *p) ;p++) { + if(c == '"') { + /* Next char is start of string if non null */ + if(p[1]) return p + 1; + /* Else null string */ + return NULL; + } + if(!isspace((unsigned char)c)) return p; + } + return NULL; +} + +/* As above but strip from end of string : maybe should handle brackets? */ +static char *strip_end(char *name) +{ + char *p, c; + if(!name) return NULL; + /* Look for first non white space or quote */ + for(p = name + strlen(name) - 1; p >= name ;p--) { + c = *p; + if(c == '"') { + if(p - 1 == name) return NULL; + *p = 0; + return name; + } + if(isspace((unsigned char)c)) *p = 0; + else return name; + } + return NULL; +} + +static MIME_HEADER *mime_hdr_new(char *name, char *value) +{ + MIME_HEADER *mhdr; + char *tmpname, *tmpval, *p; + int c; + if(name) { + if(!(tmpname = BUF_strdup(name))) return NULL; + for(p = tmpname ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpname = NULL; + if(value) { + if(!(tmpval = BUF_strdup(value))) return NULL; + for(p = tmpval ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpval = NULL; + mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER)); + if(!mhdr) return NULL; + mhdr->name = tmpname; + mhdr->value = tmpval; + if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL; + return mhdr; +} + +static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) +{ + char *tmpname, *tmpval, *p; + int c; + MIME_PARAM *mparam; + if(name) { + tmpname = BUF_strdup(name); + if(!tmpname) return 0; + for(p = tmpname ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpname = NULL; + if(value) { + tmpval = BUF_strdup(value); + if(!tmpval) return 0; + } else tmpval = NULL; + /* Parameter values are case sensitive so leave as is */ + mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM)); + if(!mparam) return 0; + mparam->param_name = tmpname; + mparam->param_value = tmpval; + sk_MIME_PARAM_push(mhdr->params, mparam); + return 1; +} + +static int mime_hdr_cmp(const MIME_HEADER * const *a, + const MIME_HEADER * const *b) +{ + return(strcmp((*a)->name, (*b)->name)); +} + +static int mime_param_cmp(const MIME_PARAM * const *a, + const MIME_PARAM * const *b) +{ + return(strcmp((*a)->param_name, (*b)->param_name)); +} + +/* Find a header with a given name (if possible) */ + +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) +{ + MIME_HEADER htmp; + int idx; + htmp.name = name; + idx = sk_MIME_HEADER_find(hdrs, &htmp); + if(idx < 0) return NULL; + return sk_MIME_HEADER_value(hdrs, idx); +} + +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) +{ + MIME_PARAM param; + int idx; + param.param_name = name; + idx = sk_MIME_PARAM_find(hdr->params, ¶m); + if(idx < 0) return NULL; + return sk_MIME_PARAM_value(hdr->params, idx); +} + +static void mime_hdr_free(MIME_HEADER *hdr) +{ + if(hdr->name) OPENSSL_free(hdr->name); + if(hdr->value) OPENSSL_free(hdr->value); + if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); + OPENSSL_free(hdr); +} + +static void mime_param_free(MIME_PARAM *param) +{ + if(param->param_name) OPENSSL_free(param->param_name); + if(param->param_value) OPENSSL_free(param->param_value); + OPENSSL_free(param); +} + +/* Check for a multipart boundary. Returns: + * 0 : no boundary + * 1 : part boundary + * 2 : final boundary + */ +static int mime_bound_check(char *line, int linelen, char *bound, int blen) +{ + if(linelen == -1) linelen = strlen(line); + if(blen == -1) blen = strlen(bound); + /* Quickly eliminate if line length too short */ + if(blen + 2 > linelen) return 0; + /* Check for part boundary */ + if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) { + if(!strncmp(line + blen + 2, "--", 2)) return 2; + else return 1; + } + return 0; +} + +static int strip_eol(char *linebuf, int *plen) + { + int len = *plen; + char *p, c; + int is_eol = 0; + p = linebuf + len - 1; + for (p = linebuf + len - 1; len > 0; len--, p--) + { + c = *p; + if (c == '\n') + is_eol = 1; + else if (c != '\r') + break; + } + *plen = len; + return is_eol; + } diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c index 72cc1210becd..9132350f1078 100644 --- a/crypto/asn1/asn_moid.c +++ b/crypto/asn1/asn_moid.c @@ -149,7 +149,7 @@ static int do_create(char *value, char *name) if (lntmp == NULL) return 0; memcpy(lntmp, ln, p - ln); - lntmp[p - ln + 1] = 0; + lntmp[p - ln] = 0; oid = OBJ_nid2obj(nid); oid->ln = lntmp; } diff --git a/crypto/asn1/t_req.c b/crypto/asn1/t_req.c index c779a9bb1805..5557e0658448 100644 --- a/crypto/asn1/t_req.c +++ b/crypto/asn1/t_req.c @@ -244,7 +244,7 @@ get_next: } } } - if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) + if(!(cflag & X509_FLAG_NO_EXTENSIONS)) { exts = X509_REQ_get_extensions(x); if(exts) @@ -262,7 +262,7 @@ get_next: j=X509_EXTENSION_get_critical(ex); if (BIO_printf(bp,": %s\n",j?"critical":"") <= 0) goto err; - if(!X509V3_EXT_print(bp, ex, 0, 16)) + if(!X509V3_EXT_print(bp, ex, cflag, 16)) { BIO_printf(bp, "%16s", ""); M_ASN1_OCTET_STRING_print(bp,ex->value); diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c index fe2ea4046d2b..ae72b525d7d4 100644 --- a/crypto/asn1/t_x509.c +++ b/crypto/asn1/t_x509.c @@ -393,8 +393,9 @@ int ASN1_GENERALIZEDTIME_print(BIO *bp, ASN1_GENERALIZEDTIME *tm) d= (v[6]-'0')*10+(v[7]-'0'); h= (v[8]-'0')*10+(v[9]-'0'); m= (v[10]-'0')*10+(v[11]-'0'); - if ( (v[12] >= '0') && (v[12] <= '9') && - (v[13] >= '0') && (v[13] <= '9')) + if (i >= 14 && + (v[12] >= '0') && (v[12] <= '9') && + (v[13] >= '0') && (v[13] <= '9')) s= (v[12]-'0')*10+(v[13]-'0'); if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s", @@ -428,8 +429,9 @@ int ASN1_UTCTIME_print(BIO *bp, ASN1_UTCTIME *tm) d= (v[4]-'0')*10+(v[5]-'0'); h= (v[6]-'0')*10+(v[7]-'0'); m= (v[8]-'0')*10+(v[9]-'0'); - if ( (v[10] >= '0') && (v[10] <= '9') && - (v[11] >= '0') && (v[11] <= '9')) + if (i >=12 && + (v[10] >= '0') && (v[10] <= '9') && + (v[11] >= '0') && (v[11] <= '9')) s= (v[10]-'0')*10+(v[11]-'0'); if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s", @@ -449,13 +451,13 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) l=80-2-obase; - b=s=X509_NAME_oneline(name,NULL,0); - if (!*s) + b=X509_NAME_oneline(name,NULL,0); + if (!*b) { OPENSSL_free(b); return 1; } - s++; /* skip the first slash */ + s=b+1; /* skip the first slash */ c=s; for (;;) @@ -480,8 +482,7 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) { i=s-c; if (BIO_write(bp,c,i) != i) goto err; - c+=i; - c++; + c=s+1; /* skip following slash */ if (*s != '\0') { if (BIO_write(bp,", ",2) != 2) goto err; @@ -502,4 +503,3 @@ err: OPENSSL_free(b); return(ret); } - diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 66d229b08b39..0ee406231e7c 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -130,7 +130,7 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, ASN1_VALUE *ptmpval = NULL; if (!pval) pval = &ptmpval; - asn1_tlc_clear(&c); + c.valid = 0; if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) return *pval; return NULL; @@ -140,7 +140,7 @@ int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt) { ASN1_TLC c; - asn1_tlc_clear(&c); + c.valid = 0; return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); } @@ -944,7 +944,7 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, if (utype != typ->type) ASN1_TYPE_set(typ, utype, NULL); opval = pval; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; } switch(utype) { diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 25c94aa1d95a..be19b36acd5f 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -494,7 +494,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, { for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) - sk_ASN1_VALUE_set(sk, i, tder->field); + (void)sk_ASN1_VALUE_set(sk, i, tder->field); } OPENSSL_free(derlst); OPENSSL_free(tmpdat); @@ -597,7 +597,7 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, typ = (ASN1_TYPE *)*pval; utype = typ->type; *putype = utype; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; } else utype = *putype; diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index b68b66a23b18..bb7c1e2af489 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -115,8 +115,6 @@ static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int c return; } i = asn1_get_choice_selector(pval, it); - if (asn1_cb) - asn1_cb(ASN1_OP_FREE_PRE, pval, it); if ((i >= 0) && (i < it->tcount)) { ASN1_VALUE **pchval; @@ -221,7 +219,7 @@ void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { ASN1_TYPE *typ = (ASN1_TYPE *)*pval; utype = typ->type; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; if (!*pval) return; } diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c index 00b9ea54a15f..33533aba862b 100644 --- a/crypto/asn1/x_algor.c +++ b/crypto/asn1/x_algor.c @@ -66,8 +66,65 @@ ASN1_SEQUENCE(X509_ALGOR) = { ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY) } ASN1_SEQUENCE_END(X509_ALGOR) +ASN1_ITEM_TEMPLATE(X509_ALGORS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR) +ASN1_ITEM_TEMPLATE_END(X509_ALGORS) + IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS) IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) IMPLEMENT_STACK_OF(X509_ALGOR) IMPLEMENT_ASN1_SET_OF(X509_ALGOR) + +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) + { + if (!alg) + return 0; + if (ptype != V_ASN1_UNDEF) + { + if (alg->parameter == NULL) + alg->parameter = ASN1_TYPE_new(); + if (alg->parameter == NULL) + return 0; + } + if (alg) + { + if (alg->algorithm) + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = aobj; + } + if (ptype == 0) + return 1; + if (ptype == V_ASN1_UNDEF) + { + if (alg->parameter) + { + ASN1_TYPE_free(alg->parameter); + alg->parameter = NULL; + } + } + else + ASN1_TYPE_set(alg->parameter, ptype, pval); + return 1; + } + +void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval, + X509_ALGOR *algor) + { + if (paobj) + *paobj = algor->algorithm; + if (pptype) + { + if (algor->parameter == NULL) + { + *pptype = V_ASN1_UNDEF; + return; + } + else + *pptype = algor->parameter->type; + if (ppval) + *ppval = algor->parameter->value.ptr; + } + } + diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c index b99f8fc522c1..70d56a67f26a 100644 --- a/crypto/asn1/x_crl.c +++ b/crypto/asn1/x_crl.c @@ -84,7 +84,7 @@ static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) * would affect the output of X509_CRL_print(). */ case ASN1_OP_D2I_POST: - sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp); + (void)sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp); break; } return 1; diff --git a/crypto/asn1/x_exten.c b/crypto/asn1/x_exten.c index 702421b6c851..1732e667125c 100644 --- a/crypto/asn1/x_exten.c +++ b/crypto/asn1/x_exten.c @@ -67,5 +67,10 @@ ASN1_SEQUENCE(X509_EXTENSION) = { ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING) } ASN1_SEQUENCE_END(X509_EXTENSION) +ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) +ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS) + IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index 681e5d110fad..04380abc3ff9 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -160,40 +160,40 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len int tag, int aclass, char opt, ASN1_TLC *ctx) { const unsigned char *p = *in, *q; - STACK *intname = NULL, **intname_pp = &intname; + union { STACK *s; ASN1_VALUE *a; } intname = {NULL}; + union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL}; int i, j, ret; - X509_NAME *nm = NULL, **nm_pp = &nm; STACK_OF(X509_NAME_ENTRY) *entries; X509_NAME_ENTRY *entry; q = p; /* Get internal representation of Name */ - ret = ASN1_item_ex_d2i((ASN1_VALUE **)intname_pp, + ret = ASN1_item_ex_d2i(&intname.a, &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), tag, aclass, opt, ctx); if(ret <= 0) return ret; if(*val) x509_name_ex_free(val, NULL); - if(!x509_name_ex_new((ASN1_VALUE **)nm_pp, NULL)) goto err; + if(!x509_name_ex_new(&nm.a, NULL)) goto err; /* We've decoded it: now cache encoding */ - if(!BUF_MEM_grow(nm->bytes, p - q)) goto err; - memcpy(nm->bytes->data, q, p - q); + if(!BUF_MEM_grow(nm.x->bytes, p - q)) goto err; + memcpy(nm.x->bytes->data, q, p - q); /* Convert internal representation to X509_NAME structure */ - for(i = 0; i < sk_num(intname); i++) { - entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname, i); + for(i = 0; i < sk_num(intname.s); i++) { + entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname.s, i); for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { entry = sk_X509_NAME_ENTRY_value(entries, j); entry->set = i; - if(!sk_X509_NAME_ENTRY_push(nm->entries, entry)) + if(!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) goto err; } sk_X509_NAME_ENTRY_free(entries); } - sk_free(intname); - nm->modified = 0; - *val = (ASN1_VALUE *)nm; + sk_free(intname.s); + nm.x->modified = 0; + *val = nm.a; *in = p; return ret; err: @@ -219,35 +219,35 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_IT static int x509_name_encode(X509_NAME *a) { - STACK *intname = NULL, **intname_pp = &intname; + union { STACK *s; ASN1_VALUE *a; } intname = {NULL}; int len; unsigned char *p; STACK_OF(X509_NAME_ENTRY) *entries = NULL; X509_NAME_ENTRY *entry; int i, set = -1; - intname = sk_new_null(); - if(!intname) goto memerr; + intname.s = sk_new_null(); + if(!intname.s) goto memerr; for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { entry = sk_X509_NAME_ENTRY_value(a->entries, i); if(entry->set != set) { entries = sk_X509_NAME_ENTRY_new_null(); if(!entries) goto memerr; - if(!sk_push(intname, (char *)entries)) goto memerr; + if(!sk_push(intname.s, (char *)entries)) goto memerr; set = entry->set; } if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; } - len = ASN1_item_ex_i2d((ASN1_VALUE **)intname_pp, NULL, + len = ASN1_item_ex_i2d(&intname.a, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); if (!BUF_MEM_grow(a->bytes,len)) goto memerr; p=(unsigned char *)a->bytes->data; - ASN1_item_ex_i2d((ASN1_VALUE **)intname_pp, + ASN1_item_ex_i2d(&intname.a, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); - sk_pop_free(intname, sk_internal_free); + sk_pop_free(intname.s, sk_internal_free); a->modified = 0; return len; memerr: - sk_pop_free(intname, sk_internal_free); + sk_pop_free(intname.s, sk_internal_free); ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); return -1; } diff --git a/crypto/bio/b_print.c b/crypto/bio/b_print.c index 4857cfe0ce84..3a87b0ec0b2e 100644 --- a/crypto/bio/b_print.c +++ b/crypto/bio/b_print.c @@ -79,7 +79,7 @@ #include <openssl/bn.h> /* To get BN_LLONG properly defined */ #include <openssl/bio.h> -#ifdef BN_LLONG +#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) # ifndef HAVE_LONG_LONG # define HAVE_LONG_LONG 1 # endif @@ -117,7 +117,7 @@ #if HAVE_LONG_LONG # if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) -# define LLONG _int64 +# define LLONG __int64 # else # define LLONG long long # endif diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index 4b3860b991e3..ead477d8a29e 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -63,7 +63,11 @@ #include "cryptlib.h" #include <openssl/bio.h> #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) -#include "netdb.h" +#include <netdb.h> +#if defined(NETWARE_CLIB) +#include <sys/ioctl.h> +NETDB_DEFINE_CONTEXT +#endif #endif #ifndef OPENSSL_NO_SOCK @@ -178,11 +182,11 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) /* Note: under VMS with SOCKETSHR, it seems like the first * parameter is 'char *', instead of 'const char *' */ - s=getservbyname( #ifndef CONST_STRICT - (char *) + s=getservbyname((char *)str,"tcp"); +#else + s=getservbyname(str,"tcp"); #endif - str,"tcp"); if(s != NULL) *port_ptr=ntohs((unsigned short)s->s_port); CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); @@ -360,7 +364,11 @@ struct hostent *BIO_gethostbyname(const char *name) #if 1 /* Caching gethostbyname() results forever is wrong, * so we have to let the true gethostbyname() worry about this */ +#if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__)) + return gethostbyname((char*)name); +#else return gethostbyname(name); +#endif #else struct hostent *ret; int i,lowi=0,j; @@ -400,11 +408,11 @@ struct hostent *BIO_gethostbyname(const char *name) /* Note: under VMS with SOCKETSHR, it seems like the first * parameter is 'char *', instead of 'const char *' */ - ret=gethostbyname( # ifndef CONST_STRICT - (char *) + ret=gethostbyname((char *)name); +# else + ret=gethostbyname(name); # endif - name); if (ret == NULL) goto end; @@ -456,9 +464,6 @@ int BIO_sock_init(void) { int err; -#ifdef SIGINT - signal(SIGINT,(void (*)(int))BIO_sock_cleanup); -#endif wsa_init_done=1; memset(&wsa_state,0,sizeof(wsa_state)); if (WSAStartup(0x0101,&wsa_state)!=0) @@ -484,11 +489,6 @@ int BIO_sock_init(void) if (!wsa_init_done) { - -# ifdef SIGINT - signal(SIGINT,(void (*)(int))BIO_sock_cleanup); -# endif - wsa_init_done=1; wVerReq = MAKEWORD( 2, 0 ); err = WSAStartup(wVerReq,&wsaData); @@ -511,7 +511,7 @@ void BIO_sock_cleanup(void) { wsa_init_done=0; #ifndef OPENSSL_SYS_WINCE - WSACancelBlockingCall(); + WSACancelBlockingCall(); /* Winsock 1.1 specific */ #endif WSACleanup(); } diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index 2c9e8a7c804a..cecb6a720771 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -95,6 +95,7 @@ extern "C" { #define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ #define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */ #define BIO_TYPE_DGRAM (21|0x0400|0x0100) +#define BIO_TYPE_COMP (23|0x0200) /* filter */ #define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ #define BIO_TYPE_FILTER 0x0200 @@ -129,8 +130,8 @@ extern "C" { /* dgram BIO stuff */ #define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */ #define BIO_CTRL_DGRAM_SET_CONNECTED 32 /* allow for an externally - * connected socket to be - * passed in */ + * connected socket to be + * passed in */ #define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */ #define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */ #define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35 /* setsockopt, essentially */ @@ -146,14 +147,14 @@ extern "C" { #define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */ #define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */ #define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for - * MTU. want to use this - * if asking the kernel - * fails */ + * MTU. want to use this + * if asking the kernel + * fails */ #define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU - * was exceed in the - * previous write - * operation */ + * was exceed in the + * previous write + * operation */ #define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */ diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index a0cb29b3dcee..c3da6dc82fa9 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -82,7 +82,7 @@ static int dgram_new(BIO *h); static int dgram_free(BIO *data); static int dgram_clear(BIO *bio); -int BIO_dgram_should_retry(int s); +static int BIO_dgram_should_retry(int s); static BIO_METHOD methods_dgramp= { @@ -208,9 +208,13 @@ static int dgram_write(BIO *b, const char *in, int inl) clear_socket_error(); if ( data->connected ) - ret=send(b->num,in,inl,0); + ret=writesocket(b->num,in,inl); else +#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) + ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer)); +#else ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer)); +#endif BIO_clear_retry_flags(b); if (ret <= 0) @@ -341,30 +345,90 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) memcpy(&(data->peer), to, sizeof(struct sockaddr)); break; +#if defined(SO_RCVTIMEO) case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: +#ifdef OPENSSL_SYS_WINDOWS + { + struct timeval *tv = (struct timeval *)ptr; + int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void*)&timeout, sizeof(timeout)) < 0) + { perror("setsockopt"); ret = -1; } + } +#else if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, sizeof(struct timeval)) < 0) { perror("setsockopt"); ret = -1; } +#endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: +#ifdef OPENSSL_SYS_WINDOWS + { + int timeout, sz = sizeof(timeout); + struct timeval *tv = (struct timeval *)ptr; + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void*)&timeout, &sz) < 0) + { perror("getsockopt"); ret = -1; } + else + { + tv->tv_sec = timeout / 1000; + tv->tv_usec = (timeout % 1000) * 1000; + ret = sizeof(*tv); + } + } +#else if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, (void *)&ret) < 0) { perror("getsockopt"); ret = -1; } +#endif break; +#endif +#if defined(SO_SNDTIMEO) case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: +#ifdef OPENSSL_SYS_WINDOWS + { + struct timeval *tv = (struct timeval *)ptr; + int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; + if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void*)&timeout, sizeof(timeout)) < 0) + { perror("setsockopt"); ret = -1; } + } +#else if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, sizeof(struct timeval)) < 0) { perror("setsockopt"); ret = -1; } +#endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: +#ifdef OPENSSL_SYS_WINDOWS + { + int timeout, sz = sizeof(timeout); + struct timeval *tv = (struct timeval *)ptr; + if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void*)&timeout, &sz) < 0) + { perror("getsockopt"); ret = -1; } + else + { + tv->tv_sec = timeout / 1000; + tv->tv_usec = (timeout % 1000) * 1000; + ret = sizeof(*tv); + } + } +#else if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, (void *)&ret) < 0) { perror("getsockopt"); ret = -1; } +#endif break; +#endif case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: /* fall-through */ case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: +#ifdef OPENSSL_SYS_WINDOWS + if ( data->_errno == WSAETIMEDOUT) +#else if ( data->_errno == EAGAIN) +#endif { ret = 1; data->_errno = 0; @@ -399,7 +463,7 @@ static int dgram_puts(BIO *bp, const char *str) return(ret); } -int BIO_dgram_should_retry(int i) +static int BIO_dgram_should_retry(int i) { int err; diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index b277367da3a4..4df9927c437e 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -89,6 +89,10 @@ #include "bio_lcl.h" #include <openssl/err.h> +#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) +#include <nwfileio.h> +#endif + #if !defined(OPENSSL_NO_STDIO) static int MS_CALLBACK file_write(BIO *h, const char *buf, int num); @@ -285,9 +289,9 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) /* Under CLib there are differences in file modes */ if (num & BIO_FP_TEXT) - _setmode(fd,O_TEXT); + setmode(fd,O_TEXT); else - _setmode(fd,O_BINARY); + setmode(fd,O_BINARY); #elif defined(OPENSSL_SYS_MSDOS) int fd = fileno((FILE*)ptr); /* Set correct text/binary mode */ diff --git a/crypto/bn/Makefile b/crypto/bn/Makefile index 5c3e08fa8085..0491e3db4c47 100644 --- a/crypto/bn/Makefile +++ b/crypto/bn/Makefile @@ -67,16 +67,22 @@ bn86-elf.s: asm/bn-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) bn-586.pl elf $(CFLAGS) > ../$@) co86-elf.s: asm/co-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) co-586.pl elf $(CFLAGS) > ../$@) +mo86-elf.s: asm/mo-586.pl ../perlasm/x86asm.pl + (cd asm; $(PERL) mo-586.pl elf $(CFLAGS) > ../$@) # COFF bn86-cof.s: asm/bn-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) bn-586.pl coff $(CFLAGS) > ../$@) co86-cof.s: asm/co-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) co-586.pl coff $(CFLAGS) > ../$@) +mo86-cof.s: asm/mo-586.pl ../perlasm/x86asm.pl + (cd asm; $(PERL) mo-586.pl coff $(CFLAGS) > ../$@) # a.out bn86-out.s: asm/bn-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) bn-586.pl a.out $(CFLAGS) > ../$@) co86-out.s: asm/co-586.pl ../perlasm/x86asm.pl (cd asm; $(PERL) co-586.pl a.out $(CFLAGS) > ../$@) +mo86-out.s: asm/mo-586.pl ../perlasm/x86asm.pl + (cd asm; $(PERL) mo-586.pl a.out $(CFLAGS) > ../$@) sparcv8.o: asm/sparcv8.S $(CC) $(CFLAGS) -c asm/sparcv8.S @@ -91,6 +97,8 @@ bn-mips3.o: asm/mips3.s x86_64-gcc.o: asm/x86_64-gcc.c $(CC) $(CFLAGS) -c -o $@ asm/x86_64-gcc.c +x86_64-mont.s: asm/x86_64-mont.pl + $(PERL) asm/x86_64-mont.pl $@ bn-ia64.s: asm/ia64.S $(CC) $(CFLAGS) -E asm/ia64.S > $@ @@ -108,6 +116,7 @@ linux_ppc64.s: asm/ppc.pl; $(PERL) $< $@ aix_ppc32.s: asm/ppc.pl; $(PERL) asm/ppc.pl $@ aix_ppc64.s: asm/ppc.pl; $(PERL) asm/ppc.pl $@ osx_ppc32.s: asm/ppc.pl; $(PERL) $< $@ +osx_ppc64.s: asm/ppc.pl; $(PERL) $< $@ files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/crypto/bn/asm/ia64.S b/crypto/bn/asm/ia64.S index 7b82b820e62a..951abc53ea5b 100644 --- a/crypto/bn/asm/ia64.S +++ b/crypto/bn/asm/ia64.S @@ -171,21 +171,21 @@ .skip 32 // makes the loop body aligned at 64-byte boundary bn_add_words: .prologue - .fframe 0 .save ar.pfs,r2 { .mii; alloc r2=ar.pfs,4,12,0,16 cmp4.le p6,p0=r35,r0 };; { .mfb; mov r8=r0 // return value (p6) br.ret.spnt.many b0 };; - .save ar.lc,r3 { .mib; sub r10=r35,r0,1 + .save ar.lc,r3 mov r3=ar.lc brp.loop.imp .L_bn_add_words_ctop,.L_bn_add_words_cend-16 } - .body { .mib; ADDP r14=0,r32 // rp + .save pr,r9 mov r9=pr };; + .body { .mii; ADDP r15=0,r33 // ap mov ar.lc=r10 mov ar.ec=6 } @@ -224,21 +224,21 @@ bn_add_words: .skip 32 // makes the loop body aligned at 64-byte boundary bn_sub_words: .prologue - .fframe 0 .save ar.pfs,r2 { .mii; alloc r2=ar.pfs,4,12,0,16 cmp4.le p6,p0=r35,r0 };; { .mfb; mov r8=r0 // return value (p6) br.ret.spnt.many b0 };; - .save ar.lc,r3 { .mib; sub r10=r35,r0,1 + .save ar.lc,r3 mov r3=ar.lc brp.loop.imp .L_bn_sub_words_ctop,.L_bn_sub_words_cend-16 } - .body { .mib; ADDP r14=0,r32 // rp + .save pr,r9 mov r9=pr };; + .body { .mii; ADDP r15=0,r33 // ap mov ar.lc=r10 mov ar.ec=6 } @@ -283,7 +283,6 @@ bn_sub_words: .skip 32 // makes the loop body aligned at 64-byte boundary bn_mul_words: .prologue - .fframe 0 .save ar.pfs,r2 #ifdef XMA_TEMPTATION { .mfi; alloc r2=ar.pfs,4,0,0,0 };; @@ -294,9 +293,10 @@ bn_mul_words: cmp4.le p6,p0=r34,r0 (p6) br.ret.spnt.many b0 };; - .save ar.lc,r3 { .mii; sub r10=r34,r0,1 + .save ar.lc,r3 mov r3=ar.lc + .save pr,r9 mov r9=pr };; .body @@ -397,22 +397,21 @@ bn_mul_words: .skip 48 // makes the loop body aligned at 64-byte boundary bn_mul_add_words: .prologue - .fframe 0 .save ar.pfs,r2 - .save ar.lc,r3 - .save pr,r9 { .mmi; alloc r2=ar.pfs,4,4,0,8 cmp4.le p6,p0=r34,r0 + .save ar.lc,r3 mov r3=ar.lc };; { .mib; mov r8=r0 // return value sub r10=r34,r0,1 (p6) br.ret.spnt.many b0 };; - .body { .mib; setf.sig f8=r35 // w + .save pr,r9 mov r9=pr brp.loop.imp .L_bn_mul_add_words_ctop,.L_bn_mul_add_words_cend-16 } + .body { .mmi; ADDP r14=0,r32 // rp ADDP r15=0,r33 // ap mov ar.lc=r10 } @@ -466,7 +465,6 @@ bn_mul_add_words: .skip 32 // makes the loop body aligned at 64-byte boundary bn_sqr_words: .prologue - .fframe 0 .save ar.pfs,r2 { .mii; alloc r2=ar.pfs,3,0,0,0 sxt4 r34=r34 };; @@ -476,9 +474,10 @@ bn_sqr_words: nop.f 0x0 (p6) br.ret.spnt.many b0 };; - .save ar.lc,r3 { .mii; sub r10=r34,r0,1 + .save ar.lc,r3 mov r3=ar.lc + .save pr,r9 mov r9=pr };; .body @@ -545,7 +544,6 @@ bn_sqr_words: .align 64 bn_sqr_comba8: .prologue - .fframe 0 .save ar.pfs,r2 #if defined(_HPUX_SOURCE) && !defined(_LP64) { .mii; alloc r2=ar.pfs,2,1,0,0 @@ -617,7 +615,6 @@ bn_sqr_comba8: .align 64 bn_mul_comba8: .prologue - .fframe 0 .save ar.pfs,r2 #if defined(_HPUX_SOURCE) && !defined(_LP64) { .mii; alloc r2=ar.pfs,3,0,0,0 @@ -1175,7 +1172,6 @@ bn_mul_comba8: .align 64 bn_sqr_comba4: .prologue - .fframe 0 .save ar.pfs,r2 #if defined(_HPUX_SOURCE) && !defined(_LP64) { .mii; alloc r2=ar.pfs,2,1,0,0 @@ -1208,7 +1204,6 @@ bn_sqr_comba4: .align 64 bn_mul_comba4: .prologue - .fframe 0 .save ar.pfs,r2 #if defined(_HPUX_SOURCE) && !defined(_LP64) { .mii; alloc r2=ar.pfs,3,0,0,0 @@ -1411,11 +1406,11 @@ equ=p24 .align 64 bn_div_words: .prologue - .fframe 0 .save ar.pfs,r2 - .save b0,r3 { .mii; alloc r2=ar.pfs,3,5,0,8 + .save b0,r3 mov r3=b0 + .save pr,r10 mov r10=pr };; { .mmb; cmp.eq p6,p0=r34,r0 mov r8=-1 diff --git a/crypto/bn/asm/mo-586.pl b/crypto/bn/asm/mo-586.pl new file mode 100755 index 000000000000..0982293094d9 --- /dev/null +++ b/crypto/bn/asm/mo-586.pl @@ -0,0 +1,603 @@ +#!/usr/bin/env perl + +# This is crypto/bn/asm/x86-mont.pl (with asciz from crypto/perlasm/x86asm.pl) +# from OpenSSL 0.9.9-dev + +sub ::asciz +{ my @str=unpack("C*",shift); + push @str,0; + while ($#str>15) { + &data_byte(@str[0..15]); + foreach (0..15) { shift @str; } + } + &data_byte(@str) if (@str); +} + +# ==================================================================== +# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005 +# +# This is a "teaser" code, as it can be improved in several ways... +# First of all non-SSE2 path should be implemented (yes, for now it +# performs Montgomery multiplication/convolution only on SSE2-capable +# CPUs such as P4, others fall down to original code). Then inner loop +# can be unrolled and modulo-scheduled to improve ILP and possibly +# moved to 128-bit XMM register bank (though it would require input +# rearrangement and/or increase bus bandwidth utilization). Dedicated +# squaring procedure should give further performance improvement... +# Yet, for being draft, the code improves rsa512 *sign* benchmark by +# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-) + +# December 2006 +# +# Modulo-scheduling SSE2 loops results in further 15-20% improvement. +# Integer-only code [being equipped with dedicated squaring procedure] +# gives ~40% on rsa512 sign benchmark... + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +&function_begin("bn_mul_mont"); + +$i="edx"; +$j="ecx"; +$ap="esi"; $tp="esi"; # overlapping variables!!! +$rp="edi"; $bp="edi"; # overlapping variables!!! +$np="ebp"; +$num="ebx"; + +$_num=&DWP(4*0,"esp"); # stack top layout +$_rp=&DWP(4*1,"esp"); +$_ap=&DWP(4*2,"esp"); +$_bp=&DWP(4*3,"esp"); +$_np=&DWP(4*4,"esp"); +$_n0=&DWP(4*5,"esp"); $_n0q=&QWP(4*5,"esp"); +$_sp=&DWP(4*6,"esp"); +$_bpend=&DWP(4*7,"esp"); +$frame=32; # size of above frame rounded up to 16n + + &xor ("eax","eax"); + &mov ("edi",&wparam(5)); # int num + &cmp ("edi",4); + &jl (&label("just_leave")); + + &lea ("esi",&wparam(0)); # put aside pointer to argument block + &lea ("edx",&wparam(1)); # load ap + &mov ("ebp","esp"); # saved stack pointer! + &add ("edi",2); # extra two words on top of tp + &neg ("edi"); + &lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2)) + &neg ("edi"); + + # minimize cache contention by arraning 2K window between stack + # pointer and ap argument [np is also position sensitive vector, + # but it's assumed to be near ap, as it's allocated at ~same + # time]. + &mov ("eax","esp"); + &sub ("eax","edx"); + &and ("eax",2047); + &sub ("esp","eax"); # this aligns sp and ap modulo 2048 + + &xor ("edx","esp"); + &and ("edx",2048); + &xor ("edx",2048); + &sub ("esp","edx"); # this splits them apart modulo 4096 + + &and ("esp",-64); # align to cache line + + ################################# load argument block... + &mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp + &mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap + &mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp + &mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np + &mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0 + #&mov ("edi",&DWP(5*4,"esi"));# int num + + &mov ("esi",&DWP(0,"esi")); # pull n0[0] + &mov ($_rp,"eax"); # ... save a copy of argument block + &mov ($_ap,"ebx"); + &mov ($_bp,"ecx"); + &mov ($_np,"edx"); + &mov ($_n0,"esi"); + &lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling + #&mov ($_num,$num); # redundant as $num is not reused + &mov ($_sp,"ebp"); # saved stack pointer! + +if($sse2) { +$acc0="mm0"; # mmx register bank layout +$acc1="mm1"; +$car0="mm2"; +$car1="mm3"; +$mul0="mm4"; +$mul1="mm5"; +$temp="mm6"; +$mask="mm7"; + + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"eax"),26); + &jnc (&label("non_sse2")); + + &mov ("eax",-1); + &movd ($mask,"eax"); # mask 32 lower bits + + &mov ($ap,$_ap); # load input pointers + &mov ($bp,$_bp); + &mov ($np,$_np); + + &xor ($i,$i); # i=0 + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp)); # bp[0] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($car1,&DWP(0,$np)); # np[0] + + &pmuludq($mul1,$mul0); # ap[0]*bp[0] + &movq ($car0,$mul1); + &movq ($acc0,$mul1); # I wish movd worked for + &pand ($acc0,$mask); # inter-register transfers + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); # "t[0]"*np[0]*n0 + &paddq ($car1,$acc0); + + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &inc ($j); # j++ +&set_label("1st",16); + &pmuludq($acc0,$mul0); # ap[j]*bp[0] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[0]; + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[j-1]= + &psrlq ($car1,32); + + &lea ($j,&DWP(1,$j)); + &cmp ($j,$num); + &jl (&label("1st")); + + &pmuludq($acc0,$mul0); # ap[num-1]*bp[0] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[0]; + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &paddq ($car1,$car0); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &inc ($i); # i++ +&set_label("outer"); + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp,$i,4)); # bp[i] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($temp,&DWP($frame,"esp")); # tp[0] + &movd ($car1,&DWP(0,$np)); # np[0] + &pmuludq($mul1,$mul0); # ap[0]*bp[i] + + &paddq ($mul1,$temp); # +=tp[0] + &movq ($acc0,$mul1); + &movq ($car0,$mul1); + &pand ($acc0,$mask); + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); + &paddq ($car1,$acc0); + + &movd ($temp,&DWP($frame+4,"esp")); # tp[1] + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[1] + + &inc ($j); # j++ + &dec ($num); +&set_label("inner"); + &pmuludq($acc0,$mul0); # ap[j]*bp[i] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &movd ($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1] + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[i]+tp[j] + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]= + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[j+1] + + &dec ($num); + &lea ($j,&DWP(1,$j)); # j++ + &jnz (&label("inner")); + + &mov ($num,$j); + &pmuludq($acc0,$mul0); # ap[num-1]*bp[i] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[i]+tp[num-1] + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + &psrlq ($car0,32); + &psrlq ($car1,32); + + &movd ($temp,&DWP($frame+4,"esp",$num,4)); # += tp[num] + &paddq ($car1,$car0); + &paddq ($car1,$temp); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &lea ($i,&DWP(1,$i)); # i++ + &cmp ($i,$num); + &jle (&label("outer")); + + &emms (); # done with mmx bank + &jmp (&label("common_tail")); + +&set_label("non_sse2",16); +} + +if (0) { + &mov ("esp",$_sp); + &xor ("eax","eax"); # signal "not fast enough [yet]" + &jmp (&label("just_leave")); + # While the below code provides competitive performance for + # all key lengthes on modern Intel cores, it's still more + # than 10% slower for 4096-bit key elsewhere:-( "Competitive" + # means compared to the original integer-only assembler. + # 512-bit RSA sign is better by ~40%, but that's about all + # one can say about all CPUs... +} else { +$inp="esi"; # integer path uses these registers differently +$word="edi"; +$carry="ebp"; + + &mov ($inp,$_ap); + &lea ($carry,&DWP(1,$num)); + &mov ($word,$_bp); + &xor ($j,$j); # j=0 + &mov ("edx",$inp); + &and ($carry,1); # see if num is even + &sub ("edx",$word); # see if ap==bp + &lea ("eax",&DWP(4,$word,$num,4)); # &bp[num] + &or ($carry,"edx"); + &mov ($word,&DWP(0,$word)); # bp[0] + &jz (&label("bn_sqr_mont")); + &mov ($_bpend,"eax"); + &mov ("eax",&DWP(0,$inp)); + &xor ("edx","edx"); + +&set_label("mull",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[0] + &add ($carry,"eax"); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("mull")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[0] + &mov ($word,$_n0); + &add ("eax",$carry); + &mov ($inp,$_np); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]= + &xor ($j,$j); + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mov ("eax",&DWP(0,$inp)); # np[0] + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &inc ($j); + + &jmp (&label("2ndmadd")); + +&set_label("1stmadd",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[i] + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("1stmadd")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[i] + &add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &add ($carry,"eax"); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &xor ($j,$j); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]= + &adc ($j,0); + &mov ("eax",&DWP(0,$inp)); # np[0] + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &mov ($j,1); + +&set_label("2ndmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]= + &jl (&label("2ndmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &xor ("eax","eax"); + &mov ($j,$_bp); # &bp[i] + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &lea ($j,&DWP(4,$j)); + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$_bpend); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(0,$j)); # bp[i+1] + &mov ($inp,$_ap); + &mov ($_bp,$j); # &bp[++i] + &xor ($j,$j); + &xor ("edx","edx"); + &mov ("eax",&DWP(0,$inp)); + &jmp (&label("1stmadd")); + +&set_label("bn_sqr_mont",16); +$sbit=$num; + &mov ($_num,$num); + &mov ($_bp,$j); # i=0 + + &mov ("eax",$word); # ap[0] + &mul ($word); # ap[0]*ap[0] + &mov (&DWP($frame,"esp"),"eax"); # tp[0]= + &mov ($sbit,"edx"); + &shr ("edx",1); + &and ($sbit,1); + &inc ($j); +&set_label("sqr",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[0] + &add ("eax",$carry); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &shr ("eax",31); + &cmp ($j,$_num); + &mov ($sbit,"eax"); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("sqr")); + + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1] + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*ap[0] + &add ("eax",$carry); + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + &shr ("eax",31); + &mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]= + + &lea ($carry,&DWP(0,"eax","edx",2)); + &mov ("eax",&DWP(0,$inp)); # np[0] + &shr ("edx",31); + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]= + &mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ($num,$j); + &adc ("edx",0); + &mov ("eax",&DWP(4,$inp)); # np[1] + &mov ($j,1); + +&set_label("3rdmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]= + + &mov ($carry,"edx"); + &mul ($word); # np[j+1]*m + &add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1] + &lea ($j,&DWP(2,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]= + &jl (&label("3rdmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &mov ($j,$_bp); # i + &xor ("eax","eax"); + &mov ($inp,$_ap); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$num); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(4,$inp,$j,4)); # ap[i] + &lea ($j,&DWP(1,$j)); + &mov ("eax",$word); + &mov ($_bp,$j); # ++i + &mul ($word); # ap[i]*ap[i] + &add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i] + &adc ("edx",0); + &mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]= + &xor ($carry,$carry); + &cmp ($j,$num); + &lea ($j,&DWP(1,$j)); + &je (&label("sqrlast")); + + &mov ($sbit,"edx"); # zaps $num + &shr ("edx",1); + &and ($sbit,1); +&set_label("sqradd",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[i] + &add ("eax",$carry); + &lea ($carry,&DWP(0,"eax","eax")); + &adc ("edx",0); + &shr ("eax",31); + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("eax",0); + &add ($carry,$sbit); + &adc ("eax",0); + &cmp ($j,$_num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &mov ($sbit,"eax"); + &jle (&label("sqradd")); + + &mov ($carry,"edx"); + &lea ("edx",&DWP(0,$sbit,"edx",2)); + &shr ($carry,31); +&set_label("sqrlast"); + &mov ($word,$_n0); + &mov ($inp,$_np); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num] + &mov ("eax",&DWP(0,$inp)); # np[0] + &adc ($carry,0); + &mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]= + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &lea ($num,&DWP(-1,$j)); + &adc ("edx",0); + &mov ($j,1); + &mov ("eax",&DWP(4,$inp)); # np[1] + + &jmp (&label("3rdmadd")); +} + +&set_label("common_tail",16); + &mov ($np,$_np); # load modulus pointer + &mov ($rp,$_rp); # load result pointer + &lea ($tp,&DWP($frame,"esp")); # [$ap and $bp are zapped] + + &mov ("eax",&DWP(0,$tp)); # tp[0] + &mov ($j,$num); # j=num-1 + &xor ($i,$i); # i=0 and clear CF! + +&set_label("sub",16); + &sbb ("eax",&DWP(0,$np,$i,4)); + &mov (&DWP(0,$rp,$i,4),"eax"); # rp[i]=tp[i]-np[i] + &dec ($j); # doesn't affect CF! + &mov ("eax",&DWP(4,$tp,$i,4)); # tp[i+1] + &lea ($i,&DWP(1,$i)); # i++ + &jge (&label("sub")); + + &sbb ("eax",0); # handle upmost overflow bit + &and ($tp,"eax"); + ¬ ("eax"); + &mov ($np,$rp); + &and ($np,"eax"); + &or ($tp,$np); # tp=carry?tp:rp + +&set_label("copy",16); # copy or in-place refresh + &mov ("eax",&DWP(0,$tp,$num,4)); + &mov (&DWP(0,$rp,$num,4),"eax"); # rp[i]=tp[i] + &mov (&DWP($frame,"esp",$num,4),$j); # zap temporary vector + &dec ($num); + &jge (&label("copy")); + + &mov ("esp",$_sp); # pull saved stack pointer + &mov ("eax",1); +&set_label("just_leave"); +&function_end("bn_mul_mont"); + +&asciz("Montgomery Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>"); + +&asm_finish(); diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl new file mode 100755 index 000000000000..c43b69592a5c --- /dev/null +++ b/crypto/bn/asm/x86_64-mont.pl @@ -0,0 +1,214 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005. +# +# Montgomery multiplication routine for x86_64. While it gives modest +# 9% improvement of rsa4096 sign on Opteron, rsa512 sign runs more +# than twice, >2x, as fast. Most common rsa1024 sign is improved by +# respectful 50%. It remains to be seen if loop unrolling and +# dedicated squaring routine can provide further improvement... + +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open STDOUT,"| $^X $xlate $output"; + +# int bn_mul_mont( +$rp="%rdi"; # BN_ULONG *rp, +$ap="%rsi"; # const BN_ULONG *ap, +$bp="%rdx"; # const BN_ULONG *bp, +$np="%rcx"; # const BN_ULONG *np, +$n0="%r8"; # const BN_ULONG *n0, +$num="%r9"; # int num); +$lo0="%r10"; +$hi0="%r11"; +$bp="%r12"; # reassign $bp +$hi1="%r13"; +$i="%r14"; +$j="%r15"; +$m0="%rbx"; +$m1="%rbp"; + +$code=<<___; +.text + +.globl bn_mul_mont +.type bn_mul_mont,\@function,6 +.align 16 +bn_mul_mont: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov ${num}d,${num}d + lea 2($num),%rax + mov %rsp,%rbp + neg %rax + lea (%rsp,%rax,8),%rsp # tp=alloca(8*(num+2)) + and \$-1024,%rsp # minimize TLB usage + + mov %rbp,8(%rsp,$num,8) # tp[num+1]=%rsp + mov %rdx,$bp # $bp reassigned, remember? + + mov ($n0),$n0 # pull n0[0] value + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov ($bp),$m0 # m0=bp[0] + mov ($ap),%rax + mulq $m0 # ap[0]*bp[0] + mov %rax,$lo0 + mov %rdx,$hi0 + + imulq $n0,%rax # "tp[0]"*n0 + mov %rax,$m1 + + mulq ($np) # np[0]*m1 + add $lo0,%rax # discarded + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ +.L1st: + mov ($ap,$j,8),%rax + mulq $m0 # ap[j]*bp[0] + add $hi0,%rax + adc \$0,%rdx + mov %rax,$lo0 + mov ($np,$j,8),%rax + mov %rdx,$hi0 + + mulq $m1 # np[j]*m1 + add $hi1,%rax + lea 1($j),$j # j++ + adc \$0,%rdx + add $lo0,%rax # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov %rax,-16(%rsp,$j,8) # tp[j-1] + cmp $num,$j + mov %rdx,$hi1 + jl .L1st + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ +.align 4 +.Louter: + xor $j,$j # j=0 + + mov ($bp,$i,8),$m0 # m0=bp[i] + mov ($ap),%rax # ap[0] + mulq $m0 # ap[0]*bp[i] + add (%rsp),%rax # ap[0]*bp[i]+tp[0] + adc \$0,%rdx + mov %rax,$lo0 + mov %rdx,$hi0 + + imulq $n0,%rax # tp[0]*n0 + mov %rax,$m1 + + mulq ($np,$j,8) # np[0]*m1 + add $lo0,%rax # discarded + mov 8(%rsp),$lo0 # tp[1] + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ +.align 4 +.Linner: + mov ($ap,$j,8),%rax + mulq $m0 # ap[j]*bp[i] + add $hi0,%rax + adc \$0,%rdx + add %rax,$lo0 # ap[j]*bp[i]+tp[j] + mov ($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$hi0 + + mulq $m1 # np[j]*m1 + add $hi1,%rax + lea 1($j),$j # j++ + adc \$0,%rdx + add $lo0,%rax # np[j]*m1+ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov (%rsp,$j,8),$lo0 + cmp $num,$j + mov %rax,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + jl .Linner + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # pull upmost overflow bit + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + cmp $num,$i + jl .Louter + + lea (%rsp),$ap # borrow ap for tp + lea -1($num),$j # j=num-1 + + mov ($ap),%rax # tp[0] + xor $i,$i # i=0 and clear CF! + jmp .Lsub +.align 16 +.Lsub: sbb ($np,$i,8),%rax + mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i] + dec $j # doesn't affect CF! + mov 8($ap,$i,8),%rax # tp[i+1] + lea 1($i),$i # i++ + jge .Lsub + + sbb \$0,%rax # handle upmost overflow bit + and %rax,$ap + not %rax + mov $rp,$np + and %rax,$np + lea -1($num),$j + or $np,$ap # ap=borrow?tp:rp +.align 16 +.Lcopy: # copy or in-place refresh + mov ($ap,$j,8),%rax + mov %rax,($rp,$j,8) # rp[i]=tp[i] + mov $i,(%rsp,$j,8) # zap temporary vector + dec $j + jge .Lcopy + + mov 8(%rsp,$num,8),%rsp # restore %rsp + mov \$1,%rax + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret +.size bn_mul_mont,.-bn_mul_mont +.asciz "Montgomery Multiplication for x86_64, CRYPTOGAMS by <appro\@openssl.org>" +___ + +print $code; +close STDOUT; diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index 95c5d643cbd1..6d754d554776 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -245,8 +245,18 @@ extern "C" { #define BN_FLG_MALLOCED 0x01 #define BN_FLG_STATIC_DATA 0x02 -#define BN_FLG_EXP_CONSTTIME 0x04 /* avoid leaking exponent information through timings - * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */ +#define BN_FLG_CONSTTIME 0x04 /* avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ + +#ifndef OPENSSL_NO_DEPRECATED +#define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME /* deprecated name for the flag */ + /* avoid leaking exponent information through timings + * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */ +#endif + #ifndef OPENSSL_NO_DEPRECATED #define BN_FLG_FREE 0x8000 /* used for debuging */ #endif @@ -293,7 +303,12 @@ struct bn_mont_ctx_st BIGNUM N; /* The modulus */ BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 * (Ni is only stored for bignum algorithm) */ +#if 0 + /* OpenSSL 0.9.9 preview: */ + BN_ULONG n0[2];/* least significant word(s) of Ni */ +#else BN_ULONG n0; /* least significant word of Ni */ +#endif int flags; }; @@ -534,7 +549,7 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock, #define BN_BLINDING_NO_UPDATE 0x00000001 #define BN_BLINDING_NO_RECREATE 0x00000002 -BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod); +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod); void BN_BLINDING_free(BN_BLINDING *b); int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx); int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); @@ -546,7 +561,7 @@ void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long); unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, - const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx, int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx); @@ -775,6 +790,7 @@ void ERR_load_BN_strings(void); #define BN_F_BN_CTX_NEW 106 #define BN_F_BN_CTX_START 129 #define BN_F_BN_DIV 107 +#define BN_F_BN_DIV_NO_BRANCH 138 #define BN_F_BN_DIV_RECP 130 #define BN_F_BN_EXP 123 #define BN_F_BN_EXPAND2 108 @@ -793,6 +809,7 @@ void ERR_load_BN_strings(void); #define BN_F_BN_MOD_EXP_RECP 125 #define BN_F_BN_MOD_EXP_SIMPLE 126 #define BN_F_BN_MOD_INVERSE 110 +#define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 #define BN_F_BN_MOD_LSHIFT_QUICK 119 #define BN_F_BN_MOD_MUL_RECIPROCAL 111 #define BN_F_BN_MOD_SQRT 121 diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index ca22d4f8bdcb..c11fb4ccc2d3 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -131,7 +131,7 @@ struct bn_blinding_st BN_MONT_CTX *m_ctx); }; -BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod) { BN_BLINDING *ret=NULL; @@ -151,7 +151,12 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) { if ((ret->Ai = BN_dup(Ai)) == NULL) goto err; } - ret->mod = mod; + + /* save a copy of mod in the BN_BLINDING structure */ + if ((ret->mod = BN_dup(mod)) == NULL) goto err; + if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) + BN_set_flags(ret->mod, BN_FLG_CONSTTIME); + ret->counter = BN_BLINDING_COUNTER; return(ret); err: @@ -167,6 +172,7 @@ void BN_BLINDING_free(BN_BLINDING *r) if (r->A != NULL) BN_free(r->A ); if (r->Ai != NULL) BN_free(r->Ai); if (r->e != NULL) BN_free(r->e ); + if (r->mod != NULL) BN_free(r->mod); OPENSSL_free(r); } @@ -278,7 +284,7 @@ void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) } BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, - const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx, int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx) diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c index 2857f44861a7..1e8e57626be3 100644 --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -169,13 +169,15 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, #endif /* OPENSSL_NO_ASM */ -/* BN_div computes dv := num / divisor, rounding towards zero, and sets up - * rm such that dv*divisor + rm = num holds. +/* BN_div[_no_branch] computes dv := num / divisor, rounding towards + * zero, and sets up rm such that dv*divisor + rm = num holds. * Thus: * dv->neg == num->neg ^ divisor->neg (unless the result is zero) * rm->neg == num->neg (unless the remainder is zero) * If 'dv' or 'rm' is NULL, the respective value is not returned. */ +static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, + const BIGNUM *divisor, BN_CTX *ctx); int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { @@ -185,9 +187,25 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_ULONG d0,d1; int num_n,div_n; + /* Invalid zero-padding would have particularly bad consequences + * in the case of 'num', so don't just rely on bn_check_top() for this one + * (bn_check_top() works only for BN_DEBUG builds) */ + if (num->top > 0 && num->d[num->top - 1] == 0) + { + BNerr(BN_F_BN_DIV,BN_R_NOT_INITIALIZED); + return 0; + } + + bn_check_top(num); + + if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) + { + return BN_div_no_branch(dv, rm, num, divisor, ctx); + } + bn_check_top(dv); bn_check_top(rm); - bn_check_top(num); + /* bn_check_top(num); */ /* 'num' has been checked already */ bn_check_top(divisor); if (BN_is_zero(divisor)) @@ -397,4 +415,229 @@ err: return(0); } + +/* BN_div_no_branch is a special version of BN_div. It does not contain + * branches that may leak sensitive information. + */ +static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, + const BIGNUM *divisor, BN_CTX *ctx) + { + int norm_shift,i,loop; + BIGNUM *tmp,wnum,*snum,*sdiv,*res; + BN_ULONG *resp,*wnump; + BN_ULONG d0,d1; + int num_n,div_n; + + bn_check_top(dv); + bn_check_top(rm); + /* bn_check_top(num); */ /* 'num' has been checked in BN_div() */ + bn_check_top(divisor); + + if (BN_is_zero(divisor)) + { + BNerr(BN_F_BN_DIV_NO_BRANCH,BN_R_DIV_BY_ZERO); + return(0); + } + + BN_CTX_start(ctx); + tmp=BN_CTX_get(ctx); + snum=BN_CTX_get(ctx); + sdiv=BN_CTX_get(ctx); + if (dv == NULL) + res=BN_CTX_get(ctx); + else res=dv; + if (sdiv == NULL || res == NULL) goto err; + + /* First we normalise the numbers */ + norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); + if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; + sdiv->neg=0; + norm_shift+=BN_BITS2; + if (!(BN_lshift(snum,num,norm_shift))) goto err; + snum->neg=0; + + /* Since we don't know whether snum is larger than sdiv, + * we pad snum with enough zeroes without changing its + * value. + */ + if (snum->top <= sdiv->top+1) + { + if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err; + for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0; + snum->top = sdiv->top + 2; + } + else + { + if (bn_wexpand(snum, snum->top + 1) == NULL) goto err; + snum->d[snum->top] = 0; + snum->top ++; + } + + div_n=sdiv->top; + num_n=snum->top; + loop=num_n-div_n; + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided */ + wnum.neg = 0; + wnum.d = &(snum->d[loop]); + wnum.top = div_n; + /* only needed when BN_ucmp messes up the values between top and max */ + wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ + + /* Get the top 2 words of sdiv */ + /* div_n=sdiv->top; */ + d0=sdiv->d[div_n-1]; + d1=(div_n == 1)?0:sdiv->d[div_n-2]; + + /* pointer to the 'top' of snum */ + wnump= &(snum->d[num_n-1]); + + /* Setup to 'res' */ + res->neg= (num->neg^divisor->neg); + if (!bn_wexpand(res,(loop+1))) goto err; + res->top=loop-1; + resp= &(res->d[loop-1]); + + /* space for temp */ + if (!bn_wexpand(tmp,(div_n+1))) goto err; + + /* if res->top == 0 then clear the neg value otherwise decrease + * the resp pointer */ + if (res->top == 0) + res->neg = 0; + else + resp--; + + for (i=0; i<loop-1; i++, wnump--, resp--) + { + BN_ULONG q,l0; + /* the first part of the loop uses the top two words of + * snum and sdiv to calculate a BN_ULONG q such that + * | wnum - sdiv * q | < sdiv */ +#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) + BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG); + q=bn_div_3_words(wnump,d1,d0); +#else + BN_ULONG n0,n1,rem=0; + + n0=wnump[0]; + n1=wnump[-1]; + if (n0 == d0) + q=BN_MASK2; + else /* n0 < d0 */ + { +#ifdef BN_LLONG + BN_ULLONG t2; + +#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) + q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0); +#else + q=bn_div_words(n0,n1,d0); +#ifdef BN_DEBUG_LEVITTE + fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ +X) -> 0x%08X\n", + n0, n1, d0, q); +#endif +#endif + +#ifndef REMAINDER_IS_ALREADY_CALCULATED + /* + * rem doesn't have to be BN_ULLONG. The least we + * know it's less that d0, isn't it? + */ + rem=(n1-q*d0)&BN_MASK2; +#endif + t2=(BN_ULLONG)d1*q; + + for (;;) + { + if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2])) + break; + q--; + rem += d0; + if (rem < d0) break; /* don't let rem overflow */ + t2 -= d1; + } +#else /* !BN_LLONG */ + BN_ULONG t2l,t2h,ql,qh; + + q=bn_div_words(n0,n1,d0); +#ifdef BN_DEBUG_LEVITTE + fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ +X) -> 0x%08X\n", + n0, n1, d0, q); +#endif +#ifndef REMAINDER_IS_ALREADY_CALCULATED + rem=(n1-q*d0)&BN_MASK2; +#endif + +#if defined(BN_UMULT_LOHI) + BN_UMULT_LOHI(t2l,t2h,d1,q); +#elif defined(BN_UMULT_HIGH) + t2l = d1 * q; + t2h = BN_UMULT_HIGH(d1,q); +#else + t2l=LBITS(d1); t2h=HBITS(d1); + ql =LBITS(q); qh =HBITS(q); + mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */ +#endif + + for (;;) + { + if ((t2h < rem) || + ((t2h == rem) && (t2l <= wnump[-2]))) + break; + q--; + rem += d0; + if (rem < d0) break; /* don't let rem overflow */ + if (t2l < d1) t2h--; t2l -= d1; + } +#endif /* !BN_LLONG */ + } +#endif /* !BN_DIV3W */ + + l0=bn_mul_words(tmp->d,sdiv->d,div_n,q); + tmp->d[div_n]=l0; + wnum.d--; + /* ingore top values of the bignums just sub the two + * BN_ULONG arrays with bn_sub_words */ + if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1)) + { + /* Note: As we have considered only the leading + * two BN_ULONGs in the calculation of q, sdiv * q + * might be greater than wnum (but then (q-1) * sdiv + * is less or equal than wnum) + */ + q--; + if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) + /* we can't have an overflow here (assuming + * that q != 0, but if q == 0 then tmp is + * zero anyway) */ + (*wnump)++; + } + /* store part of the result */ + *resp = q; + } + bn_correct_top(snum); + if (rm != NULL) + { + /* Keep a copy of the neg flag in num because if rm==num + * BN_rshift() will overwrite it. + */ + int neg = num->neg; + BN_rshift(rm,snum,norm_shift); + if (!BN_is_zero(rm)) + rm->neg = neg; + bn_check_top(rm); + } + bn_correct_top(res); + BN_CTX_end(ctx); + return(1); +err: + bn_check_top(rm); + BN_CTX_end(ctx); + return(0); + } + #endif diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c index 24fbbb772d0f..cfe2eb94a0ce 100644 --- a/crypto/bn/bn_err.c +++ b/crypto/bn/bn_err.c @@ -1,6 +1,6 @@ /* crypto/bn/bn_err.c */ /* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -82,6 +82,7 @@ static ERR_STRING_DATA BN_str_functs[]= {ERR_FUNC(BN_F_BN_CTX_NEW), "BN_CTX_new"}, {ERR_FUNC(BN_F_BN_CTX_START), "BN_CTX_start"}, {ERR_FUNC(BN_F_BN_DIV), "BN_div"}, +{ERR_FUNC(BN_F_BN_DIV_NO_BRANCH), "BN_div_no_branch"}, {ERR_FUNC(BN_F_BN_DIV_RECP), "BN_div_recp"}, {ERR_FUNC(BN_F_BN_EXP), "BN_exp"}, {ERR_FUNC(BN_F_BN_EXPAND2), "bn_expand2"}, @@ -100,6 +101,7 @@ static ERR_STRING_DATA BN_str_functs[]= {ERR_FUNC(BN_F_BN_MOD_EXP_RECP), "BN_mod_exp_recp"}, {ERR_FUNC(BN_F_BN_MOD_EXP_SIMPLE), "BN_mod_exp_simple"}, {ERR_FUNC(BN_F_BN_MOD_INVERSE), "BN_mod_inverse"}, +{ERR_FUNC(BN_F_BN_MOD_INVERSE_NO_BRANCH), "BN_mod_inverse_no_branch"}, {ERR_FUNC(BN_F_BN_MOD_LSHIFT_QUICK), "BN_mod_lshift_quick"}, {ERR_FUNC(BN_F_BN_MOD_MUL_RECIPROCAL), "BN_mod_mul_reciprocal"}, {ERR_FUNC(BN_F_BN_MOD_SQRT), "BN_mod_sqrt"}, diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 8f8c69448191..70a33f0d936c 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -122,9 +122,9 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) int i,bits,ret=0; BIGNUM *v,*rr; - if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { - /* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ BNerr(BN_F_BN_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } @@ -213,7 +213,7 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, if (BN_is_odd(m)) { # ifdef MONT_EXP_WORD - if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) == 0)) + if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_CONSTTIME) == 0)) { BN_ULONG A = a->d[0]; ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); @@ -245,9 +245,9 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BIGNUM *val[TABLE_SIZE]; BN_RECP_CTX recp; - if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { - /* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ BNerr(BN_F_BN_MOD_EXP_RECP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } @@ -379,7 +379,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, BIGNUM *val[TABLE_SIZE]; BN_MONT_CTX *mont=NULL; - if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); } @@ -745,9 +745,9 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, #define BN_TO_MONTGOMERY_WORD(r, w, mont) \ (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) - if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { - /* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ BNerr(BN_F_BN_MOD_EXP_MONT_WORD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } @@ -881,9 +881,9 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, /* Table of variables obtained from 'ctx' */ BIGNUM *val[TABLE_SIZE]; - if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0) + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { - /* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */ + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ BNerr(BN_F_BN_MOD_EXP_SIMPLE,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c index f02e6fcdb422..4a352119ba8a 100644 --- a/crypto/bn/bn_gcd.c +++ b/crypto/bn/bn_gcd.c @@ -203,6 +203,8 @@ err: /* solves ax == 1 (mod n) */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { @@ -210,6 +212,11 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, BIGNUM *ret=NULL; int sign; + if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) + { + return BN_mod_inverse_no_branch(in, a, n, ctx); + } + bn_check_top(a); bn_check_top(n); @@ -491,3 +498,157 @@ err: bn_check_top(ret); return(ret); } + + +/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. + * It does not contain branches that may leak sensitive information. + */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) + { + BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; + BIGNUM local_A, local_B; + BIGNUM *pA, *pB; + BIGNUM *ret=NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) goto err; + + if (in == NULL) + R=BN_new(); + else + R=in; + if (R == NULL) goto err; + + BN_one(X); + BN_zero(Y); + if (BN_copy(B,a) == NULL) goto err; + if (BN_copy(A,n) == NULL) goto err; + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) + { + /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pB = &local_B; + BN_with_flags(pB, B, BN_FLG_CONSTTIME); + if (!BN_nnmod(B, pB, A, ctx)) goto err; + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) + { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pA = &local_A; + BN_with_flags(pA, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div(D,M,pA,B,ctx)) goto err; + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp=A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A=B; + B=M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp,D,X,ctx)) goto err; + if (!BN_add(tmp,tmp,Y)) goto err; + + M=Y; /* keep the BIGNUM object, the value does not matter */ + Y=X; + X=tmp; + sign = -sign; + } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) + { + if (!BN_sub(Y,n,Y)) goto err; + } + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) + { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y,n) < 0) + { + if (!BN_copy(R,Y)) goto err; + } + else + { + if (!BN_nnmod(R,Y,n,ctx)) goto err; + } + } + else + { + BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE); + goto err; + } + ret=R; +err: + if ((ret == NULL) && (in == NULL)) BN_free(R); + BN_CTX_end(ctx); + bn_check_top(ret); + return(ret); + } diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c index 6a793857e130..306f029f2789 100644 --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -384,7 +384,11 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]) if (zz == 0) break; d1 = BN_BITS2 - d0; - if (d0) z[dN] = (z[dN] << d1) >> d1; /* clear up the top d1 bits */ + /* clear up the top d1 bits */ + if (d0) + z[dN] = (z[dN] << d1) >> d1; + else + z[dN] = 0; z[0] ^= zz; /* reduction t^0 component */ for (k = 1; p[k] != 0; k++) diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h index ad4ca7ff305a..27ac4397a151 100644 --- a/crypto/bn/bn_lcl.h +++ b/crypto/bn/bn_lcl.h @@ -481,6 +481,7 @@ BN_ULONG bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num); #ifdef __cplusplus } diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 210ccb42bba1..2649b8c53851 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -763,7 +763,7 @@ int BN_is_bit_set(const BIGNUM *a, int n) i=n/BN_BITS2; j=n%BN_BITS2; if (a->top <= i) return 0; - return((a->d[i]&(((BN_ULONG)1)<<j))?1:0); + return(((a->d[i])>>j)&((BN_ULONG)1)); } int BN_mask_bits(BIGNUM *a, int n) diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 961ca67ea1f5..4799b152ddcb 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -122,11 +122,50 @@ #define MONT_WORD /* use the faster word-based algorithm */ +#if defined(MONT_WORD) && defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) +/* This condition means we have a specific non-default build: + * In the 0.9.8 branch, OPENSSL_BN_ASM_MONT is normally not set for any + * BN_BITS2<=32 platform; an explicit "enable-montasm" is required. + * I.e., if we are here, the user intentionally deviates from the + * normal stable build to get better Montgomery performance from + * the 0.9.9-dev backport. + * + * In this case only, we also enable BN_from_montgomery_word() + * (another non-stable feature from 0.9.9-dev). + */ +#define MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD +#endif + +#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont); +#endif + + + int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret=0; +#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) + int num = mont->N.top; + + if (num>1 && a->top==num && b->top==num) + { + if (bn_wexpand(r,num) == NULL) return(0); +#if 0 /* for OpenSSL 0.9.9 mont->n0 */ + if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,mont->n0,num)) +#else + if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,&mont->n0,num)) +#endif + { + r->neg = a->neg^b->neg; + r->top = num; + bn_correct_top(r); + return(1); + } + } +#endif BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); @@ -142,7 +181,11 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, if (!BN_mul(tmp,a,b,ctx)) goto err; } /* reduce from aRR to aR */ +#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD + if (!BN_from_montgomery_word(r,tmp,mont)) goto err; +#else if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; +#endif bn_check_top(r); ret=1; err: @@ -150,6 +193,150 @@ err: return(ret); } +#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) + { + BIGNUM *n; + BN_ULONG *ap,*np,*rp,n0,v,*nrp; + int al,nl,max,i,x,ri; + + n= &(mont->N); + /* mont->ri is the size of mont->N in bits (rounded up + to the word size) */ + al=ri=mont->ri/BN_BITS2; + + nl=n->top; + if ((al == 0) || (nl == 0)) { ret->top=0; return(1); } + + max=(nl+al+1); /* allow for overflow (no?) XXX */ + if (bn_wexpand(r,max) == NULL) return(0); + + r->neg^=n->neg; + np=n->d; + rp=r->d; + nrp= &(r->d[nl]); + + /* clear the top words of T */ + for (i=r->top; i<max; i++) /* memset? XXX */ + r->d[i]=0; + + r->top=max; +#if 0 /* for OpenSSL 0.9.9 mont->n0 */ + n0=mont->n0[0]; +#else + n0=mont->n0; +#endif + +#ifdef BN_COUNT + fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl); +#endif + for (i=0; i<nl; i++) + { +#ifdef __TANDEM + { + long long t1; + long long t2; + long long t3; + t1 = rp[0] * (n0 & 0177777); + t2 = 037777600000l; + t2 = n0 & t2; + t3 = rp[0] & 0177777; + t2 = (t3 * t2) & BN_MASK2; + t1 = t1 + t2; + v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1); + } +#else + v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); +#endif + nrp++; + rp++; + if (((nrp[-1]+=v)&BN_MASK2) >= v) + continue; + else + { + if (((++nrp[0])&BN_MASK2) != 0) continue; + if (((++nrp[1])&BN_MASK2) != 0) continue; + for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; + } + } + bn_correct_top(r); + + /* mont->ri will be a multiple of the word size and below code + * is kind of BN_rshift(ret,r,mont->ri) equivalent */ + if (r->top <= ri) + { + ret->top=0; + return(1); + } + al=r->top-ri; + + if (bn_wexpand(ret,ri) == NULL) return(0); + x=0-(((al-ri)>>(sizeof(al)*8-1))&1); + ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */ + ret->neg=r->neg; + + rp=ret->d; + ap=&(r->d[ri]); + + { + size_t m1,m2; + + v=bn_sub_words(rp,ap,np,ri); + /* this ----------------^^ works even in al<ri case + * thanks to zealous zeroing of top of the vector in the + * beginning. */ + + /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */ + /* in other words if subtraction result is real, then + * trick unconditional memcpy below to perform in-place + * "refresh" instead of actual copy. */ + m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */ + m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */ + m1|=m2; /* (al!=ri) */ + m1|=(0-(size_t)v); /* (al!=ri || v) */ + m1&=~m2; /* (al!=ri || v) && !al>ri */ + nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1)); + } + + /* 'i<ri' is chosen to eliminate dependency on input data, even + * though it results in redundant copy in al<ri case. */ + for (i=0,ri-=4; i<ri; i+=4) + { + BN_ULONG t1,t2,t3,t4; + + t1=nrp[i+0]; + t2=nrp[i+1]; + t3=nrp[i+2]; ap[i+0]=0; + t4=nrp[i+3]; ap[i+1]=0; + rp[i+0]=t1; ap[i+2]=0; + rp[i+1]=t2; ap[i+3]=0; + rp[i+2]=t3; + rp[i+3]=t4; + } + for (ri+=4; i<ri; i++) + rp[i]=nrp[i], ap[i]=0; + bn_correct_top(r); + bn_correct_top(ret); + bn_check_top(ret); + + return(1); + } + +int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) + { + int retn=0; + BIGNUM *t; + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) && BN_copy(t,a)) + retn = BN_from_montgomery_word(ret,t,mont); + BN_CTX_end(ctx); + return retn; + } + +#else /* !MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */ + int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { @@ -176,7 +363,6 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, max=(nl+al+1); /* allow for overflow (no?) XXX */ if (bn_wexpand(r,max) == NULL) goto err; - if (bn_wexpand(ret,max) == NULL) goto err; r->neg=a->neg^n->neg; np=n->d; @@ -228,19 +414,72 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, } bn_correct_top(r); - /* mont->ri will be a multiple of the word size */ -#if 0 - BN_rshift(ret,r,mont->ri); -#else - ret->neg = r->neg; - x=ri; + /* mont->ri will be a multiple of the word size and below code + * is kind of BN_rshift(ret,r,mont->ri) equivalent */ + if (r->top <= ri) + { + ret->top=0; + retn=1; + goto err; + } + al=r->top-ri; + +# define BRANCH_FREE 1 +# if BRANCH_FREE + if (bn_wexpand(ret,ri) == NULL) goto err; + x=0-(((al-ri)>>(sizeof(al)*8-1))&1); + ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */ + ret->neg=r->neg; + rp=ret->d; - ap= &(r->d[x]); - if (r->top < x) - al=0; - else - al=r->top-x; + ap=&(r->d[ri]); + + { + size_t m1,m2; + + v=bn_sub_words(rp,ap,np,ri); + /* this ----------------^^ works even in al<ri case + * thanks to zealous zeroing of top of the vector in the + * beginning. */ + + /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */ + /* in other words if subtraction result is real, then + * trick unconditional memcpy below to perform in-place + * "refresh" instead of actual copy. */ + m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */ + m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */ + m1|=m2; /* (al!=ri) */ + m1|=(0-(size_t)v); /* (al!=ri || v) */ + m1&=~m2; /* (al!=ri || v) && !al>ri */ + nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1)); + } + + /* 'i<ri' is chosen to eliminate dependency on input data, even + * though it results in redundant copy in al<ri case. */ + for (i=0,ri-=4; i<ri; i+=4) + { + BN_ULONG t1,t2,t3,t4; + + t1=nrp[i+0]; + t2=nrp[i+1]; + t3=nrp[i+2]; ap[i+0]=0; + t4=nrp[i+3]; ap[i+1]=0; + rp[i+0]=t1; ap[i+2]=0; + rp[i+1]=t2; ap[i+3]=0; + rp[i+2]=t3; + rp[i+3]=t4; + } + for (ri+=4; i<ri; i++) + rp[i]=nrp[i], ap[i]=0; + bn_correct_top(r); + bn_correct_top(ret); +# else + if (bn_wexpand(ret,al) == NULL) goto err; ret->top=al; + ret->neg=r->neg; + + rp=ret->d; + ap=&(r->d[ri]); al-=4; for (i=0; i<al; i+=4) { @@ -258,7 +497,7 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, al+=4; for (; i<al; i++) rp[i]=ap[i]; -#endif +# endif #else /* !MONT_WORD */ BIGNUM *t1,*t2; @@ -278,16 +517,19 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, if (!BN_rshift(ret,t2,mont->ri)) goto err; #endif /* MONT_WORD */ +#if !defined(BRANCH_FREE) || BRANCH_FREE==0 if (BN_ucmp(ret, &(mont->N)) >= 0) { if (!BN_usub(ret,ret,&(mont->N))) goto err; } +#endif retn=1; bn_check_top(ret); err: BN_CTX_end(ctx); return(retn); } +#endif /* MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */ BN_MONT_CTX *BN_MONT_CTX_new(void) { @@ -307,6 +549,11 @@ void BN_MONT_CTX_init(BN_MONT_CTX *ctx) BN_init(&(ctx->RR)); BN_init(&(ctx->N)); BN_init(&(ctx->Ni)); +#if 0 /* for OpenSSL 0.9.9 mont->n0 */ + ctx->n0[0] = ctx->n0[1] = 0; +#else + ctx->n0 = 0; +#endif ctx->flags=0; } @@ -340,14 +587,51 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; BN_zero(R); +#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)", + only certain BN_BITS2<=32 platforms actually need this */ + if (!(BN_set_bit(R,2*BN_BITS2))) goto err; /* R */ +#else if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ +#endif buf[0]=mod->d[0]; /* tmod = N mod word size */ buf[1]=0; + + BN_init(&tmod); tmod.d=buf; tmod.top = buf[0] != 0 ? 1 : 0; tmod.dmax=2; tmod.neg=0; + +#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)"; + only certain BN_BITS2<=32 platforms actually need this */ + tmod.top=0; + if ((buf[0] = mod->d[0])) tmod.top=1; + if ((buf[1] = mod->top>1 ? mod->d[1] : 0)) tmod.top=2; + + if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) + goto err; + if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */ + if (!BN_is_zero(Ri)) + { + if (!BN_sub_word(Ri,1)) goto err; + } + else /* if N mod word size == 1 */ + { + if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL) + goto err; + /* Ri-- (mod double word size) */ + Ri->neg=0; + Ri->d[0]=BN_MASK2; + Ri->d[1]=BN_MASK2; + Ri->top=2; + } + if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; + /* Ni = (R*Ri-1)/N, + * keep only couple of least significant words: */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; +#else /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) goto err; @@ -363,7 +647,13 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only least significant word: */ +# if 0 /* for OpenSSL 0.9.9 mont->n0 */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = 0; +# else mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0; +# endif +#endif } #else /* !MONT_WORD */ { /* bignum version */ @@ -399,7 +689,12 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) if (!BN_copy(&(to->N),&(from->N))) return NULL; if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL; to->ri=from->ri; +#if 0 /* for OpenSSL 0.9.9 mont->n0 */ + to->n0[0]=from->n0[0]; + to->n0[1]=from->n0[1]; +#else to->n0=from->n0; +#endif return(to); } diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c index aec1eafc65fb..b848c8cc60f4 100644 --- a/crypto/bn/bn_mul.c +++ b/crypto/bn/bn_mul.c @@ -389,6 +389,7 @@ BN_ULONG bn_add_part_words(BN_ULONG *r, * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) * a[1]*b[1] */ +/* dnX may not be positive, but n2/2+dnX has to be */ void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, int dna, int dnb, BN_ULONG *t) { @@ -398,7 +399,7 @@ void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, BN_ULONG ln,lo,*p; # ifdef BN_COUNT - fprintf(stderr," bn_mul_recursive %d * %d\n",n2,n2); + fprintf(stderr," bn_mul_recursive %d%+d * %d%+d\n",n2,dna,n2,dnb); # endif # ifdef BN_MUL_COMBA # if 0 @@ -545,6 +546,7 @@ void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, /* n+tn is the word length * t needs to be n*4 is size, as does r */ +/* tnX may not be negative but less than n */ void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, int tna, int tnb, BN_ULONG *t) { @@ -553,8 +555,8 @@ void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, BN_ULONG ln,lo,*p; # ifdef BN_COUNT - fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n", - tna, n, tnb, n); + fprintf(stderr," bn_mul_part_recursive (%d%+d) * (%d%+d)\n", + n, tna, n, tnb); # endif if (n < 8) { @@ -655,14 +657,17 @@ void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, for (;;) { i/=2; - if (i < tna && i < tnb) + /* these simplified conditions work + * exclusively because difference + * between tna and tnb is 1 or 0 */ + if (i < tna || i < tnb) { bn_mul_part_recursive(&(r[n2]), &(a[n]),&(b[n]), i,tna-i,tnb-i,p); break; } - else if (i <= tna && i <= tnb) + else if (i == tna || i == tnb) { bn_mul_recursive(&(r[n2]), &(a[n]),&(b[n]), diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index f8e306bb82d3..1fc94f55c32c 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -59,6 +59,7 @@ #include "bn_lcl.h" #include "cryptlib.h" + #define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2 #define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2 #define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2 @@ -99,114 +100,106 @@ static const BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, 0xFFFFFFFF,0x000001FF}; -#elif BN_BITS2 == 16 -static const BN_ULONG _nist_p_192[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFE, - 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}; -static const BN_ULONG _nist_p_224[] = {0x0001,0x0000,0x0000,0x0000,0x0000, - 0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}; -static const BN_ULONG _nist_p_256[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, - 0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x0000,0xFFFF, - 0xFFFF}; -static const BN_ULONG _nist_p_384[] = {0xFFFF,0xFFFF,0x0000,0x0000,0x0000, - 0x0000,0xFFFF,0xFFFF,0xFFFE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, - 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}; -static const BN_ULONG _nist_p_521[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, - 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, - 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, - 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x01FF}; -#elif BN_BITS2 == 8 -static const BN_ULONG _nist_p_192[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF}; -static const BN_ULONG _nist_p_224[] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; -static const BN_ULONG _nist_p_256[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF}; -static const BN_ULONG _nist_p_384[] = {0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; -static const BN_ULONG _nist_p_521[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0x01}; #endif + +static const BIGNUM _bignum_nist_p_192 = + { + (BN_ULONG *)_nist_p_192, + BN_NIST_192_TOP, + BN_NIST_192_TOP, + 0, + BN_FLG_STATIC_DATA + }; + +static const BIGNUM _bignum_nist_p_224 = + { + (BN_ULONG *)_nist_p_224, + BN_NIST_224_TOP, + BN_NIST_224_TOP, + 0, + BN_FLG_STATIC_DATA + }; + +static const BIGNUM _bignum_nist_p_256 = + { + (BN_ULONG *)_nist_p_256, + BN_NIST_256_TOP, + BN_NIST_256_TOP, + 0, + BN_FLG_STATIC_DATA + }; + +static const BIGNUM _bignum_nist_p_384 = + { + (BN_ULONG *)_nist_p_384, + BN_NIST_384_TOP, + BN_NIST_384_TOP, + 0, + BN_FLG_STATIC_DATA + }; + +static const BIGNUM _bignum_nist_p_521 = + { + (BN_ULONG *)_nist_p_521, + BN_NIST_521_TOP, + BN_NIST_521_TOP, + 0, + BN_FLG_STATIC_DATA + }; + + const BIGNUM *BN_get0_nist_prime_192(void) { - static BIGNUM const_nist_192 = { (BN_ULONG *)_nist_p_192, - BN_NIST_192_TOP, BN_NIST_192_TOP, 0, BN_FLG_STATIC_DATA }; - return &const_nist_192; + return &_bignum_nist_p_192; } const BIGNUM *BN_get0_nist_prime_224(void) { - static BIGNUM const_nist_224 = { (BN_ULONG *)_nist_p_224, - BN_NIST_224_TOP, BN_NIST_224_TOP, 0, BN_FLG_STATIC_DATA }; - return &const_nist_224; + return &_bignum_nist_p_224; } const BIGNUM *BN_get0_nist_prime_256(void) { - static BIGNUM const_nist_256 = { (BN_ULONG *)_nist_p_256, - BN_NIST_256_TOP, BN_NIST_256_TOP, 0, BN_FLG_STATIC_DATA }; - return &const_nist_256; + return &_bignum_nist_p_256; } const BIGNUM *BN_get0_nist_prime_384(void) { - static BIGNUM const_nist_384 = { (BN_ULONG *)_nist_p_384, - BN_NIST_384_TOP, BN_NIST_384_TOP, 0, BN_FLG_STATIC_DATA }; - return &const_nist_384; + return &_bignum_nist_p_384; } const BIGNUM *BN_get0_nist_prime_521(void) { - static BIGNUM const_nist_521 = { (BN_ULONG *)_nist_p_521, - BN_NIST_521_TOP, BN_NIST_521_TOP, 0, BN_FLG_STATIC_DATA }; - return &const_nist_521; + return &_bignum_nist_p_521; } -/* some misc internal functions */ -#if BN_BITS2 != 64 -static BN_ULONG _256_data[BN_NIST_256_TOP*6]; -static int _is_set_256_data = 0; -static void _init_256_data(void); - -static BN_ULONG _384_data[BN_NIST_384_TOP*8]; -static int _is_set_384_data = 0; -static void _init_384_data(void); -#endif - -#define BN_NIST_ADD_ONE(a) while (!(++(*(a)))) ++(a); static void nist_cp_bn_0(BN_ULONG *buf, BN_ULONG *a, int top, int max) - { + { int i; - BN_ULONG *_tmp1 = (buf), *_tmp2 = (a); - for (i = (top); i != 0; i--) - *_tmp1++ = *_tmp2++; - for (i = (max) - (top); i != 0; i--) - *_tmp1++ = (BN_ULONG) 0; - } + BN_ULONG *_tmp1 = (buf), *_tmp2 = (a); + + OPENSSL_assert(top <= max); + for (i = (top); i != 0; i--) + *_tmp1++ = *_tmp2++; + for (i = (max) - (top); i != 0; i--) + *_tmp1++ = (BN_ULONG) 0; + } static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top) - { + { int i; - BN_ULONG *_tmp1 = (buf), *_tmp2 = (a); - for (i = (top); i != 0; i--) - *_tmp1++ = *_tmp2++; - } + BN_ULONG *_tmp1 = (buf), *_tmp2 = (a); + for (i = (top); i != 0; i--) + *_tmp1++ = *_tmp2++; + } #if BN_BITS2 == 64 -#define bn_cp_64(to, n, from, m) (to)[n] = (from)[m]; +#define bn_cp_64(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0; #define bn_64_set_0(to, n) (to)[n] = (BN_ULONG)0; /* TBD */ -#define bn_cp_32(to, n, from, m) (to)[n] = (from)[m]; +#define bn_cp_32(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0; #define bn_32_set_0(to, n) (to)[n] = (BN_ULONG)0; #else #define bn_cp_64(to, n, from, m) \ @@ -220,26 +213,8 @@ static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top) bn_32_set_0(to, (n)*2+1); \ } #if BN_BITS2 == 32 -#define bn_cp_32(to, n, from, m) (to)[n] = (from)[m]; +#define bn_cp_32(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0; #define bn_32_set_0(to, n) (to)[n] = (BN_ULONG)0; -#elif BN_BITS2 == 16 -#define bn_cp_32(to, n, from, m) \ - { \ - (to)[(n)*2] = (from)[(m)*2]; \ - (to)[(n)*2+1] = (from)[(m)*2+1];\ - } -#define bn_32_set_0(to, n) { (to)[(n)*2] = 0; (to)[(n)*2+1] = 0; } -#elif BN_BITS2 == 8 -#define bn_cp_32(to, n, from, m) \ - { \ - (to)[(n)*4] = (from)[(m)*4]; \ - (to)[(n)*4+1] = (from)[(m)*4+1];\ - (to)[(n)*4+2] = (from)[(m)*4+2];\ - (to)[(n)*4+3] = (from)[(m)*4+3];\ - } -#define bn_32_set_0(to, n) \ - { (to)[(n)*4] = (BN_ULONG)0; (to)[(n)*4+1] = (BN_ULONG)0; \ - (to)[(n)*4+2] = (BN_ULONG)0; (to)[(n)*4+3] = (BN_ULONG)0; } #endif #endif /* BN_BITS2 != 64 */ @@ -255,10 +230,18 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) { int top = a->top, i; - BN_ULONG carry = 0; + int carry; register BN_ULONG *r_d, *a_d = a->d; BN_ULONG t_d[BN_NIST_192_TOP], - buf[BN_NIST_192_TOP]; + buf[BN_NIST_192_TOP], + c_d[BN_NIST_192_TOP], + *res; + size_t mask; + + field = &_bignum_nist_p_192; /* just to make sure */ + + if (BN_is_negative(a) || a->top > 2*BN_NIST_192_TOP) + return BN_nnmod(r, field, a, ctx); i = BN_ucmp(field, a); if (i == 0) @@ -269,9 +252,6 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, else if (i > 0) return (r == a) ? 1 : (BN_copy(r ,a) != NULL); - if (top == BN_NIST_192_TOP) - return BN_usub(r, a, field); - if (r != a) { if (!bn_wexpand(r, BN_NIST_192_TOP)) @@ -284,41 +264,33 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, nist_cp_bn_0(buf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, BN_NIST_192_TOP); -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma message save -# pragma message disable BADSUBSCRIPT -#endif - nist_set_192(t_d, buf, 0, 3, 3); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP)) - ++carry; - + carry = bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_set_192(t_d, buf, 4, 4, 0); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP)) - ++carry; - -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma message restore -#endif + carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); nist_set_192(t_d, buf, 5, 5, 5) - if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); - while (carry) - { - if (bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP)) - --carry; - } + nist_cp_bn(r_d, res, BN_NIST_192_TOP); r->top = BN_NIST_192_TOP; bn_correct_top(r); - if (BN_ucmp(r, field) >= 0) + + if (BN_ucmp(field, r) <= 0) { - bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP); - bn_correct_top(r); + if (!BN_usub(r, r, field)) return 0; } - bn_check_top(r); return 1; } @@ -336,12 +308,20 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) { -#if BN_BITS2 != 64 +#if BN_BITS2 == 32 int top = a->top, i; - int carry = 0; + int carry; BN_ULONG *r_d, *a_d = a->d; BN_ULONG t_d[BN_NIST_224_TOP], - buf[BN_NIST_224_TOP]; + buf[BN_NIST_224_TOP], + c_d[BN_NIST_224_TOP], + *res; + size_t mask; + + field = &_bignum_nist_p_224; /* just to make sure */ + + if (BN_is_negative(a) || a->top > 2*BN_NIST_224_TOP) + return BN_nnmod(r, field, a, ctx); i = BN_ucmp(field, a); if (i == 0) @@ -352,9 +332,6 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, else if (i > 0) return (r == a)? 1 : (BN_copy(r ,a) != NULL); - if (top == BN_NIST_224_TOP) - return BN_usub(r, a, field); - if (r != a) { if (!bn_wexpand(r, BN_NIST_224_TOP)) @@ -368,65 +345,53 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, nist_cp_bn_0(buf, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, BN_NIST_224_TOP); nist_set_224(t_d, buf, 10, 9, 8, 7, 0, 0, 0); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP)) - ++carry; + carry = bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_set_224(t_d, buf, 0, 13, 12, 11, 0, 0, 0); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_224_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_set_224(t_d, buf, 13, 12, 11, 10, 9, 8, 7); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP)) - --carry; +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP); + bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else + if (bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP)) + bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP); +#endif nist_set_224(t_d, buf, 0, 0, 0, 0, 13, 12, 11); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP)) - --carry; - - if (carry > 0) - while (carry) - { - if (bn_sub_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP)) - --carry; - } - else if (carry < 0) - while (carry) - { - if (bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP)) - ++carry; - } +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP); + bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_cp_bn(r_d, res, BN_NIST_224_TOP); +#else + if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP)) + bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP); +#endif r->top = BN_NIST_224_TOP; bn_correct_top(r); - if (BN_ucmp(r, field) >= 0) + + if (BN_ucmp(field, r) <= 0) { - bn_sub_words(r_d, r_d, _nist_p_224, BN_NIST_224_TOP); - bn_correct_top(r); + if (!BN_usub(r, r, field)) return 0; } - bn_check_top(r); + return 1; -#else +#else /* BN_BITS!=32 */ return 0; #endif } -#if BN_BITS2 != 64 -static void _init_256_data(void) - { - int i; - BN_ULONG *tmp1 = _256_data; - const BN_ULONG *tmp2 = tmp1; - - memcpy(tmp1, _nist_p_256, BN_NIST_256_TOP * sizeof(BN_ULONG)); - tmp1 += BN_NIST_256_TOP; - - for (i=0; i<5; i++) - { - bn_add_words(tmp1, _nist_p_256, tmp2, BN_NIST_256_TOP); - tmp2 = tmp1; - tmp1 += BN_NIST_256_TOP; - } - _is_set_256_data = 1; - } -#endif - #define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \ { \ if (a8 != 0) bn_cp_32(to, 0, from, (a8) - 8) else bn_32_set_0(to, 0)\ @@ -442,24 +407,21 @@ static void _init_256_data(void) int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) { -#if BN_BITS2 != 64 +#if BN_BITS2 == 32 int i, top = a->top; int carry = 0; register BN_ULONG *a_d = a->d, *r_d; BN_ULONG t_d[BN_NIST_256_TOP], - t_d2[BN_NIST_256_TOP], - buf[BN_NIST_256_TOP]; + buf[BN_NIST_256_TOP], + c_d[BN_NIST_256_TOP], + *res; + size_t mask; + + field = &_bignum_nist_p_256; /* just to make sure */ + + if (BN_is_negative(a) || a->top > 2*BN_NIST_256_TOP) + return BN_nnmod(r, field, a, ctx); - if (!_is_set_256_data) - { - CRYPTO_w_lock(CRYPTO_LOCK_BN); - - if (!_is_set_256_data) - _init_256_data(); - - CRYPTO_w_unlock(CRYPTO_LOCK_BN); - } - i = BN_ucmp(field, a); if (i == 0) { @@ -469,9 +431,6 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, else if (i > 0) return (r == a)? 1 : (BN_copy(r ,a) != NULL); - if (top == BN_NIST_256_TOP) - return BN_usub(r, a, field); - if (r != a) { if (!bn_wexpand(r, BN_NIST_256_TOP)) @@ -487,98 +446,96 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, /*S1*/ nist_set_256(t_d, buf, 15, 14, 13, 12, 11, 0, 0, 0); /*S2*/ - nist_set_256(t_d2,buf, 0, 15, 14, 13, 12, 0, 0, 0); - if (bn_add_words(t_d, t_d, t_d2, BN_NIST_256_TOP)) - carry = 2; - /* left shift */ - { - register BN_ULONG *ap,t,c; - ap = t_d; - c=0; - for (i = BN_NIST_256_TOP; i != 0; --i) - { - t= *ap; - *(ap++)=((t<<1)|c)&BN_MASK2; - c=(t & BN_TBIT)?1:0; - } - if (c) - ++carry; - } + nist_set_256(c_d,buf, 0, 15, 14, 13, 12, 0, 0, 0); + carry = bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP); + mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask)); + + carry = bn_add_words(t_d, res, res, BN_NIST_256_TOP); + mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask)); + + carry = bn_add_words(r_d, r_d, res, BN_NIST_256_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - ++carry; /*S3*/ nist_set_256(t_d, buf, 15, 14, 0, 0, 0, 10, 9, 8); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S4*/ nist_set_256(t_d, buf, 8, 13, 15, 14, 13, 11, 10, 9); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*D1*/ nist_set_256(t_d, buf, 10, 8, 0, 0, 0, 13, 12, 11); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - --carry; +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP); + bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else + if (bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP)) + bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP); +#endif /*D2*/ nist_set_256(t_d, buf, 11, 9, 0, 0, 15, 14, 13, 12); +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP); + bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - --carry; + bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP); +#endif /*D3*/ nist_set_256(t_d, buf, 12, 0, 10, 9, 8, 15, 14, 13); +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP); + bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - --carry; + bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP); +#endif /*D4*/ nist_set_256(t_d, buf, 13, 0, 11, 10, 9, 0, 15, 14); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP)) - --carry; - - if (carry) - { - if (carry > 0) - bn_sub_words(r_d, r_d, _256_data + BN_NIST_256_TOP * - --carry, BN_NIST_256_TOP); - else - { - carry = -carry; - bn_add_words(r_d, r_d, _256_data + BN_NIST_256_TOP * - --carry, BN_NIST_256_TOP); - } - } +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP); + bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_cp_bn(r_d, res, BN_NIST_384_TOP); +#else + if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP)) + bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP); +#endif r->top = BN_NIST_256_TOP; bn_correct_top(r); - if (BN_ucmp(r, field) >= 0) + + if (BN_ucmp(field, r) <= 0) { - bn_sub_words(r_d, r_d, _nist_p_256, BN_NIST_256_TOP); - bn_correct_top(r); + if (!BN_usub(r, r, field)) return 0; } - bn_check_top(r); + return 1; -#else +#else /* BN_BITS!=32 */ return 0; #endif } -#if BN_BITS2 != 64 -static void _init_384_data(void) - { - int i; - BN_ULONG *tmp1 = _384_data; - const BN_ULONG *tmp2 = tmp1; - - memcpy(tmp1, _nist_p_384, BN_NIST_384_TOP * sizeof(BN_ULONG)); - tmp1 += BN_NIST_384_TOP; - - for (i=0; i<7; i++) - { - bn_add_words(tmp1, _nist_p_384, tmp2, BN_NIST_384_TOP); - tmp2 = tmp1; - tmp1 += BN_NIST_384_TOP; - } - _is_set_384_data = 1; - } -#endif - #define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \ { \ if (a12 != 0) bn_cp_32(to, 0, from, (a12) - 12) else bn_32_set_0(to, 0)\ @@ -598,22 +555,20 @@ static void _init_384_data(void) int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) { -#if BN_BITS2 != 64 +#if BN_BITS2 == 32 int i, top = a->top; int carry = 0; register BN_ULONG *r_d, *a_d = a->d; BN_ULONG t_d[BN_NIST_384_TOP], - buf[BN_NIST_384_TOP]; + buf[BN_NIST_384_TOP], + c_d[BN_NIST_384_TOP], + *res; + size_t mask; - if (!_is_set_384_data) - { - CRYPTO_w_lock(CRYPTO_LOCK_BN); - - if (!_is_set_384_data) - _init_384_data(); + field = &_bignum_nist_p_384; /* just to make sure */ - CRYPTO_w_unlock(CRYPTO_LOCK_BN); - } + if (BN_is_negative(a) || a->top > 2*BN_NIST_384_TOP) + return BN_nnmod(r, field, a, ctx); i = BN_ucmp(field, a); if (i == 0) @@ -624,9 +579,6 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, else if (i > 0) return (r == a)? 1 : (BN_copy(r ,a) != NULL); - if (top == BN_NIST_384_TOP) - return BN_usub(r, a, field); - if (r != a) { if (!bn_wexpand(r, BN_NIST_384_TOP)) @@ -646,72 +598,108 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, register BN_ULONG *ap,t,c; ap = t_d; c=0; - for (i = BN_NIST_256_TOP; i != 0; --i) + for (i = 3; i != 0; --i) { t= *ap; *(ap++)=((t<<1)|c)&BN_MASK2; c=(t & BN_TBIT)?1:0; } + *ap=c; } - if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), - t_d, BN_NIST_256_TOP)) - ++carry; + carry = bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), + t_d, BN_NIST_256_TOP); + /* + * we need if (result>=modulus) subtract(result,modulus); + * in n-bit space this can be expressed as + * if (carry || result>=modulus) subtract(result,modulus); + * the catch is that comparison implies subtraction and + * therefore one can write tmp=subtract(result,modulus); + * and then if(carry || !borrow) result=tmp; this's what + * happens below, but without explicit if:-) a. + */ + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S2 */ - if (bn_add_words(r_d, r_d, buf, BN_NIST_384_TOP)) - ++carry; + carry = bn_add_words(r_d, res, buf, BN_NIST_384_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S3*/ nist_set_384(t_d,buf,20,19,18,17,16,15,14,13,12,23,22,21); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S4*/ nist_set_384(t_d,buf,19,18,17,16,15,14,13,12,20,0,23,0); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S5*/ - nist_set_256(t_d, buf, 0, 0, 0, 0, 23-4, 22-4, 21-4, 20-4); - if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), - t_d, BN_NIST_256_TOP)) - ++carry; + nist_set_384(t_d, buf,0,0,0,0,23,22,21,20,0,0,0,0); + carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*S6*/ nist_set_384(t_d,buf,0,0,0,0,0,0,23,22,21,0,0,20); - if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - ++carry; + carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP); + mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = ~mask | (0-(size_t)carry); + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + /*D1*/ nist_set_384(t_d,buf,22,21,20,19,18,17,16,15,14,13,12,23); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - --carry; +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP); + bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else + if (bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP)) + bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP); +#endif /*D2*/ nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,22,21,20,0); +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP); + bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); +#else if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - --carry; + bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP); +#endif /*D3*/ nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,23,0,0,0); - if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP)) - --carry; - - if (carry) - { - if (carry > 0) - bn_sub_words(r_d, r_d, _384_data + BN_NIST_384_TOP * - --carry, BN_NIST_384_TOP); - else - { - carry = -carry; - bn_add_words(r_d, r_d, _384_data + BN_NIST_384_TOP * - --carry, BN_NIST_384_TOP); - } - } +#if BRANCH_FREE + carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP); + bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP); + mask = 0-(size_t)carry; + res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask)); + nist_cp_bn(r_d, res, BN_NIST_384_TOP); +#else + if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP)) + bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP); +#endif r->top = BN_NIST_384_TOP; bn_correct_top(r); - if (BN_ucmp(r, field) >= 0) + + if (BN_ucmp(field, r) <= 0) { - bn_sub_words(r_d, r_d, _nist_p_384, BN_NIST_384_TOP); - bn_correct_top(r); + if (!BN_usub(r, r, field)) return 0; } - bn_check_top(r); + return 1; -#else +#else /* BN_BITS!=32 */ return 0; #endif } @@ -723,20 +711,37 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, #define BN_NIST_521_TOP_MASK (BN_ULONG)0x1FF #elif BN_BITS2 == 32 #define BN_NIST_521_TOP_MASK (BN_ULONG)0x1FF -#elif BN_BITS2 == 16 -#define BN_NIST_521_TOP_MASK (BN_ULONG)0x1FF -#elif BN_BITS2 == 8 -#define BN_NIST_521_TOP_MASK (BN_ULONG)0x1 #endif int top, ret = 0; - BN_ULONG *r_d; BIGNUM *tmp; + field = &_bignum_nist_p_521; /* just to make sure */ + + if (BN_is_negative(a)) + return BN_nnmod(r, field, a, ctx); + /* check whether a reduction is necessary */ top = a->top; if (top < BN_NIST_521_TOP || ( top == BN_NIST_521_TOP && - (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK))))) - return (r == a)? 1 : (BN_copy(r ,a) != NULL); + (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK))))) + { + int i = BN_ucmp(field, a); + if (i == 0) + { + BN_zero(r); + return 1; + } + else + { +#ifdef BN_DEBUG + OPENSSL_assert(i > 0); /* because 'field' is 1111...1111 */ +#endif + return (r == a)? 1 : (BN_copy(r ,a) != NULL); + } + } + + if (BN_num_bits(a) > 2*521) + return BN_nnmod(r, field, a, ctx); BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); @@ -756,15 +761,11 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, if (!BN_uadd(r, tmp, r)) goto err; - top = r->top; - r_d = r->d; - if (top == BN_NIST_521_TOP && - (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK))) + + if (BN_ucmp(field, r) <= 0) { - BN_NIST_ADD_ONE(r_d) - r_d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; + if (!BN_usub(r, r, field)) goto err; } - bn_correct_top(r); ret = 1; err: diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c index 5bab019553bf..7b25979dd1c4 100644 --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -377,14 +377,14 @@ static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, static int probable_prime(BIGNUM *rnd, int bits) { int i; - BN_ULONG mods[NUMPRIMES]; + prime_t mods[NUMPRIMES]; BN_ULONG delta,maxdelta; again: if (!BN_rand(rnd,bits,1,1)) return(0); /* we now have a random number 'rand' to test. */ for (i=1; i<NUMPRIMES; i++) - mods[i]=BN_mod_word(rnd,(BN_ULONG)primes[i]); + mods[i]=(prime_t)BN_mod_word(rnd,(BN_ULONG)primes[i]); maxdelta=BN_MASK2 - primes[NUMPRIMES-1]; delta=0; loop: for (i=1; i<NUMPRIMES; i++) diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h index b7cf9a9bfe12..51d2194febdb 100644 --- a/crypto/bn/bn_prime.h +++ b/crypto/bn/bn_prime.h @@ -58,10 +58,12 @@ #ifndef EIGHT_BIT #define NUMPRIMES 2048 +typedef unsigned short prime_t; #else #define NUMPRIMES 54 +typedef unsigned char prime_t; #endif -static const unsigned int primes[NUMPRIMES]= +static const prime_t primes[NUMPRIMES]= { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, diff --git a/crypto/bn/bn_prime.pl b/crypto/bn/bn_prime.pl index e583d1d53b9d..3fafb6f3e90a 100644 --- a/crypto/bn/bn_prime.pl +++ b/crypto/bn/bn_prime.pl @@ -101,10 +101,12 @@ for ($i=0; $i <= $#primes; $i++) printf "#ifndef EIGHT_BIT\n"; printf "#define NUMPRIMES %d\n",$num; +printf "typedef unsigned short prime_t;\n"; printf "#else\n"; printf "#define NUMPRIMES %d\n",$eight; +printf "typedef unsigned char prime_t;\n"; printf "#endif\n"; -print "static const unsigned int primes[NUMPRIMES]=\n\t{\n\t"; +print "static const prime_t primes[NUMPRIMES]=\n\t{\n\t"; $init=0; for ($i=0; $i <= $#primes; $i++) { diff --git a/crypto/bn/bntest.c b/crypto/bn/bntest.c index c885300a669f..310763eca0c6 100644 --- a/crypto/bn/bntest.c +++ b/crypto/bn/bntest.c @@ -184,120 +184,120 @@ int main(int argc, char *argv[]) message(out,"BN_add"); if (!test_add(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_sub"); if (!test_sub(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_lshift1"); if (!test_lshift1(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_lshift (fixed)"); if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL))) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_lshift"); if (!test_lshift(out,ctx,NULL)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_rshift1"); if (!test_rshift1(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_rshift"); if (!test_rshift(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_sqr"); if (!test_sqr(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mul"); if (!test_mul(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_div"); if (!test_div(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_div_word"); if (!test_div_word(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_div_recp"); if (!test_div_recp(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mod"); if (!test_mod(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mod_mul"); if (!test_mod_mul(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mont"); if (!test_mont(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mod_exp"); if (!test_mod_exp(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mod_exp_mont_consttime"); if (!test_mod_exp_mont_consttime(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_exp"); if (!test_exp(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_kronecker"); if (!test_kron(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_mod_sqrt"); if (!test_sqrt(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_add"); if (!test_gf2m_add(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod"); if (!test_gf2m_mod(out)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_mul"); if (!test_gf2m_mod_mul(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_sqr"); if (!test_gf2m_mod_sqr(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_inv"); if (!test_gf2m_mod_inv(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_div"); if (!test_gf2m_mod_div(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_exp"); if (!test_gf2m_mod_exp(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_sqrt"); if (!test_gf2m_mod_sqrt(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); message(out,"BN_GF2m_mod_solve_quad"); if (!test_gf2m_mod_solve_quad(out,ctx)) goto err; - BIO_flush(out); + (void)BIO_flush(out); BN_CTX_free(ctx); BIO_free(out); @@ -307,7 +307,7 @@ int main(int argc, char *argv[]) err: BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices * the failure, see test_bn in test/Makefile.ssl*/ - BIO_flush(out); + (void)BIO_flush(out); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); EXIT(1); diff --git a/crypto/cms/Makefile b/crypto/cms/Makefile new file mode 100644 index 000000000000..e39c310b6c6c --- /dev/null +++ b/crypto/cms/Makefile @@ -0,0 +1,183 @@ +# +# OpenSSL/crypto/cms/Makefile +# + +DIR= cms +TOP= ../.. +CC= cc +INCLUDES= -I.. -I$(TOP) -I../../include +CFLAG=-g +MAKEFILE= Makefile +AR= ar r + +CFLAGS= $(INCLUDES) $(CFLAG) + +GENERAL=Makefile +TEST= +APPS= + +LIB=$(TOP)/libcrypto.a +LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \ + cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c +LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \ + cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o + +SRC= $(LIBSRC) + +EXHEADER= cms.h +HEADER= cms_lcl.h $(EXHEADER) + +ALL= $(GENERAL) $(SRC) $(HEADER) + +top: + (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all) + +test: + +all: lib + +lib: $(LIBOBJ) + $(AR) $(LIB) $(LIBOBJ) + $(RANLIB) $(LIB) || echo Never mind. + @touch lib + +files: + $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO + +links: + @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER) + @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST) + @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS) + +install: + @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile... + @headerlist="$(EXHEADER)"; for i in $$headerlist ; \ + do \ + (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \ + chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \ + done; + +tags: + ctags $(SRC) + +tests: + +lint: + lint -DLINT $(INCLUDES) $(SRC)>fluff + +depend: + @[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile... + $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC) + +dclean: + $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new + mv -f Makefile.new $(MAKEFILE) + +clean: + rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +cms_asn1.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +cms_asn1.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +cms_asn1.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +cms_asn1.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +cms_asn1.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +cms_asn1.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +cms_asn1.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +cms_asn1.o: ../../include/openssl/opensslconf.h +cms_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +cms_asn1.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +cms_asn1.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h +cms_asn1.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +cms_asn1.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +cms_asn1.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h +cms_asn1.o: cms.h cms_asn1.c cms_lcl.h +cms_att.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +cms_att.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +cms_att.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +cms_att.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +cms_att.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +cms_att.o: ../../include/openssl/err.h ../../include/openssl/evp.h +cms_att.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +cms_att.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +cms_att.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +cms_att.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +cms_att.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h +cms_att.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +cms_att.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +cms_att.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h +cms_att.o: cms.h cms_att.c cms_lcl.h +cms_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +cms_err.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h +cms_err.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +cms_err.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +cms_err.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h +cms_err.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +cms_err.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +cms_err.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +cms_err.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +cms_err.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +cms_err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +cms_err.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +cms_err.o: cms_err.c +cms_io.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +cms_io.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +cms_io.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +cms_io.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +cms_io.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h +cms_io.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +cms_io.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +cms_io.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +cms_io.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +cms_io.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +cms_io.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +cms_io.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +cms_io.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h cms.h +cms_io.o: cms_io.c cms_lcl.h +cms_lib.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +cms_lib.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +cms_lib.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +cms_lib.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +cms_lib.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h +cms_lib.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +cms_lib.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +cms_lib.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +cms_lib.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +cms_lib.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +cms_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +cms_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +cms_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h cms.h +cms_lib.o: cms_lcl.h cms_lib.c +cms_sd.o: ../../e_os.h ../../include/openssl/asn1.h +cms_sd.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h +cms_sd.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h +cms_sd.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +cms_sd.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +cms_sd.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +cms_sd.o: ../../include/openssl/err.h ../../include/openssl/evp.h +cms_sd.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +cms_sd.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +cms_sd.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +cms_sd.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +cms_sd.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h +cms_sd.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +cms_sd.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +cms_sd.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h +cms_sd.o: ../cryptlib.h cms_lcl.h cms_sd.c +cms_smime.o: ../../e_os.h ../../include/openssl/asn1.h +cms_smime.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h +cms_smime.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h +cms_smime.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +cms_smime.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +cms_smime.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +cms_smime.o: ../../include/openssl/err.h ../../include/openssl/evp.h +cms_smime.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +cms_smime.o: ../../include/openssl/objects.h +cms_smime.o: ../../include/openssl/opensslconf.h +cms_smime.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +cms_smime.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h +cms_smime.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +cms_smime.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +cms_smime.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h +cms_smime.o: ../cryptlib.h cms_lcl.h cms_smime.c diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h new file mode 100644 index 000000000000..25f88745f23e --- /dev/null +++ b/crypto/cms/cms.h @@ -0,0 +1,473 @@ +/* crypto/cms/cms.h */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + + +#ifndef HEADER_CMS_H +#define HEADER_CMS_H + +#include <openssl/x509.h> + +#ifdef OPENSSL_NO_CMS +#error CMS is disabled. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct CMS_ContentInfo_st CMS_ContentInfo; +typedef struct CMS_SignerInfo_st CMS_SignerInfo; +typedef struct CMS_CertificateChoices CMS_CertificateChoices; +typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; +typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest; +typedef struct CMS_Receipt_st CMS_Receipt; + +DECLARE_STACK_OF(CMS_SignerInfo) +DECLARE_STACK_OF(GENERAL_NAMES) +DECLARE_ASN1_FUNCTIONS_const(CMS_ContentInfo) +DECLARE_ASN1_FUNCTIONS_const(CMS_ReceiptRequest) + +#define CMS_SIGNERINFO_ISSUER_SERIAL 0 +#define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +#define CMS_RECIPINFO_TRANS 0 +#define CMS_RECIPINFO_AGREE 1 +#define CMS_RECIPINFO_KEK 2 +#define CMS_RECIPINFO_PASS 3 +#define CMS_RECIPINFO_OTHER 4 + +/* S/MIME related flags */ + +#define CMS_TEXT 0x1 +#define CMS_NOCERTS 0x2 +#define CMS_NO_CONTENT_VERIFY 0x4 +#define CMS_NO_ATTR_VERIFY 0x8 +#define CMS_NOSIGS \ + (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY) +#define CMS_NOINTERN 0x10 +#define CMS_NO_SIGNER_CERT_VERIFY 0x20 +#define CMS_NOVERIFY 0x20 +#define CMS_DETACHED 0x40 +#define CMS_BINARY 0x80 +#define CMS_NOATTR 0x100 +#define CMS_NOSMIMECAP 0x200 +#define CMS_NOOLDMIMETYPE 0x400 +#define CMS_CRLFEOL 0x800 +#define CMS_STREAM 0x1000 +#define CMS_NOCRL 0x2000 +#define CMS_PARTIAL 0x4000 +#define CMS_REUSE_DIGEST 0x8000 +#define CMS_USE_KEYID 0x10000 + +const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms); + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +int CMS_is_detached(CMS_ContentInfo *cms); +int CMS_set_detached(CMS_ContentInfo *cms, int detached); + +#ifdef HEADER_PEM_H +DECLARE_PEM_rw_const(CMS, CMS_ContentInfo) +#endif + +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms); +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms); + +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont); +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags); + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags); + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, unsigned int flags); + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, + unsigned int flags); + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags); + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags); + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + unsigned int flags); + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags); + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags); + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, unsigned int flags); + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *dcont, BIO *out, + unsigned int flags); + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen); + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType); + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype); + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen); + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid); +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms); + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms); +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert); +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert); +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms); + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms); +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl); +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms); + +int CMS_SignedData_init(CMS_ContentInfo *cms); +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags); +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert); +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + unsigned int flags); +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer, + X509_ALGOR **pdig, X509_ALGOR **psig); +int CMS_SignerInfo_sign(CMS_SignerInfo *si); +int CMS_SignerInfo_verify(CMS_SignerInfo *si); +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain); + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs); +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize); +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap); + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si); +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si); +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +#ifdef HEADER_X509V3_H + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr); +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) *receiptList, + STACK_OF(GENERAL_NAMES) *receiptsTo); +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr); +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto); + +#endif + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_CMS_strings(void); + +/* Error codes for the CMS functions. */ + +/* Function codes. */ +#define CMS_F_CHECK_CONTENT 99 +#define CMS_F_CMS_ADD0_CERT 164 +#define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 +#define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 +#define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 +#define CMS_F_CMS_ADD1_SIGNER 102 +#define CMS_F_CMS_ADD1_SIGNINGTIME 103 +#define CMS_F_CMS_COMPRESS 104 +#define CMS_F_CMS_COMPRESSEDDATA_CREATE 105 +#define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106 +#define CMS_F_CMS_COPY_CONTENT 107 +#define CMS_F_CMS_COPY_MESSAGEDIGEST 108 +#define CMS_F_CMS_DATA 109 +#define CMS_F_CMS_DATAFINAL 110 +#define CMS_F_CMS_DATAINIT 111 +#define CMS_F_CMS_DECRYPT 112 +#define CMS_F_CMS_DECRYPT_SET1_KEY 113 +#define CMS_F_CMS_DECRYPT_SET1_PKEY 114 +#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 +#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 +#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +#define CMS_F_CMS_DIGEST_VERIFY 118 +#define CMS_F_CMS_ENCODE_RECEIPT 161 +#define CMS_F_CMS_ENCRYPT 119 +#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 +#define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 +#define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 +#define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 +#define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 +#define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 +#define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +#define CMS_F_CMS_FINAL 127 +#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 +#define CMS_F_CMS_GET0_CONTENT 129 +#define CMS_F_CMS_GET0_ECONTENT_TYPE 130 +#define CMS_F_CMS_GET0_ENVELOPED 131 +#define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 +#define CMS_F_CMS_GET0_SIGNED 133 +#define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 +#define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 +#define CMS_F_CMS_RECEIPT_VERIFY 160 +#define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143 +#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 +#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +#define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 +#define CMS_F_CMS_SET_DETACHED 147 +#define CMS_F_CMS_SIGN 148 +#define CMS_F_CMS_SIGNED_DATA_INIT 149 +#define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150 +#define CMS_F_CMS_SIGNERINFO_SIGN 151 +#define CMS_F_CMS_SIGNERINFO_VERIFY 152 +#define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 +#define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +#define CMS_F_CMS_SIGN_RECEIPT 163 +#define CMS_F_CMS_STREAM 155 +#define CMS_F_CMS_UNCOMPRESS 156 +#define CMS_F_CMS_VERIFY 157 + +/* Reason codes. */ +#define CMS_R_ADD_SIGNER_ERROR 99 +#define CMS_R_CERTIFICATE_ALREADY_PRESENT 175 +#define CMS_R_CERTIFICATE_HAS_NO_KEYID 160 +#define CMS_R_CERTIFICATE_VERIFY_ERROR 100 +#define CMS_R_CIPHER_INITIALISATION_ERROR 101 +#define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102 +#define CMS_R_CMS_DATAFINAL_ERROR 103 +#define CMS_R_CMS_LIB 104 +#define CMS_R_CONTENTIDENTIFIER_MISMATCH 170 +#define CMS_R_CONTENT_NOT_FOUND 105 +#define CMS_R_CONTENT_TYPE_MISMATCH 171 +#define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106 +#define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107 +#define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108 +#define CMS_R_CONTENT_VERIFY_ERROR 109 +#define CMS_R_CTRL_ERROR 110 +#define CMS_R_CTRL_FAILURE 111 +#define CMS_R_DECRYPT_ERROR 112 +#define CMS_R_DIGEST_ERROR 161 +#define CMS_R_ERROR_GETTING_PUBLIC_KEY 113 +#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114 +#define CMS_R_ERROR_SETTING_KEY 115 +#define CMS_R_ERROR_SETTING_RECIPIENTINFO 116 +#define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117 +#define CMS_R_INVALID_KEY_LENGTH 118 +#define CMS_R_MD_BIO_INIT_ERROR 119 +#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120 +#define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121 +#define CMS_R_MSGSIGDIGEST_ERROR 172 +#define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162 +#define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163 +#define CMS_R_NEED_ONE_SIGNER 164 +#define CMS_R_NOT_A_SIGNED_RECEIPT 165 +#define CMS_R_NOT_ENCRYPTED_DATA 122 +#define CMS_R_NOT_KEK 123 +#define CMS_R_NOT_KEY_TRANSPORT 124 +#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125 +#define CMS_R_NO_CIPHER 126 +#define CMS_R_NO_CONTENT 127 +#define CMS_R_NO_CONTENT_TYPE 173 +#define CMS_R_NO_DEFAULT_DIGEST 128 +#define CMS_R_NO_DIGEST_SET 129 +#define CMS_R_NO_KEY 130 +#define CMS_R_NO_KEY_OR_CERT 174 +#define CMS_R_NO_MATCHING_DIGEST 131 +#define CMS_R_NO_MATCHING_RECIPIENT 132 +#define CMS_R_NO_MATCHING_SIGNATURE 166 +#define CMS_R_NO_MSGSIGDIGEST 167 +#define CMS_R_NO_PRIVATE_KEY 133 +#define CMS_R_NO_PUBLIC_KEY 134 +#define CMS_R_NO_RECEIPT_REQUEST 168 +#define CMS_R_NO_SIGNERS 135 +#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136 +#define CMS_R_RECEIPT_DECODE_ERROR 169 +#define CMS_R_RECIPIENT_ERROR 137 +#define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138 +#define CMS_R_SIGNFINAL_ERROR 139 +#define CMS_R_SMIME_TEXT_ERROR 140 +#define CMS_R_STORE_INIT_ERROR 141 +#define CMS_R_TYPE_NOT_COMPRESSED_DATA 142 +#define CMS_R_TYPE_NOT_DATA 143 +#define CMS_R_TYPE_NOT_DIGESTED_DATA 144 +#define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145 +#define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 +#define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147 +#define CMS_R_UNKNOWN_CIPHER 148 +#define CMS_R_UNKNOWN_DIGEST_ALGORIHM 149 +#define CMS_R_UNKNOWN_ID 150 +#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151 +#define CMS_R_UNSUPPORTED_CONTENT_TYPE 152 +#define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 +#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154 +#define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE 155 +#define CMS_R_UNSUPPORTED_TYPE 156 +#define CMS_R_UNWRAP_ERROR 157 +#define CMS_R_VERIFICATION_FAILURE 158 +#define CMS_R_WRAP_ERROR 159 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c new file mode 100644 index 000000000000..766492186183 --- /dev/null +++ b/crypto/cms/cms_asn1.c @@ -0,0 +1,346 @@ +/* crypto/cms/cms_asn1.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include "cms.h" +#include "cms_lcl.h" + + +ASN1_SEQUENCE(CMS_IssuerAndSerialNumber) = { + ASN1_SIMPLE(CMS_IssuerAndSerialNumber, issuer, X509_NAME), + ASN1_SIMPLE(CMS_IssuerAndSerialNumber, serialNumber, ASN1_INTEGER) +} ASN1_SEQUENCE_END(CMS_IssuerAndSerialNumber) + +ASN1_SEQUENCE(CMS_OtherCertificateFormat) = { + ASN1_SIMPLE(CMS_OtherCertificateFormat, otherCertFormat, ASN1_OBJECT), + ASN1_OPT(CMS_OtherCertificateFormat, otherCert, ASN1_ANY) +} ASN1_SEQUENCE_END(CMS_OtherCertificateFormat) + +ASN1_CHOICE(CMS_CertificateChoices) = { + ASN1_SIMPLE(CMS_CertificateChoices, d.certificate, X509), + ASN1_IMP(CMS_CertificateChoices, d.extendedCertificate, ASN1_SEQUENCE, 0), + ASN1_IMP(CMS_CertificateChoices, d.v1AttrCert, ASN1_SEQUENCE, 1), + ASN1_IMP(CMS_CertificateChoices, d.v2AttrCert, ASN1_SEQUENCE, 2), + ASN1_IMP(CMS_CertificateChoices, d.other, CMS_OtherCertificateFormat, 3) +} ASN1_CHOICE_END(CMS_CertificateChoices) + +ASN1_CHOICE(CMS_SignerIdentifier) = { + ASN1_SIMPLE(CMS_SignerIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_SignerIdentifier, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0) +} ASN1_CHOICE_END(CMS_SignerIdentifier) + +ASN1_NDEF_SEQUENCE(CMS_EncapsulatedContentInfo) = { + ASN1_SIMPLE(CMS_EncapsulatedContentInfo, eContentType, ASN1_OBJECT), + ASN1_NDEF_EXP_OPT(CMS_EncapsulatedContentInfo, eContent, ASN1_OCTET_STRING_NDEF, 0) +} ASN1_NDEF_SEQUENCE_END(CMS_EncapsulatedContentInfo) + +/* Minor tweak to operation: free up signer key, cert */ +static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) + { + if(operation == ASN1_OP_FREE_POST) + { + CMS_SignerInfo *si = (CMS_SignerInfo *)*pval; + if (si->pkey) + EVP_PKEY_free(si->pkey); + if (si->signer) + X509_free(si->signer); + } + return 1; + } + +ASN1_SEQUENCE_cb(CMS_SignerInfo, cms_si_cb) = { + ASN1_SIMPLE(CMS_SignerInfo, version, LONG), + ASN1_SIMPLE(CMS_SignerInfo, sid, CMS_SignerIdentifier), + ASN1_SIMPLE(CMS_SignerInfo, digestAlgorithm, X509_ALGOR), + ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, signedAttrs, X509_ATTRIBUTE, 0), + ASN1_SIMPLE(CMS_SignerInfo, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_SignerInfo, signature, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, unsignedAttrs, X509_ATTRIBUTE, 1) +} ASN1_SEQUENCE_END_cb(CMS_SignerInfo, CMS_SignerInfo) + +ASN1_SEQUENCE(CMS_OtherRevocationInfoFormat) = { + ASN1_SIMPLE(CMS_OtherRevocationInfoFormat, otherRevInfoFormat, ASN1_OBJECT), + ASN1_OPT(CMS_OtherRevocationInfoFormat, otherRevInfo, ASN1_ANY) +} ASN1_SEQUENCE_END(CMS_OtherRevocationInfoFormat) + +ASN1_CHOICE(CMS_RevocationInfoChoice) = { + ASN1_SIMPLE(CMS_RevocationInfoChoice, d.crl, X509_CRL), + ASN1_IMP(CMS_RevocationInfoChoice, d.other, CMS_OtherRevocationInfoFormat, 1) +} ASN1_CHOICE_END(CMS_RevocationInfoChoice) + +ASN1_NDEF_SEQUENCE(CMS_SignedData) = { + ASN1_SIMPLE(CMS_SignedData, version, LONG), + ASN1_SET_OF(CMS_SignedData, digestAlgorithms, X509_ALGOR), + ASN1_SIMPLE(CMS_SignedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0), + ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1), + ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo) +} ASN1_NDEF_SEQUENCE_END(CMS_SignedData) + +ASN1_SEQUENCE(CMS_OriginatorInfo) = { + ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0), + ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1) +} ASN1_SEQUENCE_END(CMS_OriginatorInfo) + +ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = { + ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT), + ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR), + ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0) +} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo) + +ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = { + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, version, LONG), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, rid, CMS_SignerIdentifier), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_KeyTransRecipientInfo) + +ASN1_SEQUENCE(CMS_OtherKeyAttribute) = { + ASN1_SIMPLE(CMS_OtherKeyAttribute, keyAttrId, ASN1_OBJECT), + ASN1_OPT(CMS_OtherKeyAttribute, keyAttr, ASN1_ANY) +} ASN1_SEQUENCE_END(CMS_OtherKeyAttribute) + +ASN1_SEQUENCE(CMS_RecipientKeyIdentifier) = { + ASN1_SIMPLE(CMS_RecipientKeyIdentifier, subjectKeyIdentifier, ASN1_OCTET_STRING), + ASN1_OPT(CMS_RecipientKeyIdentifier, date, ASN1_GENERALIZEDTIME), + ASN1_OPT(CMS_RecipientKeyIdentifier, other, CMS_OtherKeyAttribute) +} ASN1_SEQUENCE_END(CMS_RecipientKeyIdentifier) + +ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = { + ASN1_SIMPLE(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0) +} ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier) + +ASN1_SEQUENCE(CMS_RecipientEncryptedKey) = { + ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier), + ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_RecipientEncryptedKey) + +ASN1_SEQUENCE(CMS_OriginatorPublicKey) = { + ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_OriginatorPublicKey, publicKey, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(CMS_OriginatorPublicKey) + +ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = { + ASN1_SIMPLE(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0), + ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1) +} ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey) + +ASN1_SEQUENCE(CMS_KeyAgreeRecipientInfo) = { + ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, version, LONG), + ASN1_EXP(CMS_KeyAgreeRecipientInfo, originator, CMS_OriginatorIdentifierOrKey, 0), + ASN1_EXP_OPT(CMS_KeyAgreeRecipientInfo, ukm, ASN1_OCTET_STRING, 1), + ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SEQUENCE_OF(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys, CMS_RecipientEncryptedKey) +} ASN1_SEQUENCE_END(CMS_KeyAgreeRecipientInfo) + +ASN1_SEQUENCE(CMS_KEKIdentifier) = { + ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING), + ASN1_OPT(CMS_KEKIdentifier, date, ASN1_GENERALIZEDTIME), + ASN1_OPT(CMS_KEKIdentifier, other, CMS_OtherKeyAttribute) +} ASN1_SEQUENCE_END(CMS_KEKIdentifier) + +ASN1_SEQUENCE(CMS_KEKRecipientInfo) = { + ASN1_SIMPLE(CMS_KEKRecipientInfo, version, LONG), + ASN1_SIMPLE(CMS_KEKRecipientInfo, kekid, CMS_KEKIdentifier), + ASN1_SIMPLE(CMS_KEKRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_KEKRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_KEKRecipientInfo) + +ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = { + ASN1_SIMPLE(CMS_PasswordRecipientInfo, version, LONG), + ASN1_IMP_OPT(CMS_PasswordRecipientInfo, keyDerivationAlgorithm, X509_ALGOR, 0), + ASN1_SIMPLE(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo) + +ASN1_SEQUENCE(CMS_OtherRecipientInfo) = { + ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT), + ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY) +} ASN1_SEQUENCE_END(CMS_OtherRecipientInfo) + +/* Free up RecipientInfo additional data */ +static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) + { + if(operation == ASN1_OP_FREE_PRE) + { + CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval; + if (ri->type == CMS_RECIPINFO_TRANS) + { + CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; + if (ktri->pkey) + EVP_PKEY_free(ktri->pkey); + if (ktri->recip) + X509_free(ktri->recip); + } + else if (ri->type == CMS_RECIPINFO_KEK) + { + CMS_KEKRecipientInfo *kekri = ri->d.kekri; + if (kekri->key) + { + OPENSSL_cleanse(kekri->key, kekri->keylen); + OPENSSL_free(kekri->key); + } + } + } + return 1; + } + +ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = { + ASN1_SIMPLE(CMS_RecipientInfo, d.ktri, CMS_KeyTransRecipientInfo), + ASN1_IMP(CMS_RecipientInfo, d.kari, CMS_KeyAgreeRecipientInfo, 1), + ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2), + ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3), + ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4) +} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type) + +ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = { + ASN1_SIMPLE(CMS_EnvelopedData, version, LONG), + ASN1_IMP_OPT(CMS_EnvelopedData, originatorInfo, CMS_OriginatorInfo, 0), + ASN1_SET_OF(CMS_EnvelopedData, recipientInfos, CMS_RecipientInfo), + ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1) +} ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData) + +ASN1_NDEF_SEQUENCE(CMS_DigestedData) = { + ASN1_SIMPLE(CMS_DigestedData, version, LONG), + ASN1_SIMPLE(CMS_DigestedData, digestAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_DigestedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_SIMPLE(CMS_DigestedData, digest, ASN1_OCTET_STRING) +} ASN1_NDEF_SEQUENCE_END(CMS_DigestedData) + +ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = { + ASN1_SIMPLE(CMS_EncryptedData, version, LONG), + ASN1_SIMPLE(CMS_EncryptedData, encryptedContentInfo, CMS_EncryptedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1) +} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData) + +ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = { + ASN1_SIMPLE(CMS_AuthenticatedData, version, LONG), + ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0), + ASN1_SET_OF(CMS_AuthenticatedData, recipientInfos, CMS_RecipientInfo), + ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR), + ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1), + ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2), + ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3) +} ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData) + +ASN1_NDEF_SEQUENCE(CMS_CompressedData) = { + ASN1_SIMPLE(CMS_CompressedData, version, LONG), + ASN1_SIMPLE(CMS_CompressedData, compressionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_CompressedData, encapContentInfo, CMS_EncapsulatedContentInfo), +} ASN1_NDEF_SEQUENCE_END(CMS_CompressedData) + +/* This is the ANY DEFINED BY table for the top level ContentInfo structure */ + +ASN1_ADB_TEMPLATE(cms_default) = ASN1_EXP(CMS_ContentInfo, d.other, ASN1_ANY, 0); + +ASN1_ADB(CMS_ContentInfo) = { + ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP(CMS_ContentInfo, d.data, ASN1_OCTET_STRING_NDEF, 0)), + ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP(CMS_ContentInfo, d.signedData, CMS_SignedData, 0)), + ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)), + ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)), + ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)), + ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)), + ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)), +} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL); + +ASN1_NDEF_SEQUENCE(CMS_ContentInfo) = { + ASN1_SIMPLE(CMS_ContentInfo, contentType, ASN1_OBJECT), + ASN1_ADB_OBJECT(CMS_ContentInfo) +} ASN1_NDEF_SEQUENCE_END(CMS_ContentInfo) + +/* Specials for signed attributes */ + +/* When signing attributes we want to reorder them to match the sorted + * encoding. + */ + +ASN1_ITEM_TEMPLATE(CMS_Attributes_Sign) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, CMS_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Sign) + +/* When verifying attributes we need to use the received order. So + * we use SEQUENCE OF and tag it to SET OF + */ + +ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, + V_ASN1_SET, CMS_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify) + + + +ASN1_CHOICE(CMS_ReceiptsFrom) = { + ASN1_IMP(CMS_ReceiptsFrom, d.allOrFirstTier, LONG, 0), + ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1) +} ASN1_CHOICE_END(CMS_ReceiptsFrom) + +ASN1_SEQUENCE(CMS_ReceiptRequest) = { + ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING), + ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom), + ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES) +} ASN1_SEQUENCE_END(CMS_ReceiptRequest) + +ASN1_SEQUENCE(CMS_Receipt) = { + ASN1_SIMPLE(CMS_Receipt, version, LONG), + ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT), + ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING), + ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_Receipt) + diff --git a/crypto/cms/cms_att.c b/crypto/cms/cms_att.c new file mode 100644 index 000000000000..5b71722ebc80 --- /dev/null +++ b/crypto/cms/cms_att.c @@ -0,0 +1,195 @@ +/* crypto/cms/cms_att.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include "cms.h" +#include "cms_lcl.h" + +/* CMS SignedData Attribute utilities */ + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si) +{ + return X509at_get_attr_count(si->signedAttrs); +} + +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos) +{ + return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos); +} + +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos); +} + +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc) +{ + return X509at_get_attr(si->signedAttrs, loc); +} + +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc) +{ + return X509at_delete_attr(si->signedAttrs, loc); +} + +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) +{ + if(X509at_add1_attr(&si->signedAttrs, attr)) return 1; + return 0; +} + +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_OBJ(&si->signedAttrs, obj, + type, bytes, len)) return 1; + return 0; +} + +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_NID(&si->signedAttrs, nid, + type, bytes, len)) return 1; + return 0; +} + +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_txt(&si->signedAttrs, attrname, + type, bytes, len)) return 1; + return 0; +} + +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type) +{ + return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type); +} + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si) +{ + return X509at_get_attr_count(si->unsignedAttrs); +} + +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos) +{ + return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos); +} + +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos); +} + +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc) +{ + return X509at_get_attr(si->unsignedAttrs, loc); +} + +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc) +{ + return X509at_delete_attr(si->unsignedAttrs, loc); +} + +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) +{ + if(X509at_add1_attr(&si->unsignedAttrs, attr)) return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, + type, bytes, len)) return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_NID(&si->unsignedAttrs, nid, + type, bytes, len)) return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len) +{ + if(X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname, + type, bytes, len)) return 1; + return 0; +} + +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type) +{ + return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type); +} + +/* Specific attribute cases */ diff --git a/crypto/cms/cms_cd.c b/crypto/cms/cms_cd.c new file mode 100644 index 000000000000..a5fc2c4e2b42 --- /dev/null +++ b/crypto/cms/cms_cd.c @@ -0,0 +1,134 @@ +/* crypto/cms/cms_cd.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include <openssl/bio.h> +#include <openssl/comp.h> +#include "cms_lcl.h" + +DECLARE_ASN1_ITEM(CMS_CompressedData) + +#ifdef ZLIB + +/* CMS CompressedData Utilities */ + +CMS_ContentInfo *cms_CompressedData_create(int comp_nid) + { + CMS_ContentInfo *cms; + CMS_CompressedData *cd; + /* Will need something cleverer if there is ever more than one + * compression algorithm or parameters have some meaning... + */ + if (comp_nid != NID_zlib_compression) + { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE, + CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; + } + cms = CMS_ContentInfo_new(); + if (!cms) + return NULL; + + cd = M_ASN1_new_of(CMS_CompressedData); + + if (!cd) + goto err; + + cms->contentType = OBJ_nid2obj(NID_id_smime_ct_compressedData); + cms->d.compressedData = cd; + + cd->version = 0; + + X509_ALGOR_set0(cd->compressionAlgorithm, + OBJ_nid2obj(NID_zlib_compression), + V_ASN1_UNDEF, NULL); + + cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); + + return cms; + + err: + + if (cms) + CMS_ContentInfo_free(cms); + + return NULL; + } + +BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms) + { + CMS_CompressedData *cd; + ASN1_OBJECT *compoid; + if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) + { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, + CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA); + return NULL; + } + cd = cms->d.compressedData; + X509_ALGOR_get0(&compoid, NULL, NULL, cd->compressionAlgorithm); + if (OBJ_obj2nid(compoid) != NID_zlib_compression) + { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, + CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; + } + return BIO_new(BIO_f_zlib()); + } + +#endif diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c new file mode 100644 index 000000000000..8919c15be126 --- /dev/null +++ b/crypto/cms/cms_dd.c @@ -0,0 +1,148 @@ +/* crypto/cms/cms_dd.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include "cms_lcl.h" + +DECLARE_ASN1_ITEM(CMS_DigestedData) + +/* CMS DigestedData Utilities */ + +CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md) + { + CMS_ContentInfo *cms; + CMS_DigestedData *dd; + cms = CMS_ContentInfo_new(); + if (!cms) + return NULL; + + dd = M_ASN1_new_of(CMS_DigestedData); + + if (!dd) + goto err; + + cms->contentType = OBJ_nid2obj(NID_pkcs7_digest); + cms->d.digestedData = dd; + + dd->version = 0; + dd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); + + cms_DigestAlgorithm_set(dd->digestAlgorithm, md); + + return cms; + + err: + + if (cms) + CMS_ContentInfo_free(cms); + + return NULL; + } + +BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms) + { + CMS_DigestedData *dd; + dd = cms->d.digestedData; + return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm); + } + +int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify) + { + EVP_MD_CTX mctx; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + int r = 0; + CMS_DigestedData *dd; + EVP_MD_CTX_init(&mctx); + + dd = cms->d.digestedData; + + if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, dd->digestAlgorithm)) + goto err; + + if (EVP_DigestFinal_ex(&mctx, md, &mdlen) <= 0) + goto err; + + if (verify) + { + if (mdlen != (unsigned int)dd->digest->length) + { + CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, + CMS_R_MESSAGEDIGEST_WRONG_LENGTH); + goto err; + } + + if (memcmp(md, dd->digest->data, mdlen)) + CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, + CMS_R_VERIFICATION_FAILURE); + else + r = 1; + } + else + { + if (!ASN1_STRING_set(dd->digest, md, mdlen)) + goto err; + r = 1; + } + + err: + EVP_MD_CTX_cleanup(&mctx); + + return r; + + } diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c new file mode 100644 index 000000000000..bab26235bdc4 --- /dev/null +++ b/crypto/cms/cms_enc.c @@ -0,0 +1,262 @@ +/* crypto/cms/cms_enc.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include <openssl/rand.h> +#include "cms_lcl.h" + +/* CMS EncryptedData Utilities */ + +DECLARE_ASN1_ITEM(CMS_EncryptedData) + +/* Return BIO based on EncryptedContentInfo and key */ + +BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) + { + BIO *b; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *ciph; + X509_ALGOR *calg = ec->contentEncryptionAlgorithm; + unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; + + int ok = 0; + + int enc, keep_key = 0; + + enc = ec->cipher ? 1 : 0; + + b = BIO_new(BIO_f_cipher()); + if (!b) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + BIO_get_cipher_ctx(b, &ctx); + + if (enc) + { + ciph = ec->cipher; + /* If not keeping key set cipher to NULL so subsequent calls + * decrypt. + */ + if (ec->key) + ec->cipher = NULL; + } + else + { + ciph = EVP_get_cipherbyobj(calg->algorithm); + + if (!ciph) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_UNKNOWN_CIPHER); + goto err; + } + } + + if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_INITIALISATION_ERROR); + goto err; + } + + if (enc) + { + int ivlen; + calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); + /* Generate a random IV if we need one */ + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivlen > 0) + { + if (RAND_pseudo_bytes(iv, ivlen) <= 0) + goto err; + piv = iv; + } + } + else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + + + if (enc && !ec->key) + { + /* Generate random key */ + if (!ec->keylen) + ec->keylen = EVP_CIPHER_CTX_key_length(ctx); + ec->key = OPENSSL_malloc(ec->keylen); + if (!ec->key) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_CIPHER_CTX_rand_key(ctx, ec->key) <= 0) + goto err; + keep_key = 1; + } + else if (ec->keylen != (unsigned int)EVP_CIPHER_CTX_key_length(ctx)) + { + /* If necessary set key length */ + if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_INVALID_KEY_LENGTH); + goto err; + } + } + + if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_INITIALISATION_ERROR); + goto err; + } + + if (piv) + { + calg->parameter = ASN1_TYPE_new(); + if (!calg->parameter) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + } + ok = 1; + + err: + if (ec->key && !keep_key) + { + OPENSSL_cleanse(ec->key, ec->keylen); + OPENSSL_free(ec->key); + ec->key = NULL; + } + if (ok) + return b; + BIO_free(b); + return NULL; + } + +int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen) + { + ec->cipher = cipher; + if (key) + { + ec->key = OPENSSL_malloc(keylen); + if (!ec->key) + return 0; + memcpy(ec->key, key, keylen); + } + ec->keylen = keylen; + if (cipher) + ec->contentType = OBJ_nid2obj(NID_pkcs7_data); + return 1; + } + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen) + { + CMS_EncryptedContentInfo *ec; + if (!key || !keylen) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY); + return 0; + } + if (ciph) + { + cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); + if (!cms->d.encryptedData) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, + ERR_R_MALLOC_FAILURE); + return 0; + } + cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); + cms->d.encryptedData->version = 0; + } + else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, + CMS_R_NOT_ENCRYPTED_DATA); + return 0; + } + ec = cms->d.encryptedData->encryptedContentInfo; + return cms_EncryptedContent_init(ec, ciph, key, keylen); + } + +BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms) + { + CMS_EncryptedData *enc = cms->d.encryptedData; + if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs) + enc->version = 2; + return cms_EncryptedContent_init_bio(enc->encryptedContentInfo); + } diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c new file mode 100644 index 000000000000..d499ae85b400 --- /dev/null +++ b/crypto/cms/cms_env.c @@ -0,0 +1,825 @@ +/* crypto/cms/cms_env.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include <openssl/rand.h> +#include <openssl/aes.h> +#include "cms_lcl.h" + +/* CMS EnvelopedData Utilities */ + +DECLARE_ASN1_ITEM(CMS_EnvelopedData) +DECLARE_ASN1_ITEM(CMS_RecipientInfo) +DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) +DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) +DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) + +DECLARE_STACK_OF(CMS_RecipientInfo) + +static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) + { + if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) + { + CMSerr(CMS_F_CMS_GET0_ENVELOPED, + CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); + return NULL; + } + return cms->d.envelopedData; + } + +static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) + { + if (cms->d.other == NULL) + { + cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData); + if (!cms->d.envelopedData) + { + CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + cms->d.envelopedData->version = 0; + cms->d.envelopedData->encryptedContentInfo->contentType = + OBJ_nid2obj(NID_pkcs7_data); + ASN1_OBJECT_free(cms->contentType); + cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); + return cms->d.envelopedData; + } + return cms_get0_enveloped(cms); + } + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) + { + CMS_EnvelopedData *env; + env = cms_get0_enveloped(cms); + if (!env) + return NULL; + return env->recipientInfos; + } + +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri) + { + return ri->type; + } + +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) + { + CMS_ContentInfo *cms; + CMS_EnvelopedData *env; + cms = CMS_ContentInfo_new(); + if (!cms) + goto merr; + env = cms_enveloped_data_init(cms); + if (!env) + goto merr; + if (!cms_EncryptedContent_init(env->encryptedContentInfo, + cipher, NULL, 0)) + goto merr; + return cms; + merr: + if (cms) + CMS_ContentInfo_free(cms); + CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE); + return NULL; + } + +/* Key Transport Recipient Info (KTRI) routines */ + +/* Add a recipient certificate. For now only handle key transport. + * If we ever handle key agreement will need updating. + */ + +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags) + { + CMS_RecipientInfo *ri = NULL; + CMS_KeyTransRecipientInfo *ktri; + CMS_EnvelopedData *env; + EVP_PKEY *pk = NULL; + int type; + env = cms_get0_enveloped(cms); + if (!env) + goto err; + + /* Initialize recipient info */ + ri = M_ASN1_new_of(CMS_RecipientInfo); + if (!ri) + goto merr; + + /* Initialize and add key transport recipient info */ + + ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); + if (!ri->d.ktri) + goto merr; + ri->type = CMS_RECIPINFO_TRANS; + + ktri = ri->d.ktri; + + X509_check_purpose(recip, -1, -1); + pk = X509_get_pubkey(recip); + if (!pk) + { + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, + CMS_R_ERROR_GETTING_PUBLIC_KEY); + goto err; + } + CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); + ktri->pkey = pk; + ktri->recip = recip; + + if (flags & CMS_USE_KEYID) + { + ktri->version = 2; + type = CMS_RECIPINFO_KEYIDENTIFIER; + } + else + { + ktri->version = 0; + type = CMS_RECIPINFO_ISSUER_SERIAL; + } + + /* Not a typo: RecipientIdentifier and SignerIdentifier are the + * same structure. + */ + + if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) + goto err; + + /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, + * hard code algorithm parameters. + */ + + if (pk->type == EVP_PKEY_RSA) + { + X509_ALGOR_set0(ktri->keyEncryptionAlgorithm, + OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, 0); + } + else + { + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + } + + if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) + goto merr; + + return ri; + + merr: + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); + err: + if (ri) + M_ASN1_free_of(ri, CMS_RecipientInfo); + return NULL; + + } + +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg) + { + CMS_KeyTransRecipientInfo *ktri; + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + + ktri = ri->d.ktri; + + if (pk) + *pk = ktri->pkey; + if (recip) + *recip = ktri->recip; + if (palg) + *palg = ktri->keyEncryptionAlgorithm; + return 1; + } + +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno) + { + CMS_KeyTransRecipientInfo *ktri; + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ktri = ri->d.ktri; + + return cms_SignerIdentifier_get0_signer_id(ktri->rid, + keyid, issuer, sno); + } + +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) + { + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, + CMS_R_NOT_KEY_TRANSPORT); + return -2; + } + return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); + } + +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) + { + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ri->d.ktri->pkey = pkey; + return 1; + } + +/* Encrypt content key in key transport recipient info */ + +static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_KeyTransRecipientInfo *ktri; + CMS_EncryptedContentInfo *ec; + unsigned char *ek = NULL; + int eklen; + + int ret = 0; + + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ktri = ri->d.ktri; + ec = cms->d.envelopedData->encryptedContentInfo; + + eklen = EVP_PKEY_size(ktri->pkey); + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + eklen = EVP_PKEY_encrypt(ek, ec->key, ec->keylen, ktri->pkey); + + if (eklen <= 0) + goto err; + + ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); + ek = NULL; + + ret = 1; + + err: + if (ek) + OPENSSL_free(ek); + return ret; + + } + +/* Decrypt content key from KTRI */ + +static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; + unsigned char *ek = NULL; + int eklen; + int ret = 0; + + if (ktri->pkey == NULL) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, + CMS_R_NO_PRIVATE_KEY); + return 0; + } + + eklen = EVP_PKEY_size(ktri->pkey); + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + eklen = EVP_PKEY_decrypt(ek, + ktri->encryptedKey->data, + ktri->encryptedKey->length, ktri->pkey); + if (eklen <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); + goto err; + } + + ret = 1; + + cms->d.envelopedData->encryptedContentInfo->key = ek; + cms->d.envelopedData->encryptedContentInfo->keylen = eklen; + + err: + if (!ret && ek) + OPENSSL_free(ek); + + return ret; + } + +/* Key Encrypted Key (KEK) RecipientInfo routines */ + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen) + { + ASN1_OCTET_STRING tmp_os; + CMS_KEKRecipientInfo *kekri; + if (ri->type != CMS_RECIPINFO_KEK) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK); + return -2; + } + kekri = ri->d.kekri; + tmp_os.type = V_ASN1_OCTET_STRING; + tmp_os.flags = 0; + tmp_os.data = (unsigned char *)id; + tmp_os.length = (int)idlen; + return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier); + } + +/* For now hard code AES key wrap info */ + +static size_t aes_wrap_keylen(int nid) + { + switch (nid) + { + case NID_id_aes128_wrap: + return 16; + + case NID_id_aes192_wrap: + return 24; + + case NID_id_aes256_wrap: + return 32; + + default: + return 0; + } + } + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType) + { + CMS_RecipientInfo *ri = NULL; + CMS_EnvelopedData *env; + CMS_KEKRecipientInfo *kekri; + env = cms_get0_enveloped(cms); + if (!env) + goto err; + + if (nid == NID_undef) + { + switch (keylen) + { + case 16: + nid = NID_id_aes128_wrap; + break; + + case 24: + nid = NID_id_aes192_wrap; + break; + + case 32: + nid = NID_id_aes256_wrap; + break; + + default: + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, + CMS_R_INVALID_KEY_LENGTH); + goto err; + } + + } + else + { + + size_t exp_keylen = aes_wrap_keylen(nid); + + if (!exp_keylen) + { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, + CMS_R_UNSUPPORTED_KEK_ALGORITHM); + goto err; + } + + if (keylen != exp_keylen) + { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, + CMS_R_INVALID_KEY_LENGTH); + goto err; + } + + } + + /* Initialize recipient info */ + ri = M_ASN1_new_of(CMS_RecipientInfo); + if (!ri) + goto merr; + + ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); + if (!ri->d.kekri) + goto merr; + ri->type = CMS_RECIPINFO_KEK; + + kekri = ri->d.kekri; + + if (otherTypeId) + { + kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute); + if (kekri->kekid->other == NULL) + goto merr; + } + + if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) + goto merr; + + + /* After this point no calls can fail */ + + kekri->version = 4; + + kekri->key = key; + kekri->keylen = keylen; + + ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); + + kekri->kekid->date = date; + + if (kekri->kekid->other) + { + kekri->kekid->other->keyAttrId = otherTypeId; + kekri->kekid->other->keyAttr = otherType; + } + + X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, + OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); + + return ri; + + merr: + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE); + err: + if (ri) + M_ASN1_free_of(ri, CMS_RecipientInfo); + return NULL; + + } + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype) + { + CMS_KEKIdentifier *rkid; + if (ri->type != CMS_RECIPINFO_KEK) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK); + return 0; + } + rkid = ri->d.kekri->kekid; + if (palg) + *palg = ri->d.kekri->keyEncryptionAlgorithm; + if (pid) + *pid = rkid->keyIdentifier; + if (pdate) + *pdate = rkid->date; + if (potherid) + { + if (rkid->other) + *potherid = rkid->other->keyAttrId; + else + *potherid = NULL; + } + if (pothertype) + { + if (rkid->other) + *pothertype = rkid->other->keyAttr; + else + *pothertype = NULL; + } + return 1; + } + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen) + { + CMS_KEKRecipientInfo *kekri; + if (ri->type != CMS_RECIPINFO_KEK) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK); + return 0; + } + + kekri = ri->d.kekri; + kekri->key = key; + kekri->keylen = keylen; + return 1; + } + + +/* Encrypt content key in KEK recipient info */ + +static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *wkey = NULL; + int wkeylen; + int r = 0; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); + return 0; + } + + if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + wkey = OPENSSL_malloc(ec->keylen + 8); + + if (!wkey) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); + + if (wkeylen <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); + goto err; + } + + ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); + + r = 1; + + err: + + if (!r && wkey) + OPENSSL_free(wkey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + + } + +/* Decrypt content key in KEK recipient info */ + +static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *ukey = NULL; + int ukeylen; + int r = 0, wrap_nid; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY); + return 0; + } + + wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); + if (aes_wrap_keylen(wrap_nid) != kekri->keylen) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_INVALID_KEY_LENGTH); + return 0; + } + + /* If encrypted key length is invalid don't bother */ + + if (kekri->encryptedKey->length < 16) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); + goto err; + } + + if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); + + if (!ukey) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + ukeylen = AES_unwrap_key(&actx, NULL, ukey, + kekri->encryptedKey->data, + kekri->encryptedKey->length); + + if (ukeylen <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_UNWRAP_ERROR); + goto err; + } + + ec->key = ukey; + ec->keylen = ukeylen; + + r = 1; + + err: + + if (!r && ukey) + OPENSSL_free(ukey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + + } + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) + { + switch(ri->type) + { + case CMS_RECIPINFO_TRANS: + return cms_RecipientInfo_ktri_decrypt(cms, ri); + + case CMS_RECIPINFO_KEK: + return cms_RecipientInfo_kekri_decrypt(cms, ri); + + default: + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, + CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE); + return 0; + } + } + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) + { + CMS_EncryptedContentInfo *ec; + STACK_OF(CMS_RecipientInfo) *rinfos; + CMS_RecipientInfo *ri; + int i, r, ok = 0; + BIO *ret; + + /* Get BIO first to set up key */ + + ec = cms->d.envelopedData->encryptedContentInfo; + ret = cms_EncryptedContent_init_bio(ec); + + /* If error or no cipher end of processing */ + + if (!ret || !ec->cipher) + return ret; + + /* Now encrypt content key according to each RecipientInfo type */ + + rinfos = cms->d.envelopedData->recipientInfos; + + for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) + { + ri = sk_CMS_RecipientInfo_value(rinfos, i); + + switch (ri->type) + { + case CMS_RECIPINFO_TRANS: + r = cms_RecipientInfo_ktri_encrypt(cms, ri); + break; + + case CMS_RECIPINFO_KEK: + r = cms_RecipientInfo_kekri_encrypt(cms, ri); + break; + + default: + CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, + CMS_R_UNSUPPORTED_RECIPIENT_TYPE); + goto err; + } + + if (r <= 0) + { + CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, + CMS_R_ERROR_SETTING_RECIPIENTINFO); + goto err; + } + } + + ok = 1; + + err: + ec->cipher = NULL; + if (ec->key) + { + OPENSSL_cleanse(ec->key, ec->keylen); + OPENSSL_free(ec->key); + ec->key = NULL; + ec->keylen = 0; + } + if (ok) + return ret; + BIO_free(ret); + return NULL; + + } diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c new file mode 100644 index 000000000000..52fa53954f32 --- /dev/null +++ b/crypto/cms/cms_err.c @@ -0,0 +1,236 @@ +/* crypto/cms/cms_err.c */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include <stdio.h> +#include <openssl/err.h> +#include <openssl/cms.h> + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CMS,func,0) +#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CMS,0,reason) + +static ERR_STRING_DATA CMS_str_functs[]= + { +{ERR_FUNC(CMS_F_CHECK_CONTENT), "CHECK_CONTENT"}, +{ERR_FUNC(CMS_F_CMS_ADD0_CERT), "CMS_add0_cert"}, +{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY), "CMS_add0_recipient_key"}, +{ERR_FUNC(CMS_F_CMS_ADD1_RECEIPTREQUEST), "CMS_add1_ReceiptRequest"}, +{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT), "CMS_add1_recipient_cert"}, +{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER), "CMS_add1_signer"}, +{ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"}, +{ERR_FUNC(CMS_F_CMS_COMPRESS), "CMS_compress"}, +{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_CREATE), "cms_CompressedData_create"}, +{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO), "cms_CompressedData_init_bio"}, +{ERR_FUNC(CMS_F_CMS_COPY_CONTENT), "CMS_COPY_CONTENT"}, +{ERR_FUNC(CMS_F_CMS_COPY_MESSAGEDIGEST), "CMS_COPY_MESSAGEDIGEST"}, +{ERR_FUNC(CMS_F_CMS_DATA), "CMS_data"}, +{ERR_FUNC(CMS_F_CMS_DATAFINAL), "CMS_dataFinal"}, +{ERR_FUNC(CMS_F_CMS_DATAINIT), "CMS_dataInit"}, +{ERR_FUNC(CMS_F_CMS_DECRYPT), "CMS_decrypt"}, +{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY), "CMS_decrypt_set1_key"}, +{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY), "CMS_decrypt_set1_pkey"}, +{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX), "cms_DigestAlgorithm_find_ctx"}, +{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "cms_DigestAlgorithm_init_bio"}, +{ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL), "cms_DigestedData_do_final"}, +{ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY), "CMS_digest_verify"}, +{ERR_FUNC(CMS_F_CMS_ENCODE_RECEIPT), "cms_encode_Receipt"}, +{ERR_FUNC(CMS_F_CMS_ENCRYPT), "CMS_encrypt"}, +{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO), "cms_EncryptedContent_init_bio"}, +{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT), "CMS_EncryptedData_decrypt"}, +{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT), "CMS_EncryptedData_encrypt"}, +{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY), "CMS_EncryptedData_set1_key"}, +{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_CREATE), "CMS_EnvelopedData_create"}, +{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO), "cms_EnvelopedData_init_bio"}, +{ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT), "CMS_ENVELOPED_DATA_INIT"}, +{ERR_FUNC(CMS_F_CMS_FINAL), "CMS_final"}, +{ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES), "CMS_GET0_CERTIFICATE_CHOICES"}, +{ERR_FUNC(CMS_F_CMS_GET0_CONTENT), "CMS_get0_content"}, +{ERR_FUNC(CMS_F_CMS_GET0_ECONTENT_TYPE), "CMS_GET0_ECONTENT_TYPE"}, +{ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "CMS_GET0_ENVELOPED"}, +{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"}, +{ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"}, +{ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1), "cms_msgSigDigest_add1"}, +{ERR_FUNC(CMS_F_CMS_RECEIPTREQUEST_CREATE0), "CMS_ReceiptRequest_create0"}, +{ERR_FUNC(CMS_F_CMS_RECEIPT_VERIFY), "cms_Receipt_verify"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT), "CMS_RECIPIENTINFO_KEKRI_DECRYPT"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT), "CMS_RECIPIENTINFO_KEKRI_ENCRYPT"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID), "CMS_RecipientInfo_kekri_get0_id"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP), "CMS_RecipientInfo_kekri_id_cmp"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RecipientInfo_ktri_cert_cmp"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT), "CMS_RECIPIENTINFO_KTRI_DECRYPT"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT), "CMS_RECIPIENTINFO_KTRI_ENCRYPT"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS), "CMS_RecipientInfo_ktri_get0_algs"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID), "CMS_RecipientInfo_ktri_get0_signer_id"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY), "CMS_RecipientInfo_set0_key"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY), "CMS_RecipientInfo_set0_pkey"}, +{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "cms_set1_SignerIdentifier"}, +{ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"}, +{ERR_FUNC(CMS_F_CMS_SIGN), "CMS_sign"}, +{ERR_FUNC(CMS_F_CMS_SIGNED_DATA_INIT), "CMS_SIGNED_DATA_INIT"}, +{ERR_FUNC(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN), "CMS_SIGNERINFO_CONTENT_SIGN"}, +{ERR_FUNC(CMS_F_CMS_SIGNERINFO_SIGN), "CMS_SignerInfo_sign"}, +{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY), "CMS_SignerInfo_verify"}, +{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CERT), "CMS_SIGNERINFO_VERIFY_CERT"}, +{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT), "CMS_SignerInfo_verify_content"}, +{ERR_FUNC(CMS_F_CMS_SIGN_RECEIPT), "CMS_sign_receipt"}, +{ERR_FUNC(CMS_F_CMS_STREAM), "CMS_STREAM"}, +{ERR_FUNC(CMS_F_CMS_UNCOMPRESS), "CMS_uncompress"}, +{ERR_FUNC(CMS_F_CMS_VERIFY), "CMS_verify"}, +{0,NULL} + }; + +static ERR_STRING_DATA CMS_str_reasons[]= + { +{ERR_REASON(CMS_R_ADD_SIGNER_ERROR) ,"add signer error"}, +{ERR_REASON(CMS_R_CERTIFICATE_ALREADY_PRESENT),"certificate already present"}, +{ERR_REASON(CMS_R_CERTIFICATE_HAS_NO_KEYID),"certificate has no keyid"}, +{ERR_REASON(CMS_R_CERTIFICATE_VERIFY_ERROR),"certificate verify error"}, +{ERR_REASON(CMS_R_CIPHER_INITIALISATION_ERROR),"cipher initialisation error"}, +{ERR_REASON(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),"cipher parameter initialisation error"}, +{ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR) ,"cms datafinal error"}, +{ERR_REASON(CMS_R_CMS_LIB) ,"cms lib"}, +{ERR_REASON(CMS_R_CONTENTIDENTIFIER_MISMATCH),"contentidentifier mismatch"}, +{ERR_REASON(CMS_R_CONTENT_NOT_FOUND) ,"content not found"}, +{ERR_REASON(CMS_R_CONTENT_TYPE_MISMATCH) ,"content type mismatch"}, +{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),"content type not compressed data"}, +{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),"content type not enveloped data"}, +{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),"content type not signed data"}, +{ERR_REASON(CMS_R_CONTENT_VERIFY_ERROR) ,"content verify error"}, +{ERR_REASON(CMS_R_CTRL_ERROR) ,"ctrl error"}, +{ERR_REASON(CMS_R_CTRL_FAILURE) ,"ctrl failure"}, +{ERR_REASON(CMS_R_DECRYPT_ERROR) ,"decrypt error"}, +{ERR_REASON(CMS_R_DIGEST_ERROR) ,"digest error"}, +{ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"}, +{ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"}, +{ERR_REASON(CMS_R_ERROR_SETTING_KEY) ,"error setting key"}, +{ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),"error setting recipientinfo"}, +{ERR_REASON(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),"invalid encrypted key length"}, +{ERR_REASON(CMS_R_INVALID_KEY_LENGTH) ,"invalid key length"}, +{ERR_REASON(CMS_R_MD_BIO_INIT_ERROR) ,"md bio init error"}, +{ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"}, +{ERR_REASON(CMS_R_MESSAGEDIGEST_WRONG_LENGTH),"messagedigest wrong length"}, +{ERR_REASON(CMS_R_MSGSIGDIGEST_ERROR) ,"msgsigdigest error"}, +{ERR_REASON(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE),"msgsigdigest verification failure"}, +{ERR_REASON(CMS_R_MSGSIGDIGEST_WRONG_LENGTH),"msgsigdigest wrong length"}, +{ERR_REASON(CMS_R_NEED_ONE_SIGNER) ,"need one signer"}, +{ERR_REASON(CMS_R_NOT_A_SIGNED_RECEIPT) ,"not a signed receipt"}, +{ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA) ,"not encrypted data"}, +{ERR_REASON(CMS_R_NOT_KEK) ,"not kek"}, +{ERR_REASON(CMS_R_NOT_KEY_TRANSPORT) ,"not key transport"}, +{ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"}, +{ERR_REASON(CMS_R_NO_CIPHER) ,"no cipher"}, +{ERR_REASON(CMS_R_NO_CONTENT) ,"no content"}, +{ERR_REASON(CMS_R_NO_CONTENT_TYPE) ,"no content type"}, +{ERR_REASON(CMS_R_NO_DEFAULT_DIGEST) ,"no default digest"}, +{ERR_REASON(CMS_R_NO_DIGEST_SET) ,"no digest set"}, +{ERR_REASON(CMS_R_NO_KEY) ,"no key"}, +{ERR_REASON(CMS_R_NO_KEY_OR_CERT) ,"no key or cert"}, +{ERR_REASON(CMS_R_NO_MATCHING_DIGEST) ,"no matching digest"}, +{ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"}, +{ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"}, +{ERR_REASON(CMS_R_NO_MSGSIGDIGEST) ,"no msgsigdigest"}, +{ERR_REASON(CMS_R_NO_PRIVATE_KEY) ,"no private key"}, +{ERR_REASON(CMS_R_NO_PUBLIC_KEY) ,"no public key"}, +{ERR_REASON(CMS_R_NO_RECEIPT_REQUEST) ,"no receipt request"}, +{ERR_REASON(CMS_R_NO_SIGNERS) ,"no signers"}, +{ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"}, +{ERR_REASON(CMS_R_RECEIPT_DECODE_ERROR) ,"receipt decode error"}, +{ERR_REASON(CMS_R_RECIPIENT_ERROR) ,"recipient error"}, +{ERR_REASON(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),"signer certificate not found"}, +{ERR_REASON(CMS_R_SIGNFINAL_ERROR) ,"signfinal error"}, +{ERR_REASON(CMS_R_SMIME_TEXT_ERROR) ,"smime text error"}, +{ERR_REASON(CMS_R_STORE_INIT_ERROR) ,"store init error"}, +{ERR_REASON(CMS_R_TYPE_NOT_COMPRESSED_DATA),"type not compressed data"}, +{ERR_REASON(CMS_R_TYPE_NOT_DATA) ,"type not data"}, +{ERR_REASON(CMS_R_TYPE_NOT_DIGESTED_DATA),"type not digested data"}, +{ERR_REASON(CMS_R_TYPE_NOT_ENCRYPTED_DATA),"type not encrypted data"}, +{ERR_REASON(CMS_R_TYPE_NOT_ENVELOPED_DATA),"type not enveloped data"}, +{ERR_REASON(CMS_R_UNABLE_TO_FINALIZE_CONTEXT),"unable to finalize context"}, +{ERR_REASON(CMS_R_UNKNOWN_CIPHER) ,"unknown cipher"}, +{ERR_REASON(CMS_R_UNKNOWN_DIGEST_ALGORIHM),"unknown digest algorihm"}, +{ERR_REASON(CMS_R_UNKNOWN_ID) ,"unknown id"}, +{ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"}, +{ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"}, +{ERR_REASON(CMS_R_UNSUPPORTED_KEK_ALGORITHM),"unsupported kek algorithm"}, +{ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"}, +{ERR_REASON(CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE),"unsupported recpientinfo type"}, +{ERR_REASON(CMS_R_UNSUPPORTED_TYPE) ,"unsupported type"}, +{ERR_REASON(CMS_R_UNWRAP_ERROR) ,"unwrap error"}, +{ERR_REASON(CMS_R_VERIFICATION_FAILURE) ,"verification failure"}, +{ERR_REASON(CMS_R_WRAP_ERROR) ,"wrap error"}, +{0,NULL} + }; + +#endif + +void ERR_load_CMS_strings(void) + { +#ifndef OPENSSL_NO_ERR + + if (ERR_func_error_string(CMS_str_functs[0].error) == NULL) + { + ERR_load_strings(0,CMS_str_functs); + ERR_load_strings(0,CMS_str_reasons); + } +#endif + } diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c new file mode 100644 index 000000000000..ed34ff32282a --- /dev/null +++ b/crypto/cms/cms_ess.c @@ -0,0 +1,420 @@ +/* crypto/cms/cms_ess.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/rand.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include "cms_lcl.h" + +DECLARE_ASN1_ITEM(CMS_ReceiptRequest) +DECLARE_ASN1_ITEM(CMS_Receipt) + +IMPLEMENT_ASN1_FUNCTIONS_const(CMS_ReceiptRequest) + +/* ESS services: for now just Signed Receipt related */ + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr) + { + ASN1_STRING *str; + CMS_ReceiptRequest *rr = NULL; + if (prr) + *prr = NULL; + str = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_id_smime_aa_receiptRequest), + -3, V_ASN1_SEQUENCE); + if (!str) + return 0; + + rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest)); + if (!rr) + return -1; + if (prr) + *prr = rr; + else + CMS_ReceiptRequest_free(rr); + return 1; + } + +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) *receiptList, + STACK_OF(GENERAL_NAMES) *receiptsTo) + { + CMS_ReceiptRequest *rr = NULL; + + rr = CMS_ReceiptRequest_new(); + if (!rr) + goto merr; + if (id) + ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); + else + { + if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32)) + goto merr; + if (RAND_pseudo_bytes(rr->signedContentIdentifier->data, 32) + <= 0) + goto err; + } + + sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free); + rr->receiptsTo = receiptsTo; + + if (receiptList) + { + rr->receiptsFrom->type = 1; + rr->receiptsFrom->d.receiptList = receiptList; + } + else + { + rr->receiptsFrom->type = 0; + rr->receiptsFrom->d.allOrFirstTier = allorfirst; + } + + return rr; + + merr: + CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE); + + err: + if (rr) + CMS_ReceiptRequest_free(rr); + + return NULL; + + } + +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr) + { + unsigned char *rrder = NULL; + int rrderlen, r = 0; + + rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder); + if (rrderlen < 0) + goto merr; + + if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest, + V_ASN1_SEQUENCE, rrder, rrderlen)) + goto merr; + + r = 1; + + merr: + if (!r) + CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE); + + if (rrder) + OPENSSL_free(rrder); + + return r; + + } + +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto) + { + if (pcid) + *pcid = rr->signedContentIdentifier; + if (rr->receiptsFrom->type == 0) + { + if (pallorfirst) + *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier; + if (plist) + *plist = NULL; + } + else + { + if (pallorfirst) + *pallorfirst = -1; + if (plist) + *plist = rr->receiptsFrom->d.receiptList; + } + if (prto) + *prto = rr->receiptsTo; + } + +/* Digest a SignerInfo structure for msgSigDigest attribute processing */ + +static int cms_msgSigDigest(CMS_SignerInfo *si, + unsigned char *dig, unsigned int *diglen) + { + const EVP_MD *md; + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return 0; + if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md, + si->signedAttrs, dig, diglen)) + return 0; + return 1; + } + +/* Add a msgSigDigest attribute to a SignerInfo */ + +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) + { + unsigned char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + if (!cms_msgSigDigest(src, dig, &diglen)) + { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR); + return 0; + } + if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest, + V_ASN1_OCTET_STRING, dig, diglen)) + { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; + } + +/* Verify signed receipt after it has already passed normal CMS verify */ + +int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) + { + int r = 0, i; + CMS_ReceiptRequest *rr = NULL; + CMS_Receipt *rct = NULL; + STACK_OF(CMS_SignerInfo) *sis, *osis; + CMS_SignerInfo *si, *osi = NULL; + ASN1_OCTET_STRING *msig, **pcont; + ASN1_OBJECT *octype; + unsigned char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + /* Get SignerInfos, also checks SignedData content type */ + osis = CMS_get0_SignerInfos(req_cms); + sis = CMS_get0_SignerInfos(cms); + if (!osis || !sis) + goto err; + + if (sk_CMS_SignerInfo_num(sis) != 1) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER); + goto err; + } + + /* Check receipt content type */ + if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT); + goto err; + } + + /* Extract and decode receipt content */ + pcont = CMS_get0_content(cms); + if (!pcont || !*pcont) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT); + goto err; + } + + rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt)); + + if (!rct) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR); + goto err; + } + + /* Locate original request */ + + for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++) + { + osi = sk_CMS_SignerInfo_value(osis, i); + if (!ASN1_STRING_cmp(osi->signature, + rct->originatorSignatureValue)) + break; + } + + if (i == sk_CMS_SignerInfo_num(osis)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE); + goto err; + } + + si = sk_CMS_SignerInfo_value(sis, 0); + + /* Get msgSigDigest value and compare */ + + msig = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_id_smime_aa_msgSigDigest), + -3, V_ASN1_OCTET_STRING); + + if (!msig) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST); + goto err; + } + + if (!cms_msgSigDigest(osi, dig, &diglen)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR); + goto err; + } + + if (diglen != (unsigned int)msig->length) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, + CMS_R_MSGSIGDIGEST_WRONG_LENGTH); + goto err; + } + + if (memcmp(dig, msig->data, diglen)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, + CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE); + goto err; + } + + /* Compare content types */ + + octype = CMS_signed_get0_data_by_OBJ(osi, + OBJ_nid2obj(NID_pkcs9_contentType), + -3, V_ASN1_OBJECT); + if (!octype) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE); + goto err; + } + + /* Compare details in receipt request */ + + if (OBJ_cmp(octype, rct->contentType)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH); + goto err; + } + + /* Get original receipt request details */ + + if (!CMS_get1_ReceiptRequest(osi, &rr)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST); + goto err; + } + + if (ASN1_STRING_cmp(rr->signedContentIdentifier, + rct->signedContentIdentifier)) + { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, + CMS_R_CONTENTIDENTIFIER_MISMATCH); + goto err; + } + + r = 1; + + err: + if (rr) + CMS_ReceiptRequest_free(rr); + if (rct) + M_ASN1_free_of(rct, CMS_Receipt); + + return r; + + } + +/* Encode a Receipt into an OCTET STRING read for including into content of + * a SignedData ContentInfo. + */ + +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si) + { + CMS_Receipt rct; + CMS_ReceiptRequest *rr = NULL; + ASN1_OBJECT *ctype; + ASN1_OCTET_STRING *os = NULL; + + /* Get original receipt request */ + + /* Get original receipt request details */ + + if (!CMS_get1_ReceiptRequest(si, &rr)) + { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST); + goto err; + } + + /* Get original content type */ + + ctype = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_pkcs9_contentType), + -3, V_ASN1_OBJECT); + if (!ctype) + { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE); + goto err; + } + + rct.version = 1; + rct.contentType = ctype; + rct.signedContentIdentifier = rr->signedContentIdentifier; + rct.originatorSignatureValue = si->signature; + + os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL); + + err: + if (rr) + CMS_ReceiptRequest_free(rr); + + return os; + + } + + diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c new file mode 100644 index 000000000000..30f5ddfe6d2d --- /dev/null +++ b/crypto/cms/cms_io.c @@ -0,0 +1,140 @@ +/* crypto/cms/cms_io.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include "cms.h" +#include "cms_lcl.h" + +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms) + { + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms); + } + +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms) + { + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms); + } + +IMPLEMENT_PEM_rw_const(CMS, CMS_ContentInfo, PEM_STRING_CMS, CMS_ContentInfo) + +/* Callback for int_smime_write_ASN1 */ + +static int cms_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, + const ASN1_ITEM *it) + { + CMS_ContentInfo *cms = (CMS_ContentInfo *)val; + BIO *tmpbio, *cmsbio; + int r = 0; + + if (!(flags & SMIME_DETACHED)) + { + SMIME_crlf_copy(data, out, flags); + return 1; + } + + /* Let CMS code prepend any needed BIOs */ + + cmsbio = CMS_dataInit(cms, out); + + if (!cmsbio) + return 0; + + /* Copy data across, passing through filter BIOs for processing */ + SMIME_crlf_copy(data, cmsbio, flags); + + /* Finalize structure */ + if (CMS_dataFinal(cms, cmsbio) <= 0) + goto err; + + r = 1; + + err: + + /* Now remove any digests prepended to the BIO */ + + while (cmsbio != out) + { + tmpbio = BIO_pop(cmsbio); + BIO_free(cmsbio); + cmsbio = tmpbio; + } + + return 1; + + } + + +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags) + { + STACK_OF(X509_ALGOR) *mdalgs; + int ctype_nid = OBJ_obj2nid(cms->contentType); + int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms)); + if (ctype_nid == NID_pkcs7_signed) + mdalgs = cms->d.signedData->digestAlgorithms; + else + mdalgs = NULL; + + return int_smime_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags, + ctype_nid, econt_nid, mdalgs, + cms_output_data, + ASN1_ITEM_rptr(CMS_ContentInfo)); + } + +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont) + { + return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont, + ASN1_ITEM_rptr(CMS_ContentInfo)); + } diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h new file mode 100644 index 000000000000..7d60fac67eb7 --- /dev/null +++ b/crypto/cms/cms_lcl.h @@ -0,0 +1,460 @@ +/* crypto/cms/cms_lcl.h */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_CMS_LCL_H +#define HEADER_CMS_LCL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <openssl/x509.h> + +/* Cryptographic message syntax (CMS) structures: taken + * from RFC3852 + */ + +/* Forward references */ + +typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber; +typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo; +typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier; +typedef struct CMS_SignedData_st CMS_SignedData; +typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat; +typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo; +typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo; +typedef struct CMS_EnvelopedData_st CMS_EnvelopedData; +typedef struct CMS_DigestedData_st CMS_DigestedData; +typedef struct CMS_EncryptedData_st CMS_EncryptedData; +typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData; +typedef struct CMS_CompressedData_st CMS_CompressedData; +typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat; +typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo; +typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey; +typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey; +typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo; +typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute; +typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier; +typedef struct CMS_KeyAgreeRecipientIdentifier_st CMS_KeyAgreeRecipientIdentifier; +typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey; +typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier; +typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo; +typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo; +typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo; +typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom; + +struct CMS_ContentInfo_st + { + ASN1_OBJECT *contentType; + union { + ASN1_OCTET_STRING *data; + CMS_SignedData *signedData; + CMS_EnvelopedData *envelopedData; + CMS_DigestedData *digestedData; + CMS_EncryptedData *encryptedData; + CMS_AuthenticatedData *authenticatedData; + CMS_CompressedData *compressedData; + ASN1_TYPE *other; + /* Other types ... */ + void *otherData; + } d; + }; + +struct CMS_SignedData_st + { + long version; + STACK_OF(X509_ALGOR) *digestAlgorithms; + CMS_EncapsulatedContentInfo *encapContentInfo; + STACK_OF(CMS_CertificateChoices) *certificates; + STACK_OF(CMS_RevocationInfoChoice) *crls; + STACK_OF(CMS_SignerInfo) *signerInfos; + }; + +struct CMS_EncapsulatedContentInfo_st + { + ASN1_OBJECT *eContentType; + ASN1_OCTET_STRING *eContent; + /* Set to 1 if incomplete structure only part set up */ + int partial; + }; + +struct CMS_SignerInfo_st + { + long version; + CMS_SignerIdentifier *sid; + X509_ALGOR *digestAlgorithm; + STACK_OF(X509_ATTRIBUTE) *signedAttrs; + X509_ALGOR *signatureAlgorithm; + ASN1_OCTET_STRING *signature; + STACK_OF(X509_ATTRIBUTE) *unsignedAttrs; + /* Signing certificate and key */ + X509 *signer; + EVP_PKEY *pkey; + }; + +struct CMS_SignerIdentifier_st + { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + ASN1_OCTET_STRING *subjectKeyIdentifier; + } d; + }; + +struct CMS_EnvelopedData_st + { + long version; + CMS_OriginatorInfo *originatorInfo; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + CMS_EncryptedContentInfo *encryptedContentInfo; + STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; + }; + +struct CMS_OriginatorInfo_st + { + STACK_OF(CMS_CertificateChoices) *certificates; + STACK_OF(CMS_RevocationInfoChoice) *crls; + }; + +struct CMS_EncryptedContentInfo_st + { + ASN1_OBJECT *contentType; + X509_ALGOR *contentEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedContent; + /* Content encryption algorithm and key */ + const EVP_CIPHER *cipher; + unsigned char *key; + size_t keylen; + }; + +struct CMS_RecipientInfo_st + { + int type; + union { + CMS_KeyTransRecipientInfo *ktri; + CMS_KeyAgreeRecipientInfo *kari; + CMS_KEKRecipientInfo *kekri; + CMS_PasswordRecipientInfo *pwri; + CMS_OtherRecipientInfo *ori; + } d; + }; + +typedef CMS_SignerIdentifier CMS_RecipientIdentifier; + +struct CMS_KeyTransRecipientInfo_st + { + long version; + CMS_RecipientIdentifier *rid; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + /* Recipient Key and cert */ + X509 *recip; + EVP_PKEY *pkey; + }; + +struct CMS_KeyAgreeRecipientInfo_st + { + long version; + CMS_OriginatorIdentifierOrKey *originator; + ASN1_OCTET_STRING *ukm; + X509_ALGOR *keyEncryptionAlgorithm; + STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys; + }; + +struct CMS_OriginatorIdentifierOrKey_st + { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + ASN1_OCTET_STRING *subjectKeyIdentifier; + CMS_OriginatorPublicKey *originatorKey; + } d; + }; + +struct CMS_OriginatorPublicKey_st + { + X509_ALGOR *algorithm; + ASN1_BIT_STRING *publicKey; + }; + +struct CMS_RecipientEncryptedKey_st + { + CMS_KeyAgreeRecipientIdentifier *rid; + ASN1_OCTET_STRING *encryptedKey; + }; + +struct CMS_KeyAgreeRecipientIdentifier_st + { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + CMS_RecipientKeyIdentifier *rKeyId; + } d; + }; + +struct CMS_RecipientKeyIdentifier_st + { + ASN1_OCTET_STRING *subjectKeyIdentifier; + ASN1_GENERALIZEDTIME *date; + CMS_OtherKeyAttribute *other; + }; + +struct CMS_KEKRecipientInfo_st + { + long version; + CMS_KEKIdentifier *kekid; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + /* Extra info: symmetric key to use */ + unsigned char *key; + size_t keylen; + }; + +struct CMS_KEKIdentifier_st + { + ASN1_OCTET_STRING *keyIdentifier; + ASN1_GENERALIZEDTIME *date; + CMS_OtherKeyAttribute *other; + }; + +struct CMS_PasswordRecipientInfo_st + { + long version; + X509_ALGOR *keyDerivationAlgorithm; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + }; + +struct CMS_OtherRecipientInfo_st + { + ASN1_OBJECT *oriType; + ASN1_TYPE *oriValue; + }; + +struct CMS_DigestedData_st + { + long version; + X509_ALGOR *digestAlgorithm; + CMS_EncapsulatedContentInfo *encapContentInfo; + ASN1_OCTET_STRING *digest; + }; + +struct CMS_EncryptedData_st + { + long version; + CMS_EncryptedContentInfo *encryptedContentInfo; + STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; + }; + +struct CMS_AuthenticatedData_st + { + long version; + CMS_OriginatorInfo *originatorInfo; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + X509_ALGOR *macAlgorithm; + X509_ALGOR *digestAlgorithm; + CMS_EncapsulatedContentInfo *encapContentInfo; + STACK_OF(X509_ATTRIBUTE) *authAttrs; + ASN1_OCTET_STRING *mac; + STACK_OF(X509_ATTRIBUTE) *unauthAttrs; + }; + +struct CMS_CompressedData_st + { + long version; + X509_ALGOR *compressionAlgorithm; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + CMS_EncapsulatedContentInfo *encapContentInfo; + }; + +struct CMS_RevocationInfoChoice_st + { + int type; + union { + X509_CRL *crl; + CMS_OtherRevocationInfoFormat *other; + } d; + }; + +#define CMS_REVCHOICE_CRL 0 +#define CMS_REVCHOICE_OTHER 1 + +struct CMS_OtherRevocationInfoFormat_st + { + ASN1_OBJECT *otherRevInfoFormat; + ASN1_TYPE *otherRevInfo; + }; + +struct CMS_CertificateChoices + { + int type; + union { + X509 *certificate; + ASN1_STRING *extendedCertificate; /* Obsolete */ + ASN1_STRING *v1AttrCert; /* Left encoded for now */ + ASN1_STRING *v2AttrCert; /* Left encoded for now */ + CMS_OtherCertificateFormat *other; + } d; + }; + +#define CMS_CERTCHOICE_CERT 0 +#define CMS_CERTCHOICE_EXCERT 1 +#define CMS_CERTCHOICE_V1ACERT 2 +#define CMS_CERTCHOICE_V2ACERT 3 +#define CMS_CERTCHOICE_OTHER 4 + +struct CMS_OtherCertificateFormat_st + { + ASN1_OBJECT *otherCertFormat; + ASN1_TYPE *otherCert; + }; + +/* This is also defined in pkcs7.h but we duplicate it + * to allow the CMS code to be independent of PKCS#7 + */ + +struct CMS_IssuerAndSerialNumber_st + { + X509_NAME *issuer; + ASN1_INTEGER *serialNumber; + }; + +struct CMS_OtherKeyAttribute_st + { + ASN1_OBJECT *keyAttrId; + ASN1_TYPE *keyAttr; + }; + +/* ESS structures */ + +#ifdef HEADER_X509V3_H + +struct CMS_ReceiptRequest_st + { + ASN1_OCTET_STRING *signedContentIdentifier; + CMS_ReceiptsFrom *receiptsFrom; + STACK_OF(GENERAL_NAMES) *receiptsTo; + }; + + +struct CMS_ReceiptsFrom_st + { + int type; + union + { + long allOrFirstTier; + STACK_OF(GENERAL_NAMES) *receiptList; + } d; + }; +#endif + +struct CMS_Receipt_st + { + long version; + ASN1_OBJECT *contentType; + ASN1_OCTET_STRING *signedContentIdentifier; + ASN1_OCTET_STRING *originatorSignatureValue; + }; + +DECLARE_ASN1_ITEM(CMS_SignerInfo) +DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) +DECLARE_ASN1_ITEM(CMS_Attributes_Sign) +DECLARE_ASN1_ITEM(CMS_Attributes_Verify) +DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) + +#define CMS_SIGNERINFO_ISSUER_SERIAL 0 +#define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +#define CMS_RECIPINFO_ISSUER_SERIAL 0 +#define CMS_RECIPINFO_KEYIDENTIFIER 1 + +BIO *cms_content_bio(CMS_ContentInfo *cms); + +CMS_ContentInfo *cms_Data_create(void); + +CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md); +BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms); +int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify); + +BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms); +int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain); +int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type); +int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert); + +CMS_ContentInfo *cms_CompressedData_create(int comp_nid); +BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms); + +void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md); +BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm); +int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, + X509_ALGOR *mdalg); + +BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec); +BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms); +int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen); + +int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms); +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si); + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c new file mode 100644 index 000000000000..8e6c1d29a52c --- /dev/null +++ b/crypto/cms/cms_lib.c @@ -0,0 +1,623 @@ +/* crypto/cms/cms_lib.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/bio.h> +#include <openssl/asn1.h> +#include "cms.h" +#include "cms_lcl.h" + +IMPLEMENT_ASN1_FUNCTIONS_const(CMS_ContentInfo) + +DECLARE_ASN1_ITEM(CMS_CertificateChoices) +DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) +DECLARE_STACK_OF(CMS_CertificateChoices) +DECLARE_STACK_OF(CMS_RevocationInfoChoice) + +const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms) + { + return cms->contentType; + } + +CMS_ContentInfo *cms_Data_create(void) + { + CMS_ContentInfo *cms; + cms = CMS_ContentInfo_new(); + if (cms) + { + cms->contentType = OBJ_nid2obj(NID_pkcs7_data); + /* Never detached */ + CMS_set_detached(cms, 0); + } + return cms; + } + +BIO *cms_content_bio(CMS_ContentInfo *cms) + { + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos) + return NULL; + /* If content detached data goes nowhere: create NULL BIO */ + if (!*pos) + return BIO_new(BIO_s_null()); + /* If content not detached and created return memory BIO + */ + if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) + return BIO_new(BIO_s_mem()); + /* Else content was read in: return read only BIO for it */ + return BIO_new_mem_buf((*pos)->data, (*pos)->length); + } + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) + { + BIO *cmsbio, *cont; + if (icont) + cont = icont; + else + cont = cms_content_bio(cms); + if (!cont) + { + CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); + return NULL; + } + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_data: + return cont; + + case NID_pkcs7_signed: + cmsbio = cms_SignedData_init_bio(cms); + break; + + case NID_pkcs7_digest: + cmsbio = cms_DigestedData_init_bio(cms); + break; +#ifdef ZLIB + case NID_id_smime_ct_compressedData: + cmsbio = cms_CompressedData_init_bio(cms); + break; +#endif + + case NID_pkcs7_encrypted: + cmsbio = cms_EncryptedData_init_bio(cms); + break; + + case NID_pkcs7_enveloped: + cmsbio = cms_EnvelopedData_init_bio(cms); + break; + + default: + CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); + return NULL; + } + + if (cmsbio) + return BIO_push(cmsbio, cont); + + if (!icont) + BIO_free(cont); + return NULL; + + } + +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) + { + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos) + return 0; + /* If ebmedded content find memory BIO and set content */ + if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) + { + BIO *mbio; + unsigned char *cont; + long contlen; + mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); + if (!mbio) + { + CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); + return 0; + } + contlen = BIO_get_mem_data(mbio, &cont); + /* Set bio as read only so its content can't be clobbered */ + BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); + BIO_set_mem_eof_return(mbio, 0); + ASN1_STRING_set0(*pos, cont, contlen); + (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; + } + + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_data: + case NID_pkcs7_enveloped: + case NID_pkcs7_encrypted: + case NID_id_smime_ct_compressedData: + /* Nothing to do */ + return 1; + + case NID_pkcs7_signed: + return cms_SignedData_final(cms, cmsbio); + + case NID_pkcs7_digest: + return cms_DigestedData_do_final(cms, cmsbio, 0); + + default: + CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); + return 0; + } + } + +/* Return an OCTET STRING pointer to content. This allows it to + * be accessed or set later. + */ + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) + { + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_data: + return &cms->d.data; + + case NID_pkcs7_signed: + return &cms->d.signedData->encapContentInfo->eContent; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; + + case NID_pkcs7_digest: + return &cms->d.digestedData->encapContentInfo->eContent; + + case NID_pkcs7_encrypted: + return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; + + case NID_id_smime_ct_authData: + return &cms->d.authenticatedData->encapContentInfo->eContent; + + case NID_id_smime_ct_compressedData: + return &cms->d.compressedData->encapContentInfo->eContent; + + default: + if (cms->d.other->type == V_ASN1_OCTET_STRING) + return &cms->d.other->value.octet_string; + CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } + } + +/* Return an ASN1_OBJECT pointer to content type. This allows it to + * be accessed or set later. + */ + +static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) + { + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_signed: + return &cms->d.signedData->encapContentInfo->eContentType; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->encryptedContentInfo->contentType; + + case NID_pkcs7_digest: + return &cms->d.digestedData->encapContentInfo->eContentType; + + case NID_pkcs7_encrypted: + return &cms->d.encryptedData->encryptedContentInfo->contentType; + + case NID_id_smime_ct_authData: + return &cms->d.authenticatedData->encapContentInfo->eContentType; + + case NID_id_smime_ct_compressedData: + return &cms->d.compressedData->encapContentInfo->eContentType; + + default: + CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, + CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } + } + +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) + { + ASN1_OBJECT **petype; + petype = cms_get0_econtent_type(cms); + if (petype) + return *petype; + return NULL; + } + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) + { + ASN1_OBJECT **petype, *etype; + petype = cms_get0_econtent_type(cms); + if (!petype) + return 0; + if (!oid) + return 1; + etype = OBJ_dup(oid); + if (!etype) + return 0; + ASN1_OBJECT_free(*petype); + *petype = etype; + return 1; + } + +int CMS_is_detached(CMS_ContentInfo *cms) + { + ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); + if (!pos) + return -1; + if (*pos) + return 0; + return 1; + } + +int CMS_set_detached(CMS_ContentInfo *cms, int detached) + { + ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); + if (!pos) + return 0; + if (detached) + { + if (*pos) + { + ASN1_OCTET_STRING_free(*pos); + *pos = NULL; + } + return 1; + } + if (!*pos) + *pos = ASN1_OCTET_STRING_new(); + if (*pos) + { + /* NB: special flag to show content is created and not + * read in. + */ + (*pos)->flags |= ASN1_STRING_FLAG_CONT; + return 1; + } + CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); + return 0; + } + +/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ + +void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md) + { + int param_type; + + switch (EVP_MD_type(md)) + { + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + param_type = V_ASN1_UNDEF; + break; + + default: + param_type = V_ASN1_NULL; + break; + } + + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); + + } + +/* Create a digest BIO from an X509_ALGOR structure */ + +BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) + { + BIO *mdbio = NULL; + ASN1_OBJECT *digestoid; + const EVP_MD *digest; + X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); + digest = EVP_get_digestbyobj(digestoid); + if (!digest) + { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, + CMS_R_UNKNOWN_DIGEST_ALGORIHM); + goto err; + } + mdbio = BIO_new(BIO_f_md()); + if (!mdbio || !BIO_set_md(mdbio, digest)) + { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, + CMS_R_MD_BIO_INIT_ERROR); + goto err; + } + return mdbio; + err: + if (mdbio) + BIO_free(mdbio); + return NULL; + } + +/* Locate a message digest content from a BIO chain based on SignerInfo */ + +int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, + X509_ALGOR *mdalg) + { + int nid; + ASN1_OBJECT *mdoid; + X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); + nid = OBJ_obj2nid(mdoid); + /* Look for digest type to match signature */ + for (;;) + { + EVP_MD_CTX *mtmp; + chain = BIO_find_type(chain, BIO_TYPE_MD); + if (chain == NULL) + { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, + CMS_R_NO_MATCHING_DIGEST); + return 0; + } + BIO_get_md_ctx(chain, &mtmp); + if (EVP_MD_CTX_type(mtmp) == nid) + { + EVP_MD_CTX_copy_ex(mctx, mtmp); + return 1; + } + chain = BIO_next(chain); + } + } + +static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms) + { + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_signed: + return &cms->d.signedData->certificates; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->originatorInfo->certificates; + + default: + CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, + CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } + } + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) + { + STACK_OF(CMS_CertificateChoices) **pcerts; + CMS_CertificateChoices *cch; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return NULL; + if (!*pcerts) + *pcerts = sk_CMS_CertificateChoices_new_null(); + if (!*pcerts) + return NULL; + cch = M_ASN1_new_of(CMS_CertificateChoices); + if (!cch) + return NULL; + if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) + { + M_ASN1_free_of(cch, CMS_CertificateChoices); + return NULL; + } + return cch; + } + +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) + { + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) **pcerts; + int i; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return 0; + if (!pcerts) + return 0; + for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) + { + cch = sk_CMS_CertificateChoices_value(*pcerts, i); + if (cch->type == CMS_CERTCHOICE_CERT) + { + if (!X509_cmp(cch->d.certificate, cert)) + { + CMSerr(CMS_F_CMS_ADD0_CERT, + CMS_R_CERTIFICATE_ALREADY_PRESENT); + return 0; + } + } + } + cch = CMS_add0_CertificateChoices(cms); + if (!cch) + return 0; + cch->type = CMS_CERTCHOICE_CERT; + cch->d.certificate = cert; + return 1; + } + +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) + { + int r; + r = CMS_add0_cert(cms, cert); + if (r > 0) + CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + return r; + } + +static STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms) + { + switch (OBJ_obj2nid(cms->contentType)) + { + + case NID_pkcs7_signed: + return &cms->d.signedData->crls; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->originatorInfo->crls; + + default: + CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, + CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } + } + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) + { + STACK_OF(CMS_RevocationInfoChoice) **pcrls; + CMS_RevocationInfoChoice *rch; + pcrls = cms_get0_revocation_choices(cms); + if (!pcrls) + return NULL; + if (!*pcrls) + *pcrls = sk_CMS_RevocationInfoChoice_new_null(); + if (!*pcrls) + return NULL; + rch = M_ASN1_new_of(CMS_RevocationInfoChoice); + if (!rch) + return NULL; + if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) + { + M_ASN1_free_of(rch, CMS_RevocationInfoChoice); + return NULL; + } + return rch; + } + +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) + { + CMS_RevocationInfoChoice *rch; + rch = CMS_add0_RevocationInfoChoice(cms); + if (!rch) + return 0; + rch->type = CMS_REVCHOICE_CRL; + rch->d.crl = crl; + return 1; + } + +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) + { + STACK_OF(X509) *certs = NULL; + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) **pcerts; + int i; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return NULL; + for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) + { + cch = sk_CMS_CertificateChoices_value(*pcerts, i); + if (cch->type == 0) + { + if (!certs) + { + certs = sk_X509_new_null(); + if (!certs) + return NULL; + } + if (!sk_X509_push(certs, cch->d.certificate)) + { + sk_X509_pop_free(certs, X509_free); + return NULL; + } + CRYPTO_add(&cch->d.certificate->references, + 1, CRYPTO_LOCK_X509); + } + } + return certs; + + } + +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) + { + STACK_OF(X509_CRL) *crls = NULL; + STACK_OF(CMS_RevocationInfoChoice) **pcrls; + CMS_RevocationInfoChoice *rch; + int i; + pcrls = cms_get0_revocation_choices(cms); + if (!pcrls) + return NULL; + for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) + { + rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); + if (rch->type == 0) + { + if (!crls) + { + crls = sk_X509_CRL_new_null(); + if (!crls) + return NULL; + } + if (!sk_X509_CRL_push(crls, rch->d.crl)) + { + sk_X509_CRL_pop_free(crls, X509_CRL_free); + return NULL; + } + CRYPTO_add(&rch->d.crl->references, + 1, CRYPTO_LOCK_X509_CRL); + } + } + return crls; + } diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c new file mode 100644 index 000000000000..591bfbec33b2 --- /dev/null +++ b/crypto/cms/cms_sd.c @@ -0,0 +1,1014 @@ +/* crypto/cms/cms_sd.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include "cms_lcl.h" + +/* CMS SignedData Utilities */ + +DECLARE_ASN1_ITEM(CMS_SignedData) + +static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms) + { + if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) + { + CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA); + return NULL; + } + return cms->d.signedData; + } + +static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) + { + if (cms->d.other == NULL) + { + cms->d.signedData = M_ASN1_new_of(CMS_SignedData); + if (!cms->d.signedData) + { + CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE); + return NULL; + } + cms->d.signedData->version = 1; + cms->d.signedData->encapContentInfo->eContentType = + OBJ_nid2obj(NID_pkcs7_data); + cms->d.signedData->encapContentInfo->partial = 1; + ASN1_OBJECT_free(cms->contentType); + cms->contentType = OBJ_nid2obj(NID_pkcs7_signed); + return cms->d.signedData; + } + return cms_get0_signed(cms); + } + +/* Just initialize SignedData e.g. for certs only structure */ + +int CMS_SignedData_init(CMS_ContentInfo *cms) + { + if (cms_signed_data_init(cms)) + return 1; + else + return 0; + } + +/* Check structures and fixup version numbers (if necessary) */ + +static void cms_sd_set_version(CMS_SignedData *sd) + { + int i; + CMS_CertificateChoices *cch; + CMS_RevocationInfoChoice *rch; + CMS_SignerInfo *si; + + for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) + { + cch = sk_CMS_CertificateChoices_value(sd->certificates, i); + if (cch->type == CMS_CERTCHOICE_OTHER) + { + if (sd->version < 5) + sd->version = 5; + } + else if (cch->type == CMS_CERTCHOICE_V2ACERT) + { + if (sd->version < 4) + sd->version = 4; + } + else if (cch->type == CMS_CERTCHOICE_V1ACERT) + { + if (sd->version < 3) + sd->version = 3; + } + } + + for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) + { + rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i); + if (rch->type == CMS_REVCHOICE_OTHER) + { + if (sd->version < 5) + sd->version = 5; + } + } + + if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data) + && (sd->version < 3)) + sd->version = 3; + + for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) + { + si = sk_CMS_SignerInfo_value(sd->signerInfos, i); + if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) + { + if (si->version < 3) + si->version = 3; + if (sd->version < 3) + sd->version = 3; + } + else + sd->version = 1; + } + + if (sd->version < 1) + sd->version = 1; + + } + +/* Copy an existing messageDigest value */ + +static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) + { + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *sitmp; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + ASN1_OCTET_STRING *messageDigest; + sitmp = sk_CMS_SignerInfo_value(sinfos, i); + if (sitmp == si) + continue; + if (CMS_signed_get_attr_count(sitmp) < 0) + continue; + if (OBJ_cmp(si->digestAlgorithm->algorithm, + sitmp->digestAlgorithm->algorithm)) + continue; + messageDigest = CMS_signed_get0_data_by_OBJ(sitmp, + OBJ_nid2obj(NID_pkcs9_messageDigest), + -3, V_ASN1_OCTET_STRING); + if (!messageDigest) + { + CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, + CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); + return 0; + } + + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, + messageDigest, -1)) + return 1; + else + return 0; + } + CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST); + return 0; + } + +int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type) + { + switch(type) + { + case CMS_SIGNERINFO_ISSUER_SERIAL: + sid->d.issuerAndSerialNumber = + M_ASN1_new_of(CMS_IssuerAndSerialNumber); + if (!sid->d.issuerAndSerialNumber) + goto merr; + if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer, + X509_get_issuer_name(cert))) + goto merr; + ASN1_STRING_free(sid->d.issuerAndSerialNumber->serialNumber); + sid->d.issuerAndSerialNumber->serialNumber = + ASN1_STRING_dup(X509_get_serialNumber(cert)); + if(!sid->d.issuerAndSerialNumber->serialNumber) + goto merr; + break; + + case CMS_SIGNERINFO_KEYIDENTIFIER: + if (!cert->skid) + { + CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, + CMS_R_CERTIFICATE_HAS_NO_KEYID); + return 0; + } + sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid); + if (!sid->d.subjectKeyIdentifier) + goto merr; + break; + + default: + CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID); + return 0; + } + + sid->type = type; + + return 1; + + merr: + CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE); + return 0; + + } + +int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno) + { + if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) + { + if (issuer) + *issuer = sid->d.issuerAndSerialNumber->issuer; + if (sno) + *sno = sid->d.issuerAndSerialNumber->serialNumber; + } + else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) + { + if (keyid) + *keyid = sid->d.subjectKeyIdentifier; + } + else + return 0; + return 1; + } + +int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) + { + int ret; + if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) + { + ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer, + X509_get_issuer_name(cert)); + if (ret) + return ret; + return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber, + X509_get_serialNumber(cert)); + } + else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) + { + X509_check_purpose(cert, -1, -1); + if (!cert->skid) + return -1; + return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier, + cert->skid); + } + else + return -1; + } + +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags) + { + CMS_SignedData *sd; + CMS_SignerInfo *si = NULL; + X509_ALGOR *alg; + int i, type; + if(!X509_check_private_key(signer, pk)) + { + CMSerr(CMS_F_CMS_ADD1_SIGNER, + CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + sd = cms_signed_data_init(cms); + if (!sd) + goto err; + si = M_ASN1_new_of(CMS_SignerInfo); + if (!si) + goto merr; + X509_check_purpose(signer, -1, -1); + + CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); + CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); + + si->pkey = pk; + si->signer = signer; + + if (flags & CMS_USE_KEYID) + { + si->version = 3; + if (sd->version < 3) + sd->version = 3; + type = CMS_SIGNERINFO_KEYIDENTIFIER; + } + else + { + type = CMS_SIGNERINFO_ISSUER_SERIAL; + si->version = 1; + } + + if (!cms_set1_SignerIdentifier(si->sid, signer, type)) + goto err; + + /* Since no EVP_PKEY_METHOD in 0.9.8 hard code SHA1 as default */ + if (md == NULL) + md = EVP_sha1(); + + /* OpenSSL 0.9.8 only supports SHA1 with non-RSA keys */ + + if ((pk->type != EVP_PKEY_RSA) && (EVP_MD_type(md) != NID_sha1)) + { + CMSerr(CMS_F_CMS_ADD1_SIGNER, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + } + + cms_DigestAlgorithm_set(si->digestAlgorithm, md); + + /* See if digest is present in digestAlgorithms */ + for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) + { + ASN1_OBJECT *aoid; + alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); + X509_ALGOR_get0(&aoid, NULL, NULL, alg); + if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) + break; + } + + if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) + { + alg = X509_ALGOR_new(); + if (!alg) + goto merr; + cms_DigestAlgorithm_set(alg, md); + if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) + { + X509_ALGOR_free(alg); + goto merr; + } + } + + /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, + * hard code algorithm parameters. + */ + + switch (pk->type) + { + + case EVP_PKEY_RSA: + X509_ALGOR_set0(si->signatureAlgorithm, + OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, 0); + break; + + case EVP_PKEY_DSA: + X509_ALGOR_set0(si->signatureAlgorithm, + OBJ_nid2obj(NID_dsaWithSHA1), + V_ASN1_UNDEF, 0); + break; + + + case EVP_PKEY_EC: + X509_ALGOR_set0(si->signatureAlgorithm, + OBJ_nid2obj(NID_ecdsa_with_SHA1), + V_ASN1_UNDEF, 0); + break; + + default: + CMSerr(CMS_F_CMS_ADD1_SIGNER, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + + } + + if (!(flags & CMS_NOATTR)) + { + /* Initialialize signed attributes strutucture so other + * attributes such as signing time etc are added later + * even if we add none here. + */ + if (!si->signedAttrs) + { + si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); + if (!si->signedAttrs) + goto merr; + } + + if (!(flags & CMS_NOSMIMECAP)) + { + STACK_OF(X509_ALGOR) *smcap = NULL; + i = CMS_add_standard_smimecap(&smcap); + if (i) + i = CMS_add_smimecap(si, smcap); + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + if (!i) + goto merr; + } + if (flags & CMS_REUSE_DIGEST) + { + if (!cms_copy_messageDigest(cms, si)) + goto err; + if (!(flags & CMS_PARTIAL) && + !CMS_SignerInfo_sign(si)) + goto err; + } + } + + if (!(flags & CMS_NOCERTS)) + { + /* NB ignore -1 return for duplicate cert */ + if (!CMS_add1_cert(cms, signer)) + goto merr; + } + + if (!sd->signerInfos) + sd->signerInfos = sk_CMS_SignerInfo_new_null(); + if (!sd->signerInfos || + !sk_CMS_SignerInfo_push(sd->signerInfos, si)) + goto merr; + + return si; + + merr: + CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); + err: + if (si) + M_ASN1_free_of(si, CMS_SignerInfo); + return NULL; + + } + +static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) + { + ASN1_TIME *tt; + int r = 0; + if (t) + tt = t; + else + tt = X509_gmtime_adj(NULL, 0); + + if (!tt) + goto merr; + + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime, + tt->type, tt, -1) <= 0) + goto merr; + + r = 1; + + merr: + + if (!t) + ASN1_TIME_free(tt); + + if (!r) + CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE); + + return r; + + } + +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms) + { + CMS_SignedData *sd; + sd = cms_get0_signed(cms); + if (!sd) + return NULL; + return sd->signerInfos; + } + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms) + { + STACK_OF(X509) *signers = NULL; + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *si; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (si->signer) + { + if (!signers) + { + signers = sk_X509_new_null(); + if (!signers) + return NULL; + } + if (!sk_X509_push(signers, si->signer)) + { + sk_X509_free(signers); + return NULL; + } + } + } + return signers; + } + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer) + { + if (signer) + { + CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); + if (si->pkey) + EVP_PKEY_free(si->pkey); + si->pkey = X509_get_pubkey(signer); + } + if (si->signer) + X509_free(si->signer); + si->signer = signer; + } + +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno) + { + return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno); + } + +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert) + { + return cms_SignerIdentifier_cert_cmp(si->sid, cert); + } + +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts, + unsigned int flags) + { + CMS_SignedData *sd; + CMS_SignerInfo *si; + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) *certs; + X509 *x; + int i, j; + int ret = 0; + sd = cms_get0_signed(cms); + if (!sd) + return -1; + certs = sd->certificates; + for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) + { + si = sk_CMS_SignerInfo_value(sd->signerInfos, i); + if (si->signer) + continue; + + for (j = 0; j < sk_X509_num(scerts); j++) + { + x = sk_X509_value(scerts, j); + if (CMS_SignerInfo_cert_cmp(si, x) == 0) + { + CMS_SignerInfo_set1_signer_cert(si, x); + ret++; + break; + } + } + + if (si->signer || (flags & CMS_NOINTERN)) + continue; + + for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) + { + cch = sk_CMS_CertificateChoices_value(certs, j); + if (cch->type != 0) + continue; + x = cch->d.certificate; + if (CMS_SignerInfo_cert_cmp(si, x) == 0) + { + CMS_SignerInfo_set1_signer_cert(si, x); + ret++; + break; + } + } + } + return ret; + } + +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer, + X509_ALGOR **pdig, X509_ALGOR **psig) + { + if (pk) + *pk = si->pkey; + if (signer) + *signer = si->signer; + if (pdig) + *pdig = si->digestAlgorithm; + if (psig) + *psig = si->signatureAlgorithm; + } + +/* In OpenSSL 0.9.8 we have the link between digest types and public + * key types so we need to fixup the digest type if the public key + * type is not appropriate. + */ + +static void cms_fixup_mctx(EVP_MD_CTX *mctx, EVP_PKEY *pkey) + { + if (EVP_MD_CTX_type(mctx) != NID_sha1) + return; +#ifndef OPENSSL_NO_DSA + if (pkey->type == EVP_PKEY_DSA) + mctx->digest = EVP_dss1(); +#endif +#ifndef OPENSSL_NO_ECDSA + if (pkey->type == EVP_PKEY_EC) + mctx->digest = EVP_ecdsa(); +#endif + } + +static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, + CMS_SignerInfo *si, BIO *chain) + { + EVP_MD_CTX mctx; + int r = 0; + EVP_MD_CTX_init(&mctx); + + + if (!si->pkey) + { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY); + return 0; + } + + if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) + goto err; + + /* If any signed attributes calculate and add messageDigest attribute */ + + if (CMS_signed_get_attr_count(si) >= 0) + { + ASN1_OBJECT *ctype = + cms->d.signedData->encapContentInfo->eContentType; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + EVP_DigestFinal_ex(&mctx, md, &mdlen); + if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, + md, mdlen)) + goto err; + /* Copy content type across */ + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, ctype, -1) <= 0) + goto err; + if (!CMS_SignerInfo_sign(si)) + goto err; + } + else + { + unsigned char *sig; + unsigned int siglen; + sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey)); + if (!sig) + { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, + ERR_R_MALLOC_FAILURE); + goto err; + } + cms_fixup_mctx(&mctx, si->pkey); + if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey)) + { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, + CMS_R_SIGNFINAL_ERROR); + OPENSSL_free(sig); + goto err; + } + ASN1_STRING_set0(si->signature, sig, siglen); + } + + r = 1; + + err: + EVP_MD_CTX_cleanup(&mctx); + return r; + + } + +int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) + { + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *si; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (!cms_SignerInfo_content_sign(cms, si, chain)) + return 0; + } + cms->d.signedData->encapContentInfo->partial = 0; + return 1; + } + +int CMS_SignerInfo_sign(CMS_SignerInfo *si) + { + EVP_MD_CTX mctx; + unsigned char *abuf = NULL; + int alen; + unsigned int siglen; + const EVP_MD *md = NULL; + + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return 0; + + EVP_MD_CTX_init(&mctx); + + if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) + { + if (!cms_add1_signingTime(si, NULL)) + goto err; + } + + if (EVP_SignInit_ex(&mctx, md, NULL) <= 0) + goto err; + +#if 0 + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) + { + CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); + goto err; + } +#endif + + alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf, + ASN1_ITEM_rptr(CMS_Attributes_Sign)); + if(!abuf) + goto err; + if (EVP_SignUpdate(&mctx, abuf, alen) <= 0) + goto err; + siglen = EVP_PKEY_size(si->pkey); + OPENSSL_free(abuf); + abuf = OPENSSL_malloc(siglen); + if(!abuf) + goto err; + cms_fixup_mctx(&mctx, si->pkey); + if (EVP_SignFinal(&mctx, abuf, &siglen, si->pkey) <= 0) + goto err; +#if 0 + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) + { + CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); + goto err; + } +#endif + EVP_MD_CTX_cleanup(&mctx); + + ASN1_STRING_set0(si->signature, abuf, siglen); + + return 1; + + err: + if (abuf) + OPENSSL_free(abuf); + EVP_MD_CTX_cleanup(&mctx); + return 0; + + } + +int CMS_SignerInfo_verify(CMS_SignerInfo *si) + { + EVP_MD_CTX mctx; + unsigned char *abuf = NULL; + int alen, r = -1; + const EVP_MD *md = NULL; + + if (!si->pkey) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY); + return -1; + } + + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return -1; + EVP_MD_CTX_init(&mctx); + if (EVP_VerifyInit_ex(&mctx, md, NULL) <= 0) + goto err; + + alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf, + ASN1_ITEM_rptr(CMS_Attributes_Verify)); + if(!abuf) + goto err; + r = EVP_VerifyUpdate(&mctx, abuf, alen); + OPENSSL_free(abuf); + if (r <= 0) + { + r = -1; + goto err; + } + cms_fixup_mctx(&mctx, si->pkey); + r = EVP_VerifyFinal(&mctx, + si->signature->data, si->signature->length, si->pkey); + if (!r) + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE); + err: + EVP_MD_CTX_cleanup(&mctx); + return r; + } + +/* Create a chain of digest BIOs from a CMS ContentInfo */ + +BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms) + { + int i; + CMS_SignedData *sd; + BIO *chain = NULL; + sd = cms_get0_signed(cms); + if (!sd) + return NULL; + if (cms->d.signedData->encapContentInfo->partial) + cms_sd_set_version(sd); + for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) + { + X509_ALGOR *digestAlgorithm; + BIO *mdbio; + digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i); + mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm); + if (!mdbio) + goto err; + if (chain) + BIO_push(chain, mdbio); + else + chain = mdbio; + } + return chain; + err: + if (chain) + BIO_free_all(chain); + return NULL; + } + +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) + { + ASN1_OCTET_STRING *os = NULL; + EVP_MD_CTX mctx; + int r = -1; + EVP_MD_CTX_init(&mctx); + /* If we have any signed attributes look for messageDigest value */ + if (CMS_signed_get_attr_count(si) >= 0) + { + os = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_pkcs9_messageDigest), + -3, V_ASN1_OCTET_STRING); + if (!os) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); + goto err; + } + } + + if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) + goto err; + + /* If messageDigest found compare it */ + + if (os) + { + unsigned char mval[EVP_MAX_MD_SIZE]; + unsigned int mlen; + if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_UNABLE_TO_FINALIZE_CONTEXT); + goto err; + } + if (mlen != (unsigned int)os->length) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH); + goto err; + } + + if (memcmp(mval, os->data, mlen)) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_VERIFICATION_FAILURE); + r = 0; + } + else + r = 1; + } + else + { + cms_fixup_mctx(&mctx, si->pkey); + r = EVP_VerifyFinal(&mctx, si->signature->data, + si->signature->length, si->pkey); + if (r <= 0) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_VERIFICATION_FAILURE); + r = 0; + } + } + + err: + EVP_MD_CTX_cleanup(&mctx); + return r; + + } + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) + { + unsigned char *smder = NULL; + int smderlen, r; + smderlen = i2d_X509_ALGORS(algs, &smder); + if (smderlen <= 0) + return 0; + r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities, + V_ASN1_SEQUENCE, smder, smderlen); + OPENSSL_free(smder); + return r; + } + +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize) + { + X509_ALGOR *alg; + ASN1_INTEGER *key = NULL; + if (keysize > 0) + { + key = ASN1_INTEGER_new(); + if (!key || !ASN1_INTEGER_set(key, keysize)) + return 0; + } + alg = X509_ALGOR_new(); + if (!alg) + { + if (key) + ASN1_INTEGER_free(key); + return 0; + } + + X509_ALGOR_set0(alg, OBJ_nid2obj(algnid), + key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key); + if (!*algs) + *algs = sk_X509_ALGOR_new_null(); + if (!*algs || !sk_X509_ALGOR_push(*algs, alg)) + { + X509_ALGOR_free(alg); + return 0; + } + return 1; + } + +/* Check to see if a cipher exists and if so add S/MIME capabilities */ + +static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) + { + if (EVP_get_cipherbynid(nid)) + return CMS_add_simple_smimecap(sk, nid, arg); + return 1; + } +#if 0 +static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) + { + if (EVP_get_digestbynid(nid)) + return CMS_add_simple_smimecap(sk, nid, arg); + return 1; + } +#endif +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap) + { + if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64) + || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40)) + return 0; + return 1; + } diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c new file mode 100644 index 000000000000..b35d28d411a3 --- /dev/null +++ b/crypto/cms/cms_smime.c @@ -0,0 +1,808 @@ +/* crypto/cms/cms_smime.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include "cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include "cms_lcl.h" + +static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) + { + unsigned char buf[4096]; + int r = 0, i; + BIO *tmpout = NULL; + + if (out == NULL) + tmpout = BIO_new(BIO_s_null()); + else if (flags & CMS_TEXT) + tmpout = BIO_new(BIO_s_mem()); + else + tmpout = out; + + if(!tmpout) + { + CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Read all content through chain to process digest, decrypt etc */ + for (;;) + { + i=BIO_read(in,buf,sizeof(buf)); + if (i <= 0) + { + if (BIO_method_type(in) == BIO_TYPE_CIPHER) + { + if (!BIO_get_cipher_status(in)) + goto err; + } + if (i < 0) + goto err; + break; + } + + if (tmpout && (BIO_write(tmpout, buf, i) != i)) + goto err; + } + + if(flags & CMS_TEXT) + { + if(!SMIME_text(tmpout, out)) + { + CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR); + goto err; + } + } + + r = 1; + + err: + if (tmpout && (tmpout != out)) + BIO_free(tmpout); + return r; + + } + +static int check_content(CMS_ContentInfo *cms) + { + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos || !*pos) + { + CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT); + return 0; + } + return 1; + } + +static void do_free_upto(BIO *f, BIO *upto) + { + if (upto) + { + BIO *tbio; + do + { + tbio = BIO_pop(f); + BIO_free(f); + f = tbio; + } + while (f != upto); + } + else + BIO_free_all(f); + } + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags) + { + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) + { + CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA); + return 0; + } + cont = CMS_dataInit(cms, NULL); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + BIO_free_all(cont); + return r; + } + +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags) + { + CMS_ContentInfo *cms; + cms = cms_Data_create(); + if (!cms) + return NULL; + + if (CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + + return NULL; + } + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) + { + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) + { + CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + if (r) + r = cms_DigestedData_do_final(cms, cont, 1); + do_free_upto(cont, dcont); + return r; + } + +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags) + { + CMS_ContentInfo *cms; + if (!md) + md = EVP_sha1(); + cms = cms_DigestedData_create(md); + if (!cms) + return NULL; + + if(!(flags & CMS_DETACHED)) + { + flags &= ~CMS_STREAM; + CMS_set_detached(cms, 0); + } + + if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; + } + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags) + { + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, + CMS_R_TYPE_NOT_ENCRYPTED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0) + return 0; + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; + } + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + unsigned int flags) + { + CMS_ContentInfo *cms; + if (!cipher) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER); + return NULL; + } + cms = CMS_ContentInfo_new(); + if (!cms) + return NULL; + if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) + return NULL; + + if(!(flags & CMS_DETACHED)) + { + flags &= ~CMS_STREAM; + CMS_set_detached(cms, 0); + } + + if ((flags & (CMS_STREAM|CMS_PARTIAL)) + || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; + } + +static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, + X509_STORE *store, + STACK_OF(X509) *certs, + STACK_OF(X509_CRL) *crls, + unsigned int flags) + { + X509_STORE_CTX ctx; + X509 *signer; + int i, j, r = 0; + CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); + if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) + { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, + CMS_R_STORE_INIT_ERROR); + goto err; + } + X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_SMIME_SIGN); + if (crls) + X509_STORE_CTX_set0_crls(&ctx, crls); + + i = X509_verify_cert(&ctx); + if (i <= 0) + { + j = X509_STORE_CTX_get_error(&ctx); + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, + CMS_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(j)); + goto err; + } + r = 1; + err: + X509_STORE_CTX_cleanup(&ctx); + return r; + + } + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags) + { + CMS_SignerInfo *si; + STACK_OF(CMS_SignerInfo) *sinfos; + STACK_OF(X509) *cms_certs = NULL; + STACK_OF(X509_CRL) *crls = NULL; + X509 *signer; + int i, scount = 0, ret = 0; + BIO *cmsbio = NULL, *tmpin = NULL; + + if (!dcont && !check_content(cms)) + return 0; + + /* Attempt to find all signer certificates */ + + sinfos = CMS_get0_SignerInfos(cms); + + if (sk_CMS_SignerInfo_num(sinfos) <= 0) + { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS); + goto err; + } + + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); + if (signer) + scount++; + } + + if (scount != sk_CMS_SignerInfo_num(sinfos)) + scount += CMS_set1_signers_certs(cms, certs, flags); + + if (scount != sk_CMS_SignerInfo_num(sinfos)) + { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND); + goto err; + } + + /* Attempt to verify all signers certs */ + + if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) + { + cms_certs = CMS_get1_certs(cms); + if (!(flags & CMS_NOCRL)) + crls = CMS_get1_crls(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (!cms_signerinfo_verify_cert(si, store, + cms_certs, crls, flags)) + goto err; + } + } + + /* Attempt to verify all SignerInfo signed attribute signatures */ + + if (!(flags & CMS_NO_ATTR_VERIFY)) + { + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (CMS_signed_get_attr_count(si) < 0) + continue; + if (CMS_SignerInfo_verify(si) <= 0) + goto err; + } + } + + /* Performance optimization: if the content is a memory BIO then + * store its contents in a temporary read only memory BIO. This + * avoids potentially large numbers of slow copies of data which will + * occur when reading from a read write memory BIO when signatures + * are calculated. + */ + + if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) + { + char *ptr; + long len; + len = BIO_get_mem_data(dcont, &ptr); + tmpin = BIO_new_mem_buf(ptr, len); + if (tmpin == NULL) + { + CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE); + return 0; + } + } + else + tmpin = dcont; + + + cmsbio=CMS_dataInit(cms, tmpin); + if (!cmsbio) + goto err; + + if (!cms_copy_content(out, cmsbio, flags)) + goto err; + + if (!(flags & CMS_NO_CONTENT_VERIFY)) + { + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) + { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (!CMS_SignerInfo_verify_content(si, cmsbio)) + { + CMSerr(CMS_F_CMS_VERIFY, + CMS_R_CONTENT_VERIFY_ERROR); + goto err; + } + } + } + + ret = 1; + + err: + + if (dcont && (tmpin == dcont)) + do_free_upto(cmsbio, dcont); + else + BIO_free_all(cmsbio); + + if (cms_certs) + sk_X509_pop_free(cms_certs, X509_free); + if (crls) + sk_X509_CRL_pop_free(crls, X509_CRL_free); + + return ret; + } + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags) + { + int r; + r = CMS_verify(rcms, certs, store, NULL, NULL, flags); + if (r <= 0) + return r; + return cms_Receipt_verify(rcms, ocms); + } + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, unsigned int flags) + { + CMS_ContentInfo *cms; + int i; + + cms = CMS_ContentInfo_new(); + if (!cms || !CMS_SignedData_init(cms)) + goto merr; + + if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) + { + CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR); + goto err; + } + + for (i = 0; i < sk_X509_num(certs); i++) + { + X509 *x = sk_X509_value(certs, i); + if (!CMS_add1_cert(cms, x)) + goto merr; + } + + if(!(flags & CMS_DETACHED)) + { + flags &= ~CMS_STREAM; + CMS_set_detached(cms, 0); + } + + if ((flags & (CMS_STREAM|CMS_PARTIAL)) + || CMS_final(cms, data, NULL, flags)) + return cms; + else + goto err; + + merr: + CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE); + + err: + if (cms) + CMS_ContentInfo_free(cms); + return NULL; + } + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, + unsigned int flags) + { + CMS_SignerInfo *rct_si; + CMS_ContentInfo *cms = NULL; + ASN1_OCTET_STRING **pos, *os; + BIO *rct_cont = NULL; + int r = 0; + + flags &= ~CMS_STREAM; + /* Not really detached but avoids content being allocated */ + flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED; + if (!pkey || !signcert) + { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT); + return NULL; + } + + /* Initialize signed data */ + + cms = CMS_sign(NULL, NULL, certs, NULL, flags); + if (!cms) + goto err; + + /* Set inner content type to signed receipt */ + if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt))) + goto err; + + rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags); + if (!rct_si) + { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR); + goto err; + } + + os = cms_encode_Receipt(si); + + if (!os) + goto err; + + /* Set content to digest */ + rct_cont = BIO_new_mem_buf(os->data, os->length); + if (!rct_cont) + goto err; + + /* Add msgSigDigest attribute */ + + if (!cms_msgSigDigest_add1(rct_si, si)) + goto err; + + /* Finalize structure */ + if (!CMS_final(cms, rct_cont, NULL, flags)) + goto err; + + /* Set embedded content */ + pos = CMS_get0_content(cms); + *pos = os; + + r = 1; + + err: + if (rct_cont) + BIO_free(rct_cont); + if (r) + return cms; + CMS_ContentInfo_free(cms); + return NULL; + + } + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, + const EVP_CIPHER *cipher, unsigned int flags) + { + CMS_ContentInfo *cms; + int i; + X509 *recip; + cms = CMS_EnvelopedData_create(cipher); + if (!cms) + goto merr; + for (i = 0; i < sk_X509_num(certs); i++) + { + recip = sk_X509_value(certs, i); + if (!CMS_add1_recipient_cert(cms, recip, flags)) + { + CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR); + goto err; + } + } + + if(!(flags & CMS_DETACHED)) + { + flags &= ~CMS_STREAM; + CMS_set_detached(cms, 0); + } + + if ((flags & (CMS_STREAM|CMS_PARTIAL)) + || CMS_final(cms, data, NULL, flags)) + return cms; + else + goto err; + + merr: + CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE); + err: + if (cms) + CMS_ContentInfo_free(cms); + return NULL; + } + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) + { + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + int i, r; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) + { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS) + continue; + /* If we have a cert try matching RecipientInfo + * otherwise try them all. + */ + if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)) + { + CMS_RecipientInfo_set0_pkey(ri, pk); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_pkey(ri, NULL); + if (r > 0) + return 1; + if (cert) + { + CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, + CMS_R_DECRYPT_ERROR); + return 0; + } + ERR_clear_error(); + } + } + + CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + + } + +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen) + { + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + int i, r; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) + { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK) + continue; + + /* If we have an id try matching RecipientInfo + * otherwise try them all. + */ + if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) + { + CMS_RecipientInfo_set0_key(ri, key, keylen); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_key(ri, NULL, 0); + if (r > 0) + return 1; + if (id) + { + CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, + CMS_R_DECRYPT_ERROR); + return 0; + } + ERR_clear_error(); + } + } + + CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + + } + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, + BIO *dcont, BIO *out, + unsigned int flags) + { + int r; + BIO *cont; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) + { + CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); + return 0; + } + if (!dcont && !check_content(cms)) + return 0; + if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) + return 0; + + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; + } + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags) + { + BIO *cmsbio; + int ret = 0; + if (!(cmsbio = CMS_dataInit(cms, dcont))) + { + CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE); + return 0; + } + + SMIME_crlf_copy(data, cmsbio, flags); + + (void)BIO_flush(cmsbio); + + + if (!CMS_dataFinal(cms, cmsbio)) + { + CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR); + goto err; + } + + ret = 1; + + err: + do_free_upto(cmsbio, dcont); + + return ret; + + } + +#ifdef ZLIB + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) + { + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) + { + CMSerr(CMS_F_CMS_UNCOMPRESS, + CMS_R_TYPE_NOT_COMPRESSED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; + } + +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) + { + CMS_ContentInfo *cms; + if (comp_nid <= 0) + comp_nid = NID_zlib_compression; + cms = cms_CompressedData_create(comp_nid); + if (!cms) + return NULL; + + if(!(flags & CMS_DETACHED)) + { + flags &= ~CMS_STREAM; + CMS_set_detached(cms, 0); + } + + if (CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; + } + +#else + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) + { + CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return 0; + } + +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) + { + CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; + } + +#endif diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 43402e75dbf5..0f34597e7042 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -105,6 +105,7 @@ typedef int (*deflateEnd_ft)(z_streamp strm); typedef int (*deflate_ft)(z_streamp strm, int flush); typedef int (*deflateInit__ft)(z_streamp strm, int level, const char * version, int stream_size); +typedef const char * (*zError__ft)(int err); static compress_ft p_compress=NULL; static inflateEnd_ft p_inflateEnd=NULL; static inflate_ft p_inflate=NULL; @@ -112,6 +113,7 @@ static inflateInit__ft p_inflateInit_=NULL; static deflateEnd_ft p_deflateEnd=NULL; static deflate_ft p_deflate=NULL; static deflateInit__ft p_deflateInit_=NULL; +static zError__ft p_zError=NULL; static int zlib_loaded = 0; /* only attempt to init func pts once */ static DSO *zlib_dso = NULL; @@ -123,6 +125,7 @@ static DSO *zlib_dso = NULL; #define deflateEnd p_deflateEnd #define deflate p_deflate #define deflateInit_ p_deflateInit_ +#define zError p_zError #endif /* ZLIB_SHARED */ struct zlib_state @@ -373,10 +376,13 @@ COMP_METHOD *COMP_zlib(void) p_deflateInit_ = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); + p_zError + = (zError__ft) DSO_bind_func(zlib_dso, + "zError"); if (p_compress && p_inflateEnd && p_inflate && p_inflateInit_ && p_deflateEnd - && p_deflate && p_deflateInit_) + && p_deflate && p_deflateInit_ && p_zError) zlib_loaded++; } } @@ -410,3 +416,386 @@ err: return(meth); } +void COMP_zlib_cleanup(void) + { +#ifdef ZLIB_SHARED + if (zlib_dso) + DSO_free(zlib_dso); +#endif + } + +#ifdef ZLIB + +/* Zlib based compression/decompression filter BIO */ + +typedef struct + { + unsigned char *ibuf; /* Input buffer */ + int ibufsize; /* Buffer size */ + z_stream zin; /* Input decompress context */ + unsigned char *obuf; /* Output buffer */ + int obufsize; /* Output buffer size */ + unsigned char *optr; /* Position in output buffer */ + int ocount; /* Amount of data in output buffer */ + int odone; /* deflate EOF */ + int comp_level; /* Compression level to use */ + z_stream zout; /* Output compression context */ + } BIO_ZLIB_CTX; + +#define ZLIB_DEFAULT_BUFSIZE 1024 + +static int bio_zlib_new(BIO *bi); +static int bio_zlib_free(BIO *bi); +static int bio_zlib_read(BIO *b, char *out, int outl); +static int bio_zlib_write(BIO *b, const char *in, int inl); +static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); +static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); + +static BIO_METHOD bio_meth_zlib = + { + BIO_TYPE_COMP, + "zlib", + bio_zlib_write, + bio_zlib_read, + NULL, + NULL, + bio_zlib_ctrl, + bio_zlib_new, + bio_zlib_free, + bio_zlib_callback_ctrl + }; + +BIO_METHOD *BIO_f_zlib(void) + { + return &bio_meth_zlib; + } + + +static int bio_zlib_new(BIO *bi) + { + BIO_ZLIB_CTX *ctx; +#ifdef ZLIB_SHARED + (void)COMP_zlib(); + if (!zlib_loaded) + { + COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); + return 0; + } +#endif + ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX)); + if(!ctx) + { + COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->ibuf = NULL; + ctx->obuf = NULL; + ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; + ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; + ctx->zin.zalloc = Z_NULL; + ctx->zin.zfree = Z_NULL; + ctx->zin.next_in = NULL; + ctx->zin.avail_in = 0; + ctx->zin.next_out = NULL; + ctx->zin.avail_out = 0; + ctx->zout.zalloc = Z_NULL; + ctx->zout.zfree = Z_NULL; + ctx->zout.next_in = NULL; + ctx->zout.avail_in = 0; + ctx->zout.next_out = NULL; + ctx->zout.avail_out = 0; + ctx->odone = 0; + ctx->comp_level = Z_DEFAULT_COMPRESSION; + bi->init = 1; + bi->ptr = (char *)ctx; + bi->flags = 0; + return 1; + } + +static int bio_zlib_free(BIO *bi) + { + BIO_ZLIB_CTX *ctx; + if(!bi) return 0; + ctx = (BIO_ZLIB_CTX *)bi->ptr; + if(ctx->ibuf) + { + /* Destroy decompress context */ + inflateEnd(&ctx->zin); + OPENSSL_free(ctx->ibuf); + } + if(ctx->obuf) + { + /* Destroy compress context */ + deflateEnd(&ctx->zout); + OPENSSL_free(ctx->obuf); + } + OPENSSL_free(ctx); + bi->ptr = NULL; + bi->init = 0; + bi->flags = 0; + return 1; + } + +static int bio_zlib_read(BIO *b, char *out, int outl) + { + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zin; + if(!out || !outl) return 0; + ctx = (BIO_ZLIB_CTX *)b->ptr; + zin = &ctx->zin; + BIO_clear_retry_flags(b); + if(!ctx->ibuf) + { + ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); + if(!ctx->ibuf) + { + COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); + return 0; + } + inflateInit(zin); + zin->next_in = ctx->ibuf; + zin->avail_in = 0; + } + + /* Copy output data directly to supplied buffer */ + zin->next_out = (unsigned char *)out; + zin->avail_out = (unsigned int)outl; + for(;;) + { + /* Decompress while data available */ + while(zin->avail_in) + { + ret = inflate(zin, 0); + if((ret != Z_OK) && (ret != Z_STREAM_END)) + { + COMPerr(COMP_F_BIO_ZLIB_READ, + COMP_R_ZLIB_INFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", + zError(ret)); + return 0; + } + /* If EOF or we've read everything then return */ + if((ret == Z_STREAM_END) || !zin->avail_out) + return outl - zin->avail_out; + } + + /* No data in input buffer try to read some in, + * if an error then return the total data read. + */ + ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); + if(ret <= 0) + { + /* Total data read */ + int tot = outl - zin->avail_out; + BIO_copy_next_retry(b); + if(ret < 0) return (tot > 0) ? tot : ret; + return tot; + } + zin->avail_in = ret; + zin->next_in = ctx->ibuf; + } + } + +static int bio_zlib_write(BIO *b, const char *in, int inl) + { + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zout; + if(!in || !inl) return 0; + ctx = (BIO_ZLIB_CTX *)b->ptr; + if(ctx->odone) return 0; + zout = &ctx->zout; + BIO_clear_retry_flags(b); + if(!ctx->obuf) + { + ctx->obuf = OPENSSL_malloc(ctx->obufsize); + /* Need error here */ + if(!ctx->obuf) + { + COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->optr = ctx->obuf; + ctx->ocount = 0; + deflateInit(zout, ctx->comp_level); + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + } + /* Obtain input data directly from supplied buffer */ + zout->next_in = (void *)in; + zout->avail_in = inl; + for(;;) + { + /* If data in output buffer write it first */ + while(ctx->ocount) { + ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); + if(ret <= 0) + { + /* Total data written */ + int tot = inl - zout->avail_in; + BIO_copy_next_retry(b); + if(ret < 0) return (tot > 0) ? tot : ret; + return tot; + } + ctx->optr += ret; + ctx->ocount -= ret; + } + + /* Have we consumed all supplied data? */ + if(!zout->avail_in) + return inl; + + /* Compress some more */ + + /* Reset buffer */ + ctx->optr = ctx->obuf; + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + /* Compress some more */ + ret = deflate(zout, 0); + if(ret != Z_OK) + { + COMPerr(COMP_F_BIO_ZLIB_WRITE, + COMP_R_ZLIB_DEFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", zError(ret)); + return 0; + } + ctx->ocount = ctx->obufsize - zout->avail_out; + } + } + +static int bio_zlib_flush(BIO *b) + { + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zout; + ctx = (BIO_ZLIB_CTX *)b->ptr; + /* If no data written or already flush show success */ + if(!ctx->obuf || (ctx->odone && !ctx->ocount)) return 1; + zout = &ctx->zout; + BIO_clear_retry_flags(b); + /* No more input data */ + zout->next_in = NULL; + zout->avail_in = 0; + for(;;) + { + /* If data in output buffer write it first */ + while(ctx->ocount) + { + ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); + if(ret <= 0) + { + BIO_copy_next_retry(b); + return ret; + } + ctx->optr += ret; + ctx->ocount -= ret; + } + if(ctx->odone) return 1; + + /* Compress some more */ + + /* Reset buffer */ + ctx->optr = ctx->obuf; + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + /* Compress some more */ + ret = deflate(zout, Z_FINISH); + if(ret == Z_STREAM_END) ctx->odone = 1; + else if(ret != Z_OK) + { + COMPerr(COMP_F_BIO_ZLIB_FLUSH, + COMP_R_ZLIB_DEFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", zError(ret)); + return 0; + } + ctx->ocount = ctx->obufsize - zout->avail_out; + } + } + +static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) + { + BIO_ZLIB_CTX *ctx; + int ret, *ip; + int ibs, obs; + if(!b->next_bio) return 0; + ctx = (BIO_ZLIB_CTX *)b->ptr; + switch (cmd) + { + + case BIO_CTRL_RESET: + ctx->ocount = 0; + ctx->odone = 0; + break; + + case BIO_CTRL_FLUSH: + ret = bio_zlib_flush(b); + if (ret > 0) + ret = BIO_flush(b->next_bio); + break; + + case BIO_C_SET_BUFF_SIZE: + ibs = -1; + obs = -1; + if (ptr != NULL) + { + ip = ptr; + if (*ip == 0) + ibs = (int) num; + else + obs = (int) num; + } + else + { + ibs = (int)num; + obs = ibs; + } + + if (ibs != -1) + { + if (ctx->ibuf) + { + OPENSSL_free(ctx->ibuf); + ctx->ibuf = NULL; + } + ctx->ibufsize = ibs; + } + + if (obs != -1) + { + if (ctx->obuf) + { + OPENSSL_free(ctx->obuf); + ctx->obuf = NULL; + } + ctx->obufsize = obs; + } + + break; + + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + default: + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + } + + return ret; + } + + +static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + if(!b->next_bio) + return 0; + return + BIO_callback_ctrl(b->next_bio, cmd, fp); + } + +#endif diff --git a/crypto/comp/comp.h b/crypto/comp/comp.h index 5d59354a5715..4b405c7d49ef 100644 --- a/crypto/comp/comp.h +++ b/crypto/comp/comp.h @@ -47,6 +47,13 @@ int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, unsigned char *in, int ilen); COMP_METHOD *COMP_rle(void ); COMP_METHOD *COMP_zlib(void ); +void COMP_zlib_cleanup(void); + +#ifdef HEADER_BIO_H +#ifdef ZLIB +BIO_METHOD *BIO_f_zlib(void); +#endif +#endif /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes @@ -57,8 +64,15 @@ void ERR_load_COMP_strings(void); /* Error codes for the COMP functions. */ /* Function codes. */ +#define COMP_F_BIO_ZLIB_FLUSH 99 +#define COMP_F_BIO_ZLIB_NEW 100 +#define COMP_F_BIO_ZLIB_READ 101 +#define COMP_F_BIO_ZLIB_WRITE 102 /* Reason codes. */ +#define COMP_R_ZLIB_DEFLATE_ERROR 99 +#define COMP_R_ZLIB_INFLATE_ERROR 100 +#define COMP_R_ZLIB_NOT_SUPPORTED 101 #ifdef __cplusplus } diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c index 07372226c9d0..187d68b725ca 100644 --- a/crypto/comp/comp_err.c +++ b/crypto/comp/comp_err.c @@ -1,6 +1,6 @@ /* crypto/comp/comp_err.c */ /* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -70,11 +70,18 @@ static ERR_STRING_DATA COMP_str_functs[]= { +{ERR_FUNC(COMP_F_BIO_ZLIB_FLUSH), "BIO_ZLIB_FLUSH"}, +{ERR_FUNC(COMP_F_BIO_ZLIB_NEW), "BIO_ZLIB_NEW"}, +{ERR_FUNC(COMP_F_BIO_ZLIB_READ), "BIO_ZLIB_READ"}, +{ERR_FUNC(COMP_F_BIO_ZLIB_WRITE), "BIO_ZLIB_WRITE"}, {0,NULL} }; static ERR_STRING_DATA COMP_str_reasons[]= { +{ERR_REASON(COMP_R_ZLIB_DEFLATE_ERROR) ,"zlib deflate error"}, +{ERR_REASON(COMP_R_ZLIB_INFLATE_ERROR) ,"zlib inflate error"}, +{ERR_REASON(COMP_R_ZLIB_NOT_SUPPORTED) ,"zlib not supported"}, {0,NULL} }; diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h index 4c073dd83171..8aa06bc5ecbd 100644 --- a/crypto/conf/conf.h +++ b/crypto/conf/conf.h @@ -114,6 +114,7 @@ typedef void conf_finish_func(CONF_IMODULE *md); #define CONF_MFLAGS_SILENT 0x4 #define CONF_MFLAGS_NO_DSO 0x8 #define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +#define CONF_MFLAGS_DEFAULT_SECTION 0x20 int CONF_set_default_method(CONF_METHOD *meth); void CONF_set_nconf(CONF *conf,LHASH *hash); diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c index 0032baa7119b..909d72b4b89a 100644 --- a/crypto/conf/conf_api.c +++ b/crypto/conf/conf_api.c @@ -121,7 +121,7 @@ int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) v = (CONF_VALUE *)lh_insert(conf->data, value); if (v != NULL) { - sk_CONF_VALUE_delete_ptr(ts,v); + (void)sk_CONF_VALUE_delete_ptr(ts,v); OPENSSL_free(v->name); OPENSSL_free(v->value); OPENSSL_free(v); diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c index 587211a59c19..628e8333a6d6 100644 --- a/crypto/conf/conf_mod.c +++ b/crypto/conf/conf_mod.c @@ -126,17 +126,18 @@ int CONF_modules_load(const CONF *cnf, const char *appname, { STACK_OF(CONF_VALUE) *values; CONF_VALUE *vl; - char *vsection; + char *vsection = NULL; int ret, i; if (!cnf) return 1; - if (appname == NULL) - appname = "openssl_conf"; + if (appname) + vsection = NCONF_get_string(cnf, NULL, appname); - vsection = NCONF_get_string(cnf, NULL, appname); + if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION))) + vsection = NCONF_get_string(cnf, NULL, "openssl_conf"); if (!vsection) { @@ -431,7 +432,7 @@ void CONF_modules_unload(int all) if (((md->links > 0) || !md->dso) && !all) continue; /* Since we're working in reverse this is OK */ - sk_CONF_MODULE_delete(supported_modules, i); + (void)sk_CONF_MODULE_delete(supported_modules, i); module_free(md); } if (sk_CONF_MODULE_num(supported_modules) == 0) diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c index e15c2e55463a..9c53bac1a8c1 100644 --- a/crypto/conf/conf_sap.c +++ b/crypto/conf/conf_sap.c @@ -88,8 +88,8 @@ void OPENSSL_config(const char *config_name) ERR_clear_error(); - if (CONF_modules_load_file(NULL, NULL, - CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) + if (CONF_modules_load_file(NULL, config_name, + CONF_MFLAGS_DEFAULT_SECTION|CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { BIO *bio_err; ERR_load_crypto_strings(); diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 86af760d3813..8c686238286c 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -277,7 +277,7 @@ int CRYPTO_get_new_dynlockid(void) else /* If we found a place with a NULL pointer, put our pointer in it. */ - sk_CRYPTO_dynlock_set(dyn_locks,i,pointer); + (void)sk_CRYPTO_dynlock_set(dyn_locks,i,pointer); CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); if (i == -1) @@ -319,7 +319,7 @@ void CRYPTO_destroy_dynlockid(int i) #endif if (pointer->references <= 0) { - sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); + (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); } else pointer = NULL; diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h index 5ceaa964b532..fc249c57f379 100644 --- a/crypto/cryptlib.h +++ b/crypto/cryptlib.h @@ -103,7 +103,6 @@ extern unsigned long OPENSSL_ia32cap_P; void OPENSSL_showfatal(const char *,...); void *OPENSSL_stderr(void); extern int OPENSSL_NONPIC_relocated; -int OPENSSL_isservice(void); #ifdef __cplusplus } diff --git a/crypto/crypto.h b/crypto/crypto.h index d2b5ffe3325b..fe2c1d640342 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -521,6 +521,7 @@ void OpenSSLDie(const char *file,int line,const char *assertion); unsigned long *OPENSSL_ia32cap_loc(void); #define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc())) +int OPENSSL_isservice(void); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/crypto/des/des.h b/crypto/des/des.h index 3cbc2b568e91..92b666359984 100644 --- a/crypto/des/des.h +++ b/crypto/des/des.h @@ -195,9 +195,10 @@ void DES_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out, long length,DES_key_schedule *ks1, DES_key_schedule *ks2,DES_key_schedule *ks3, DES_cblock *ivec,int *num); - +#if 0 void DES_xwhite_in2out(const_DES_cblock *DES_key,const_DES_cblock *in_white, DES_cblock *out_white); +#endif int DES_enc_read(int fd,void *buf,int len,DES_key_schedule *sched, DES_cblock *iv); diff --git a/crypto/des/des_old.c b/crypto/des/des_old.c index 7e4cd7180d18..7c33ed7a9334 100644 --- a/crypto/des/des_old.c +++ b/crypto/des/des_old.c @@ -169,11 +169,13 @@ void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, (DES_key_schedule *)ks3, ivec, num); } +#if 0 /* broken code, preserved just in case anyone specifically looks for this */ void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), _ossl_old_des_cblock (*in_white), _ossl_old_des_cblock (*out_white)) { DES_xwhite_in2out(des_key, in_white, out_white); } +#endif int _ossl_old_des_enc_read(int fd,char *buf,int len,des_key_schedule sched, _ossl_old_des_cblock *iv) diff --git a/crypto/des/des_old.h b/crypto/des/des_old.h index 1b0620c3a2e1..2b2c37235497 100644 --- a/crypto/des/des_old.h +++ b/crypto/des/des_old.h @@ -364,9 +364,10 @@ void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num); - +#if 0 void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), _ossl_old_des_cblock (*in_white), _ossl_old_des_cblock (*out_white)); +#endif int _ossl_old_des_enc_read(int fd,char *buf,int len,_ossl_old_des_key_schedule sched, _ossl_old_des_cblock *iv); diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c index 55efe03f4233..a43ef3c88188 100644 --- a/crypto/des/set_key.c +++ b/crypto/des/set_key.c @@ -115,7 +115,7 @@ int DES_check_key_parity(const_DES_cblock *key) * (and actual cblock values). */ #define NUM_WEAK_KEY 16 -static DES_cblock weak_keys[NUM_WEAK_KEY]={ +static const DES_cblock weak_keys[NUM_WEAK_KEY]={ /* weak keys */ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE}, diff --git a/crypto/des/xcbc_enc.c b/crypto/des/xcbc_enc.c index 47246eb46649..dc0c761b71f7 100644 --- a/crypto/des/xcbc_enc.c +++ b/crypto/des/xcbc_enc.c @@ -60,6 +60,7 @@ /* RSA's DESX */ +#if 0 /* broken code, preserved just in case anyone specifically looks for this */ static unsigned char desx_white_in2out[256]={ 0xBD,0x56,0xEA,0xF2,0xA2,0xF1,0xAC,0x2A,0xB0,0x93,0xD1,0x9C,0x1B,0x33,0xFD,0xD0, 0x30,0x04,0xB6,0xDC,0x7D,0xDF,0x32,0x4B,0xF7,0xCB,0x45,0x9B,0x31,0xBB,0x21,0x5A, @@ -98,7 +99,7 @@ void DES_xwhite_in2out(const_DES_cblock *des_key, const_DES_cblock *in_white, } out0=out[0]; - out1=out[i]; + out1=out[i]; /* BUG: out-of-bounds read */ for (i=0; i<8; i++) { out[i]=in[i]^desx_white_in2out[out0^out1]; @@ -106,6 +107,7 @@ void DES_xwhite_in2out(const_DES_cblock *des_key, const_DES_cblock *in_white, out1=(int)out[i&0x07]; } } +#endif void DES_xcbc_encrypt(const unsigned char *in, unsigned char *out, long length, DES_key_schedule *schedule, diff --git a/crypto/dh/Makefile b/crypto/dh/Makefile index d368e33b4ced..950cad9c5bac 100644 --- a/crypto/dh/Makefile +++ b/crypto/dh/Makefile @@ -123,11 +123,17 @@ dh_key.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h dh_key.o: ../../include/openssl/ossl_typ.h ../../include/openssl/rand.h dh_key.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h dh_key.o: ../../include/openssl/symhacks.h ../cryptlib.h dh_key.c -dh_lib.o: ../../e_os.h ../../include/openssl/bio.h ../../include/openssl/bn.h -dh_lib.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -dh_lib.o: ../../include/openssl/dh.h ../../include/openssl/e_os2.h +dh_lib.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h +dh_lib.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +dh_lib.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h +dh_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +dh_lib.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h dh_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h -dh_lib.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h -dh_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -dh_lib.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h -dh_lib.o: ../../include/openssl/symhacks.h ../cryptlib.h dh_lib.c +dh_lib.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +dh_lib.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +dh_lib.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +dh_lib.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +dh_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +dh_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +dh_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +dh_lib.o: ../cryptlib.h dh_lib.c diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 058aec75bcd9..b8469130045f 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -62,7 +62,7 @@ #include <openssl/dh.h> /* Check that p is a safe prime and - * if g is 2, 3 or 5, check that is is a suitable generator + * if g is 2, 3 or 5, check that it is a suitable generator * where * for 2, p mod 24 == 11 * for 3, p mod 12 == 5 diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index 37a2c1bca23f..e7db440342fa 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -150,7 +150,7 @@ static int generate_key(DH *dh) { BN_init(&local_prk); prk = &local_prk; - BN_with_flags(prk, priv_key, BN_FLG_EXP_CONSTTIME); + BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); } else prk = priv_key; @@ -203,7 +203,7 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) { /* XXX */ - BN_set_flags(dh->priv_key, BN_FLG_EXP_CONSTTIME); + BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); } if (!mont) goto err; diff --git a/crypto/dsa/Makefile b/crypto/dsa/Makefile index 676baf7d49ce..5493f19e85c1 100644 --- a/crypto/dsa/Makefile +++ b/crypto/dsa/Makefile @@ -126,11 +126,16 @@ dsa_lib.o: ../../e_os.h ../../include/openssl/asn1.h dsa_lib.o: ../../include/openssl/bio.h ../../include/openssl/bn.h dsa_lib.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h dsa_lib.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h -dsa_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h -dsa_lib.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +dsa_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +dsa_lib.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +dsa_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dsa_lib.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +dsa_lib.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h dsa_lib.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -dsa_lib.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h +dsa_lib.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +dsa_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h dsa_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +dsa_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h dsa_lib.o: ../cryptlib.h dsa_lib.c dsa_ossl.o: ../../e_os.h ../../include/openssl/asn1.h dsa_ossl.o: ../../include/openssl/bio.h ../../include/openssl/bn.h diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 6a6be3b57537..ca0b86a6cfc0 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -117,13 +117,20 @@ static int dsa_builtin_paramgen(DSA *ret, int bits, if (bits < 512) bits=512; bits=(bits+63)/64*64; - if (seed_len < 20) + /* NB: seed_len == 0 is special case: copy generated seed to + * seed_in if it is not NULL. + */ + if (seed_len && (seed_len < 20)) seed_in = NULL; /* seed buffer too small -- ignore */ if (seed_len > 20) seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED, * but our internal buffers are restricted to 160 bits*/ if ((seed_in != NULL) && (seed_len == 20)) + { memcpy(seed,seed_in,seed_len); + /* set seed_in to NULL to avoid it being copied back */ + seed_in = NULL; + } if ((ctx=BN_CTX_new()) == NULL) goto err; @@ -300,7 +307,7 @@ err: ok=0; goto err; } - if ((m > 1) && (seed_in != NULL)) memcpy(seed_in,seed,20); + if (seed_in != NULL) memcpy(seed_in,seed,20); if (counter_ret != NULL) *counter_ret=counter; if (h_ret != NULL) *h_ret=h; } diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c <index 0423f2e00cd2..c4aa86bc6dce 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c |