aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorSimon L. B. Nielsen <simon@FreeBSD.org>2008-09-21 14:56:30 +0000
committerSimon L. B. Nielsen <simon@FreeBSD.org>2008-09-21 14:56:30 +0000
commitbb1499d2aac1d25a95b8573ff425751f06f159e1 (patch)
treea136b5b2317abe8eb83b021afe5e088230fd67e2 /crypto
parentee266f1253f9cc49430572463d26f72910dfb49e (diff)
downloadsrc-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')
-rw-r--r--crypto/aes/Makefile15
-rw-r--r--crypto/aes/aes.h6
-rw-r--r--crypto/aes/aes_ige.c206
-rw-r--r--crypto/aes/aes_wrap.c259
-rwxr-xr-xcrypto/aes/asm/aes-586.pl12
-rw-r--r--crypto/aes/asm/aes-ia64.S1819
-rwxr-xr-xcrypto/aes/asm/aes-x86_64.pl1578
-rw-r--r--crypto/asn1/Makefile31
-rw-r--r--crypto/asn1/a_object.c1
-rw-r--r--crypto/asn1/a_type.c26
-rw-r--r--crypto/asn1/asn1.h117
-rw-r--r--crypto/asn1/asn1_err.c19
-rw-r--r--crypto/asn1/asn1_lib.c8
-rw-r--r--crypto/asn1/asn1t.h7
-rw-r--r--crypto/asn1/asn_mime.c876
-rw-r--r--crypto/asn1/asn_moid.c2
-rw-r--r--crypto/asn1/t_req.c4
-rw-r--r--crypto/asn1/t_x509.c20
-rw-r--r--crypto/asn1/tasn_dec.c6
-rw-r--r--crypto/asn1/tasn_enc.c4
-rw-r--r--crypto/asn1/tasn_fre.c4
-rw-r--r--crypto/asn1/x_algor.c57
-rw-r--r--crypto/asn1/x_crl.c2
-rw-r--r--crypto/asn1/x_exten.c5
-rw-r--r--crypto/asn1/x_name.c40
-rw-r--r--crypto/bio/b_print.c4
-rw-r--r--crypto/bio/b_sock.c32
-rw-r--r--crypto/bio/bio.h17
-rw-r--r--crypto/bio/bss_dgram.c70
-rw-r--r--crypto/bio/bss_file.c8
-rw-r--r--crypto/bn/Makefile9
-rw-r--r--crypto/bn/asm/ia64.S35
-rwxr-xr-xcrypto/bn/asm/mo-586.pl603
-rwxr-xr-xcrypto/bn/asm/x86_64-mont.pl214
-rw-r--r--crypto/bn/bn.h25
-rw-r--r--crypto/bn/bn_blind.c12
-rw-r--r--crypto/bn/bn_div.c249
-rw-r--r--crypto/bn/bn_err.c4
-rw-r--r--crypto/bn/bn_exp.c20
-rw-r--r--crypto/bn/bn_gcd.c161
-rw-r--r--crypto/bn/bn_gf2m.c6
-rw-r--r--crypto/bn/bn_lcl.h1
-rw-r--r--crypto/bn/bn_lib.c2
-rw-r--r--crypto/bn/bn_mont.c321
-rw-r--r--crypto/bn/bn_mul.c15
-rw-r--r--crypto/bn/bn_nist.c653
-rw-r--r--crypto/bn/bn_prime.c4
-rw-r--r--crypto/bn/bn_prime.h4
-rw-r--r--crypto/bn/bn_prime.pl4
-rw-r--r--crypto/bn/bntest.c60
-rw-r--r--crypto/cms/Makefile183
-rw-r--r--crypto/cms/cms.h473
-rw-r--r--crypto/cms/cms_asn1.c346
-rw-r--r--crypto/cms/cms_att.c195
-rw-r--r--crypto/cms/cms_cd.c134
-rw-r--r--crypto/cms/cms_dd.c148
-rw-r--r--crypto/cms/cms_enc.c262
-rw-r--r--crypto/cms/cms_env.c825
-rw-r--r--crypto/cms/cms_err.c236
-rw-r--r--crypto/cms/cms_ess.c420
-rw-r--r--crypto/cms/cms_io.c140
-rw-r--r--crypto/cms/cms_lcl.h460
-rw-r--r--crypto/cms/cms_lib.c623
-rw-r--r--crypto/cms/cms_sd.c1014
-rw-r--r--crypto/cms/cms_smime.c808
-rw-r--r--crypto/comp/c_zlib.c391
-rw-r--r--crypto/comp/comp.h14
-rw-r--r--crypto/comp/comp_err.c9
-rw-r--r--crypto/conf/conf.h1
-rw-r--r--crypto/conf/conf_api.c2
-rw-r--r--crypto/conf/conf_mod.c11
-rw-r--r--crypto/conf/conf_sap.c4
-rw-r--r--crypto/cryptlib.c4
-rw-r--r--crypto/cryptlib.h1
-rw-r--r--crypto/crypto.h1
-rw-r--r--crypto/des/des.h3
-rw-r--r--crypto/des/des_old.c2
-rw-r--r--crypto/des/des_old.h3
-rw-r--r--crypto/des/set_key.c2
-rw-r--r--crypto/des/xcbc_enc.c4
-rw-r--r--crypto/dh/Makefile20
-rw-r--r--crypto/dh/dh_check.c2
-rw-r--r--crypto/dh/dh_key.c4
-rw-r--r--crypto/dsa/Makefile11
-rw-r--r--crypto/dsa/dsa_gen.c11
-rw-r--r--crypto/dsa/dsa_key.c2
-rw-r--r--crypto/dsa/dsa_ossl.c2
-rw-r--r--crypto/ec/ec.h1
-rw-r--r--crypto/ec/ec_err.c3
-rw-r--r--crypto/ec/ec_mult.c34
-rw-r--r--crypto/ec/ectest.c14
-rw-r--r--crypto/ecdh/Makefile32
-rw-r--r--crypto/ecdh/ecdhtest.c10
-rw-r--r--crypto/ecdsa/Makefile48
-rw-r--r--crypto/ecdsa/ecdsatest.c22
-rw-r--r--crypto/ecdsa/ecs_ossl.c25
-rw-r--r--crypto/engine/Makefile390
-rw-r--r--crypto/engine/eng_all.c3
-rw-r--r--crypto/engine/eng_cnf.c9
-rw-r--r--crypto/engine/eng_err.c3
-rw-r--r--crypto/engine/eng_int.h2
-rw-r--r--crypto/engine/eng_padlock.c5
-rw-r--r--crypto/engine/eng_pkey.c42
-rw-r--r--crypto/engine/eng_table.c12
-rw-r--r--crypto/engine/engine.h16
-rw-r--r--crypto/err/err.c2
-rw-r--r--crypto/err/err.h4
-rw-r--r--crypto/err/err_all.c6
-rw-r--r--crypto/err/openssl.ec2
-rw-r--r--crypto/evp/Makefile66
-rw-r--r--crypto/evp/c_allc.c9
-rw-r--r--crypto/evp/e_seed.c83
-rw-r--r--crypto/evp/evp.h11
-rw-r--r--crypto/evp/evp_enc.c13
-rw-r--r--crypto/evp/evp_locl.h2
-rw-r--r--crypto/evp/evp_test.c7
-rw-r--r--crypto/evp/evptests.txt9
-rw-r--r--crypto/ex_data.c2
-rw-r--r--crypto/hmac/hmac.c7
-rw-r--r--crypto/hmac/hmac.h1
-rw-r--r--crypto/md32_common.h373
-rw-r--r--crypto/md4/md4_dgst.c89
-rw-r--r--crypto/md4/md4_locl.h44
-rw-r--r--crypto/md4/md4test.c6
-rw-r--r--crypto/md5/Makefile18
-rw-r--r--crypto/md5/asm/md5-586.pl2
-rw-r--r--crypto/md5/asm/md5-sparcv9.S1031
-rwxr-xr-xcrypto/md5/asm/md5-x86_64.pl8
-rw-r--r--crypto/md5/md5_dgst.c106
-rw-r--r--crypto/md5/md5_locl.h54
-rw-r--r--crypto/md5/md5test.c6
-rw-r--r--crypto/mem_clr.c12
-rw-r--r--crypto/o_str.c4
-rw-r--r--crypto/objects/Makefile16
-rw-r--r--crypto/objects/obj_dat.c1
-rw-r--r--crypto/objects/obj_dat.h3020
-rw-r--r--crypto/objects/obj_mac.h359
-rw-r--r--crypto/objects/obj_mac.num85
-rw-r--r--crypto/objects/objects.txt131
-rw-r--r--crypto/ocsp/ocsp.h19
-rw-r--r--crypto/ocsp/ocsp_err.c3
-rw-r--r--crypto/ocsp/ocsp_ht.c468
-rw-r--r--crypto/opensslconf.h24
-rw-r--r--crypto/opensslv.h6
-rw-r--r--crypto/ossl_typ.h7
-rw-r--r--crypto/pem/pem.h64
-rw-r--r--crypto/pem/pem_info.c2
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl80
-rw-r--r--crypto/perlasm/x86ms.pl30
-rw-r--r--crypto/perlasm/x86nasm.pl4
-rw-r--r--crypto/perlasm/x86unix.pl42
-rw-r--r--crypto/pkcs12/p12_crt.c26
-rw-r--r--crypto/pkcs7/pk7_mime.c55
-rw-r--r--crypto/pkcs7/pk7_smime.c2
-rw-r--r--crypto/pqueue/pq_compat.h2
-rw-r--r--crypto/rand/Makefile17
-rw-r--r--crypto/rand/rand_nw.c11
-rw-r--r--crypto/rand/randfile.c8
-rw-r--r--crypto/rc4/Makefile4
-rw-r--r--crypto/rc4/asm/rc4-586.pl4
-rw-r--r--crypto/rc4/asm/rc4-ia64.S5
-rwxr-xr-xcrypto/rc4/asm/rc4-x86_64.pl130
-rw-r--r--crypto/rc4/rc4_skey.c9
-rw-r--r--crypto/ripemd/asm/rmd-586.pl4
-rw-r--r--crypto/ripemd/rmd_dgst.c201
-rw-r--r--crypto/ripemd/rmd_locl.h16
-rw-r--r--crypto/ripemd/rmdtest.c6
-rw-r--r--crypto/rsa/Makefile13
-rw-r--r--crypto/rsa/rsa.h18
-rw-r--r--crypto/rsa/rsa_eay.c132
-rw-r--r--crypto/rsa/rsa_gen.c33
-rw-r--r--crypto/rsa/rsa_lib.c14
-rw-r--r--crypto/rsa/rsa_oaep.c23
-rw-r--r--crypto/rsa/rsa_ssl.c2
-rw-r--r--crypto/rsa/rsa_test.c28
-rw-r--r--crypto/seed/Makefile87
-rw-r--r--crypto/seed/seed.c286
-rw-r--r--crypto/seed/seed.h135
-rw-r--r--crypto/seed/seed_cbc.c129
-rw-r--r--crypto/seed/seed_cfb.c144
-rw-r--r--crypto/seed/seed_ecb.c60
-rw-r--r--crypto/seed/seed_locl.h116
-rw-r--r--crypto/seed/seed_ofb.c128
-rw-r--r--crypto/sha/Makefile5
-rw-r--r--crypto/sha/asm/sha1-586.pl433
-rw-r--r--crypto/sha/asm/sha1-ia64.pl346
-rwxr-xr-xcrypto/sha/asm/sha1-x86_64.pl242
-rwxr-xr-xcrypto/sha/asm/sha512-ia64.pl422
-rwxr-xr-xcrypto/sha/asm/sha512-x86_64.pl344
-rw-r--r--crypto/sha/sha1test.c6
-rw-r--r--crypto/sha/sha256.c81
-rw-r--r--crypto/sha/sha512.c103
-rw-r--r--crypto/sha/sha_locl.h278
-rw-r--r--crypto/sha/shatest.c6
-rw-r--r--crypto/stack/safestack.h274
-rw-r--r--crypto/store/str_lib.c2
-rw-r--r--crypto/symhacks.h17
-rw-r--r--crypto/x509/x509.h13
-rw-r--r--crypto/x509/x509_att.c43
-rw-r--r--crypto/x509/x509_txt.c2
-rw-r--r--crypto/x509/x509_vfy.c16
-rw-r--r--crypto/x509/x509_vpm.c2
-rw-r--r--crypto/x509v3/pcy_data.c8
-rw-r--r--crypto/x509v3/pcy_tree.c22
-rw-r--r--crypto/x509v3/v3_addr.c12
-rw-r--r--crypto/x509v3/v3_asid.c2
-rw-r--r--crypto/x509v3/v3_pci.c11
-rw-r--r--crypto/x509v3/v3_purp.c6
-rw-r--r--crypto/x509v3/v3_utl.c24
-rw-r--r--crypto/x509v3/x509v3.h5
-rw-r--r--crypto/x86_64cpuid.pl99
-rw-r--r--crypto/x86cpuid.pl32
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, &param);
+ 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");
+ &not ("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
<