summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2016-04-22 15:02:23 -0400
committerDavid Benjamin <davidben@google.com>2016-04-29 16:36:16 -0400
commit4969cc9b0ab2905ec478277f50ed3849b37a6c6b (patch)
tree552fde383dce1efd213ae145fff808806d76a225 /src/crypto
parent09f2501f7faf115dc26e0c2310b3ea8c97f66007 (diff)
downloadboringssl-4969cc9b0ab2905ec478277f50ed3849b37a6c6b.tar.gz
external/boringssl: Sync to d18cb77.
This includes the following changes which are far too many to list here: https://boringssl.googlesource.com/boringssl/+log/7b8b9c17db93ea5287575b437c77fb36eeb81b31..d18cb77864dcc4b5c7cb08c2331008c01165f34f This also retires one function from android_compat_hacks.c which is no longer necessary. Change-Id: Ie00536d7ad815464b2b031f7bcd1b683e12c1623
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/CMakeLists.txt46
-rw-r--r--src/crypto/aes/asm/aes-armv4.pl5
-rw-r--r--src/crypto/aes/asm/bsaes-armv7.pl8
-rw-r--r--src/crypto/aes/mode_wrappers.c8
-rw-r--r--src/crypto/asn1/CMakeLists.txt12
-rw-r--r--src/crypto/asn1/a_bitstr.c360
-rw-r--r--src/crypto/asn1/a_bool.c86
-rw-r--r--src/crypto/asn1/a_bytes.c481
-rw-r--r--src/crypto/asn1/a_d2i_fp.c380
-rw-r--r--src/crypto/asn1/a_dup.c78
-rw-r--r--src/crypto/asn1/a_enum.c216
-rw-r--r--src/crypto/asn1/a_gentm.c361
-rw-r--r--src/crypto/asn1/a_i2d_fp.c153
-rw-r--r--src/crypto/asn1/a_int.c710
-rw-r--r--src/crypto/asn1/a_mbstr.c525
-rw-r--r--src/crypto/asn1/a_object.c602
-rw-r--r--src/crypto/asn1/a_octet.c19
-rw-r--r--src/crypto/asn1/a_print.c106
-rw-r--r--src/crypto/asn1/a_strnid.c336
-rw-r--r--src/crypto/asn1/a_time.c254
-rw-r--r--src/crypto/asn1/a_type.c165
-rw-r--r--src/crypto/asn1/a_utctm.c501
-rw-r--r--src/crypto/asn1/a_utf8.c294
-rw-r--r--src/crypto/asn1/asn1_lib.c729
-rw-r--r--src/crypto/asn1/asn1_locl.h22
-rw-r--r--src/crypto/asn1/asn1_par.c669
-rw-r--r--src/crypto/asn1/asn1_test.cc81
-rw-r--r--src/crypto/asn1/asn_pack.c59
-rw-r--r--src/crypto/asn1/bio_asn1.c769
-rw-r--r--src/crypto/asn1/bio_ndef.c295
-rw-r--r--src/crypto/asn1/f_enum.c262
-rw-r--r--src/crypto/asn1/f_int.c270
-rw-r--r--src/crypto/asn1/f_string.c258
-rw-r--r--src/crypto/asn1/t_bitst.c59
-rw-r--r--src/crypto/asn1/t_pkey.c112
-rw-r--r--src/crypto/asn1/tasn_dec.c2311
-rw-r--r--src/crypto/asn1/tasn_enc.c1148
-rw-r--r--src/crypto/asn1/tasn_fre.c368
-rw-r--r--src/crypto/asn1/tasn_new.c559
-rw-r--r--src/crypto/asn1/tasn_prn.c970
-rw-r--r--src/crypto/asn1/tasn_typ.c49
-rw-r--r--src/crypto/asn1/x_bignum.c114
-rw-r--r--src/crypto/asn1/x_long.c187
-rw-r--r--src/crypto/base64/base64_test.cc1
-rw-r--r--src/crypto/bio/bio_mem.c5
-rw-r--r--src/crypto/bio/bio_test.cc3
-rw-r--r--src/crypto/bio/buffer.c6
-rw-r--r--src/crypto/bio/connect.c5
-rw-r--r--src/crypto/bio/fd.c2
-rw-r--r--src/crypto/bio/file.c40
-rw-r--r--src/crypto/bio/internal.h3
-rw-r--r--src/crypto/bio/pair.c2
-rw-r--r--src/crypto/bio/socket.c8
-rw-r--r--src/crypto/bn/asm/armv4-mont.pl3
-rwxr-xr-x[-rw-r--r--]src/crypto/bn/asm/rsaz-avx2.pl219
-rwxr-xr-x[-rw-r--r--]src/crypto/bn/asm/rsaz-x86_64.pl375
-rw-r--r--src/crypto/bn/asm/x86_64-gcc.c84
-rwxr-xr-x[-rw-r--r--]src/crypto/bn/asm/x86_64-mont.pl227
-rwxr-xr-x[-rw-r--r--]src/crypto/bn/asm/x86_64-mont5.pl1276
-rw-r--r--src/crypto/bn/bn.c14
-rw-r--r--src/crypto/bn/bn_asn1.c31
-rw-r--r--src/crypto/bn/bn_test.cc28
-rw-r--r--src/crypto/bn/convert.c20
-rw-r--r--src/crypto/bn/div.c212
-rw-r--r--src/crypto/bn/exponentiation.c101
-rw-r--r--src/crypto/bn/generic.c328
-rw-r--r--src/crypto/bn/internal.h85
-rw-r--r--src/crypto/bn/montgomery.c115
-rw-r--r--src/crypto/bn/mul.c35
-rw-r--r--src/crypto/bn/rsaz_exp.c49
-rw-r--r--src/crypto/bytestring/CMakeLists.txt1
-rw-r--r--src/crypto/bytestring/asn1_compat.c51
-rw-r--r--src/crypto/bytestring/ber.c216
-rw-r--r--src/crypto/bytestring/bytestring_test.cc67
-rw-r--r--src/crypto/bytestring/cbs.c20
-rw-r--r--src/crypto/bytestring/internal.h49
-rw-r--r--src/crypto/chacha/CMakeLists.txt44
-rwxr-xr-xsrc/crypto/chacha/asm/chacha-armv4.pl1151
-rwxr-xr-xsrc/crypto/chacha/asm/chacha-armv8.pl1127
-rwxr-xr-xsrc/crypto/chacha/asm/chacha-x86.pl769
-rwxr-xr-xsrc/crypto/chacha/asm/chacha-x86_64.pl1767
-rw-r--r--src/crypto/chacha/chacha.c (renamed from src/crypto/chacha/chacha_generic.c)64
-rw-r--r--src/crypto/chacha/chacha_test.cc257
-rw-r--r--src/crypto/chacha/chacha_vec.c323
-rw-r--r--src/crypto/chacha/chacha_vec_arm.S1447
-rw-r--r--src/crypto/chacha/chacha_vec_arm_generate.go153
-rw-r--r--src/crypto/cipher/aead_test.cc191
-rw-r--r--src/crypto/cipher/cipher.c2
-rw-r--r--src/crypto/cipher/cipher_test.cc43
-rw-r--r--src/crypto/cipher/e_aes.c82
-rw-r--r--src/crypto/cipher/e_chacha20poly1305.c21
-rw-r--r--src/crypto/cipher/e_des.c2
-rw-r--r--src/crypto/cipher/e_null.c2
-rw-r--r--src/crypto/cipher/e_rc2.c2
-rw-r--r--src/crypto/cipher/e_rc4.c2
-rw-r--r--src/crypto/cipher/test/cipher_test.txt16
-rw-r--r--src/crypto/cipher/tls_cbc.c52
-rw-r--r--src/crypto/cmac/cmac_test.cc2
-rw-r--r--src/crypto/conf/conf.c12
-rw-r--r--src/crypto/cpu-aarch64-linux.c61
-rw-r--r--src/crypto/cpu-arm-asm.S32
-rw-r--r--src/crypto/cpu-arm-linux.c360
-rw-r--r--src/crypto/cpu-arm.c161
-rw-r--r--src/crypto/cpu-intel.c6
-rw-r--r--src/crypto/crypto.c10
-rw-r--r--src/crypto/curve25519/CMakeLists.txt10
-rw-r--r--src/crypto/curve25519/asm/x25519-asm-arm.S6
-rw-r--r--src/crypto/curve25519/asm/x25519-asm-x86_64.S6
-rw-r--r--src/crypto/curve25519/curve25519.c532
-rw-r--r--src/crypto/curve25519/internal.h64
-rw-r--r--src/crypto/curve25519/spake25519.c464
-rw-r--r--src/crypto/curve25519/spake25519_test.cc169
-rw-r--r--src/crypto/curve25519/x25519_test.cc6
-rw-r--r--src/crypto/dh/check.c42
-rw-r--r--src/crypto/dh/dh.c19
-rw-r--r--src/crypto/dh/dh_test.cc58
-rw-r--r--src/crypto/digest/digest.c6
-rw-r--r--src/crypto/digest/digest_test.cc1
-rw-r--r--src/crypto/digest/md32_common.h60
-rw-r--r--src/crypto/directory.h66
-rw-r--r--src/crypto/directory_posix.c108
-rw-r--r--src/crypto/directory_win.c144
-rw-r--r--src/crypto/dsa/dsa.c84
-rw-r--r--src/crypto/dsa/dsa_asn1.c317
-rw-r--r--src/crypto/dsa/dsa_test.c2
-rw-r--r--src/crypto/dsa/internal.h78
-rwxr-xr-x[-rw-r--r--]src/crypto/ec/asm/p256-x86_64-asm.pl11
-rw-r--r--src/crypto/ec/ec.c110
-rw-r--r--src/crypto/ec/ec_asn1.c715
-rw-r--r--src/crypto/ec/ec_key.c19
-rw-r--r--src/crypto/ec/ec_montgomery.c137
-rw-r--r--src/crypto/ec/ec_test.cc291
-rw-r--r--src/crypto/ec/example_mul.c4
-rw-r--r--src/crypto/ec/internal.h40
-rw-r--r--src/crypto/ec/oct.c34
-rw-r--r--src/crypto/ec/p224-64.c199
-rw-r--r--src/crypto/ec/p256-64.c285
-rw-r--r--src/crypto/ec/p256-x86_64-table.h7
-rw-r--r--src/crypto/ec/p256-x86_64.c61
-rw-r--r--src/crypto/ec/simple.c333
-rw-r--r--src/crypto/ec/util-64.c74
-rw-r--r--src/crypto/ecdsa/ecdsa.c11
-rw-r--r--src/crypto/ecdsa/ecdsa_asn1.c35
-rw-r--r--src/crypto/ecdsa/ecdsa_test.cc17
-rw-r--r--src/crypto/err/asn1.errordata163
-rw-r--r--src/crypto/err/dsa.errordata3
-rw-r--r--src/crypto/err/ec.errordata3
-rw-r--r--src/crypto/err/err_data_generate.go9
-rw-r--r--src/crypto/err/evp.errordata72
-rw-r--r--src/crypto/err/rsa.errordata92
-rw-r--r--src/crypto/err/ssl.errordata1
-rw-r--r--src/crypto/err/x509.errordata40
-rw-r--r--src/crypto/evp/CMakeLists.txt2
-rw-r--r--src/crypto/evp/evp.c64
-rw-r--r--src/crypto/evp/evp_asn1.c299
-rw-r--r--src/crypto/evp/evp_ctx.c78
-rw-r--r--src/crypto/evp/evp_extra_test.cc446
-rw-r--r--src/crypto/evp/evp_test.cc96
-rw-r--r--src/crypto/evp/evp_tests.txt114
-rw-r--r--src/crypto/evp/internal.h103
-rw-r--r--src/crypto/evp/p_dsa_asn1.c482
-rw-r--r--src/crypto/evp/p_ec.c87
-rw-r--r--src/crypto/evp/p_ec_asn1.c455
-rw-r--r--src/crypto/evp/p_rsa.c103
-rw-r--r--src/crypto/evp/p_rsa_asn1.c643
-rw-r--r--src/crypto/evp/pbkdf_test.cc2
-rw-r--r--src/crypto/evp/print.c527
-rw-r--r--src/crypto/hkdf/hkdf_test.c8
-rw-r--r--src/crypto/hmac/hmac.c11
-rw-r--r--src/crypto/internal.h77
-rw-r--r--src/crypto/md4/md4.c9
-rw-r--r--src/crypto/mem.c4
-rw-r--r--src/crypto/modes/asm/aesni-gcm-x86_64.pl48
-rw-r--r--src/crypto/modes/asm/ghash-armv4.pl5
-rw-r--r--src/crypto/modes/asm/ghash-x86_64.pl5
-rw-r--r--src/crypto/modes/cfb.c11
-rw-r--r--src/crypto/modes/ctr.c31
-rw-r--r--src/crypto/modes/gcm.c94
-rw-r--r--src/crypto/modes/gcm_test.c8
-rw-r--r--src/crypto/modes/internal.h38
-rw-r--r--src/crypto/modes/ofb.c6
-rw-r--r--src/crypto/newhope/CMakeLists.txt22
-rw-r--r--src/crypto/newhope/error_correction.c134
-rw-r--r--src/crypto/newhope/internal.h95
-rw-r--r--src/crypto/newhope/newhope.c160
-rw-r--r--src/crypto/newhope/newhope_test.c144
-rw-r--r--src/crypto/newhope/ntt.c148
-rw-r--r--src/crypto/newhope/poly.c183
-rw-r--r--src/crypto/newhope/precomp.c306
-rw-r--r--src/crypto/newhope/reduce.c42
-rw-r--r--src/crypto/obj/CMakeLists.txt11
-rw-r--r--src/crypto/obj/README12
-rw-r--r--src/crypto/obj/obj_dat.h14
-rw-r--r--src/crypto/obj/obj_dat.pl6
-rw-r--r--src/crypto/obj/obj_mac.num2
-rw-r--r--src/crypto/obj/obj_test.cc106
-rw-r--r--src/crypto/obj/objects.pl40
-rw-r--r--src/crypto/obj/objects.txt2
-rw-r--r--src/crypto/pem/pem_all.c175
-rw-r--r--src/crypto/pem/pem_info.c595
-rw-r--r--src/crypto/pem/pem_lib.c1371
-rw-r--r--src/crypto/pem/pem_oth.c31
-rw-r--r--src/crypto/pem/pem_pk8.c251
-rw-r--r--src/crypto/pem/pem_pkey.c359
-rw-r--r--src/crypto/pem/pem_x509.c6
-rw-r--r--src/crypto/pem/pem_xaux.c9
-rwxr-xr-xsrc/crypto/perlasm/arm-xlate.pl6
-rwxr-xr-xsrc/crypto/perlasm/x86_64-xlate.pl9
-rw-r--r--src/crypto/perlasm/x86gas.pl2
-rw-r--r--src/crypto/pkcs8/CMakeLists.txt2
-rw-r--r--src/crypto/pkcs8/p5_pbe.c1
-rw-r--r--src/crypto/pkcs8/p5_pbev2.c1
-rw-r--r--src/crypto/pkcs8/pkcs12_test.cc3
-rw-r--r--src/crypto/pkcs8/pkcs8.c296
-rwxr-xr-xsrc/crypto/poly1305/asm/poly1305-armv4.pl1216
-rwxr-xr-xsrc/crypto/poly1305/asm/poly1305-armv8.pl925
-rwxr-xr-xsrc/crypto/poly1305/asm/poly1305-x86.pl1788
-rwxr-xr-xsrc/crypto/poly1305/asm/poly1305-x86_64.pl2235
-rw-r--r--src/crypto/poly1305/internal.h40
-rw-r--r--src/crypto/poly1305/poly1305.c17
-rw-r--r--src/crypto/poly1305/poly1305_arm.c5
-rw-r--r--src/crypto/poly1305/poly1305_test.cc69
-rw-r--r--src/crypto/poly1305/poly1305_test.txt107
-rw-r--r--src/crypto/poly1305/poly1305_vec.c104
-rw-r--r--src/crypto/rand/CMakeLists.txt1
-rw-r--r--src/crypto/rand/deterministic.c49
-rw-r--r--src/crypto/rand/rand.c5
-rw-r--r--src/crypto/rand/urandom.c4
-rw-r--r--src/crypto/rand/windows.c4
-rw-r--r--src/crypto/rc4/asm/rc4-586.pl26
-rw-r--r--src/crypto/rsa/blinding.c337
-rw-r--r--src/crypto/rsa/internal.h26
-rw-r--r--src/crypto/rsa/padding.c21
-rw-r--r--src/crypto/rsa/rsa.c30
-rw-r--r--src/crypto/rsa/rsa_asn1.c78
-rw-r--r--src/crypto/rsa/rsa_impl.c279
-rw-r--r--src/crypto/rsa/rsa_test.cc62
-rw-r--r--src/crypto/sha/asm/sha512-armv4.pl2
-rw-r--r--src/crypto/sha/sha256.c4
-rw-r--r--src/crypto/sha/sha512.c4
-rw-r--r--src/crypto/stack/stack.c2
-rw-r--r--src/crypto/test/file_test.cc52
-rw-r--r--src/crypto/test/file_test.h31
-rw-r--r--src/crypto/test/scoped_types.h8
-rw-r--r--src/crypto/test/test_util.h8
-rw-r--r--src/crypto/thread_pthread.c3
-rw-r--r--src/crypto/thread_test.c21
-rw-r--r--src/crypto/thread_win.c84
-rw-r--r--src/crypto/x509/CMakeLists.txt13
-rw-r--r--src/crypto/x509/a_digest.c53
-rw-r--r--src/crypto/x509/a_sign.c129
-rw-r--r--src/crypto/x509/a_strex.c895
-rw-r--r--src/crypto/x509/a_verify.c98
-rw-r--r--src/crypto/x509/algorithm.c (renamed from src/crypto/evp/algorithm.c)90
-rw-r--r--src/crypto/x509/asn1_gen.c1483
-rw-r--r--src/crypto/x509/by_dir.c748
-rw-r--r--src/crypto/x509/by_file.c392
-rw-r--r--src/crypto/x509/charmap.h22
-rw-r--r--src/crypto/x509/i2d_pr.c43
-rw-r--r--src/crypto/x509/internal.h66
-rw-r--r--src/crypto/x509/pkcs7_test.c21
-rw-r--r--src/crypto/x509/rsa_pss.c385
-rw-r--r--src/crypto/x509/t_crl.c101
-rw-r--r--src/crypto/x509/t_x509.c820
-rw-r--r--src/crypto/x509/t_x509a.c86
-rw-r--r--src/crypto/x509/vpm_int.h26
-rw-r--r--src/crypto/x509/x509.c5
-rw-r--r--src/crypto/x509/x509_att.c460
-rw-r--r--src/crypto/x509/x509_cmp.c702
-rw-r--r--src/crypto/x509/x509_d2.c71
-rw-r--r--src/crypto/x509/x509_def.c36
-rw-r--r--src/crypto/x509/x509_ext.c150
-rw-r--r--src/crypto/x509/x509_lu.c1191
-rw-r--r--src/crypto/x509/x509_obj.c219
-rw-r--r--src/crypto/x509/x509_r2x.c80
-rw-r--r--src/crypto/x509/x509_req.c355
-rw-r--r--src/crypto/x509/x509_set.c147
-rw-r--r--src/crypto/x509/x509_test.cc472
-rw-r--r--src/crypto/x509/x509_trs.c364
-rw-r--r--src/crypto/x509/x509_txt.c273
-rw-r--r--src/crypto/x509/x509_v3.c341
-rw-r--r--src/crypto/x509/x509_vfy.c4215
-rw-r--r--src/crypto/x509/x509_vpm.c1008
-rw-r--r--src/crypto/x509/x509cset.c195
-rw-r--r--src/crypto/x509/x509name.c549
-rw-r--r--src/crypto/x509/x509rset.c29
-rw-r--r--src/crypto/x509/x509spki.c122
-rw-r--r--src/crypto/x509/x509type.c118
-rw-r--r--src/crypto/x509/x_algor.c143
-rw-r--r--src/crypto/x509/x_all.c560
-rw-r--r--src/crypto/x509/x_attrib.c78
-rw-r--r--src/crypto/x509/x_crl.c815
-rw-r--r--src/crypto/x509/x_exten.c10
-rw-r--r--src/crypto/x509/x_info.c57
-rw-r--r--src/crypto/x509/x_name.c775
-rw-r--r--src/crypto/x509/x_pkey.c61
-rw-r--r--src/crypto/x509/x_pubkey.c544
-rw-r--r--src/crypto/x509/x_req.c63
-rw-r--r--src/crypto/x509/x_sig.c4
-rw-r--r--src/crypto/x509/x_spki.c16
-rw-r--r--src/crypto/x509/x_val.c4
-rw-r--r--src/crypto/x509/x_x509.c247
-rw-r--r--src/crypto/x509/x_x509a.c190
-rw-r--r--src/crypto/x509v3/ext_dat.h108
-rw-r--r--src/crypto/x509v3/pcy_cache.c413
-rw-r--r--src/crypto/x509v3/pcy_data.c121
-rw-r--r--src/crypto/x509v3/pcy_int.h185
-rw-r--r--src/crypto/x509v3/pcy_lib.c173
-rw-r--r--src/crypto/x509v3/pcy_map.c125
-rw-r--r--src/crypto/x509v3/pcy_node.c225
-rw-r--r--src/crypto/x509v3/pcy_tree.c1400
-rw-r--r--src/crypto/x509v3/tab_test.c68
-rw-r--r--src/crypto/x509v3/v3_akey.c264
-rw-r--r--src/crypto/x509v3/v3_akeya.c13
-rw-r--r--src/crypto/x509v3/v3_alt.c1006
-rw-r--r--src/crypto/x509v3/v3_bcons.c101
-rw-r--r--src/crypto/x509v3/v3_bitst.c134
-rw-r--r--src/crypto/x509v3/v3_conf.c657
-rw-r--r--src/crypto/x509v3/v3_cpols.c697
-rw-r--r--src/crypto/x509v3/v3_crld.c937
-rw-r--r--src/crypto/x509v3/v3_enum.c68
-rw-r--r--src/crypto/x509v3/v3_extku.c129
-rw-r--r--src/crypto/x509v3/v3_genn.c316
-rw-r--r--src/crypto/x509v3/v3_ia5.c88
-rw-r--r--src/crypto/x509v3/v3_info.c236
-rw-r--r--src/crypto/x509v3/v3_int.c56
-rw-r--r--src/crypto/x509v3/v3_lib.c435
-rw-r--r--src/crypto/x509v3/v3_ncons.c734
-rw-r--r--src/crypto/x509v3/v3_pci.c522
-rw-r--r--src/crypto/x509v3/v3_pcia.c17
-rw-r--r--src/crypto/x509v3/v3_pcons.c119
-rw-r--r--src/crypto/x509v3/v3_pku.c69
-rw-r--r--src/crypto/x509v3/v3_pmaps.c146
-rw-r--r--src/crypto/x509v3/v3_prn.c267
-rw-r--r--src/crypto/x509v3/v3_purp.c1233
-rw-r--r--src/crypto/x509v3/v3_skey.c148
-rw-r--r--src/crypto/x509v3/v3_sxnet.c270
-rw-r--r--src/crypto/x509v3/v3_utl.c2141
-rw-r--r--src/crypto/x509v3/v3name_test.c636
339 files changed, 46787 insertions, 35504 deletions
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index 6651f293..3b4413cb 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -22,6 +22,7 @@ elseif(UNIX)
endif()
set(ASM_EXT S)
enable_language(ASM)
+ set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
else()
if (CMAKE_CL_64)
message("Using nasm")
@@ -53,39 +54,6 @@ function(perlasm dest src)
)
endfunction()
-if (${ARCH} STREQUAL "x86_64")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-intel.c
- )
-endif()
-
-if (${ARCH} STREQUAL "x86")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-intel.c
- )
-endif()
-
-if (${ARCH} STREQUAL "arm")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-arm.c
- cpu-arm-asm.S
- )
-endif()
-
-if (${ARCH} STREQUAL "aarch64")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-arm.c
- )
-endif()
-
# Level 0.1 - depends on nothing outside this set.
add_subdirectory(stack)
add_subdirectory(lhash)
@@ -106,6 +74,7 @@ add_subdirectory(conf)
add_subdirectory(chacha)
add_subdirectory(poly1305)
add_subdirectory(curve25519)
+add_subdirectory(newhope)
# Level 1, depends only on 0.*
add_subdirectory(digest)
@@ -143,9 +112,11 @@ add_subdirectory(test)
add_library(
crypto
+ cpu-aarch64-linux.c
+ cpu-arm.c
+ cpu-arm-linux.c
+ cpu-intel.c
crypto.c
- directory_posix.c
- directory_win.c
ex_data.c
mem.c
refcount_c11.c
@@ -156,8 +127,6 @@ add_library(
thread_win.c
time_support.c
- ${CRYPTO_ARCH_SOURCES}
-
$<TARGET_OBJECTS:stack>
$<TARGET_OBJECTS:lhash>
$<TARGET_OBJECTS:err>
@@ -196,7 +165,8 @@ add_library(
$<TARGET_OBJECTS:pem>
$<TARGET_OBJECTS:x509>
$<TARGET_OBJECTS:x509v3>
- $<TARGET_OBJECTS:pkcs8>
+ $<TARGET_OBJECTS:pkcs8_lib>
+ $<TARGET_OBJECTS:newhope>
)
if(NOT MSVC AND NOT ANDROID)
diff --git a/src/crypto/aes/asm/aes-armv4.pl b/src/crypto/aes/asm/aes-armv4.pl
index 882017a6..a60ed4cf 100644
--- a/src/crypto/aes/asm/aes-armv4.pl
+++ b/src/crypto/aes/asm/aes-armv4.pl
@@ -191,7 +191,6 @@ AES_Te:
@ void asm_AES_encrypt(const unsigned char *in, unsigned char *out,
@ const AES_KEY *key) {
.global asm_AES_encrypt
-.hidden asm_AES_encrypt
.type asm_AES_encrypt,%function
.align 5
asm_AES_encrypt:
@@ -441,7 +440,6 @@ _armv4_AES_encrypt:
.size _armv4_AES_encrypt,.-_armv4_AES_encrypt
.global asm_AES_set_encrypt_key
-.hidden asm_AES_set_encrypt_key
.type asm_AES_set_encrypt_key,%function
.align 5
asm_AES_set_encrypt_key:
@@ -748,7 +746,6 @@ _armv4_AES_set_encrypt_key:
.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
.global asm_AES_set_decrypt_key
-.hidden asm_AES_set_decrypt_key
.type asm_AES_set_decrypt_key,%function
.align 5
asm_AES_set_decrypt_key:
@@ -765,7 +762,6 @@ asm_AES_set_decrypt_key:
@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
.global AES_set_enc2dec_key
-.hidden AES_set_enc2dec_key
.type AES_set_enc2dec_key,%function
.align 5
AES_set_enc2dec_key:
@@ -971,7 +967,6 @@ AES_Td:
@ void asm_AES_decrypt(const unsigned char *in, unsigned char *out,
@ const AES_KEY *key) {
.global asm_AES_decrypt
-.hidden asm_AES_decrypt
.type asm_AES_decrypt,%function
.align 5
asm_AES_decrypt:
diff --git a/src/crypto/aes/asm/bsaes-armv7.pl b/src/crypto/aes/asm/bsaes-armv7.pl
index 2617fef7..22362f51 100644
--- a/src/crypto/aes/asm/bsaes-armv7.pl
+++ b/src/crypto/aes/asm/bsaes-armv7.pl
@@ -1006,7 +1006,6 @@ if (0) { # following four functions are unsupported interface
# used for benchmarking...
$code.=<<___;
.globl bsaes_enc_key_convert
-.hidden bsaes_enc_key_convert
.type bsaes_enc_key_convert,%function
.align 4
bsaes_enc_key_convert:
@@ -1025,7 +1024,6 @@ bsaes_enc_key_convert:
.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
.globl bsaes_encrypt_128
-.hidden bsaes_encrypt_128
.type bsaes_encrypt_128,%function
.align 4
bsaes_encrypt_128:
@@ -1056,7 +1054,6 @@ bsaes_encrypt_128:
.size bsaes_encrypt_128,.-bsaes_encrypt_128
.globl bsaes_dec_key_convert
-.hidden bsaes_dec_key_convert
.type bsaes_dec_key_convert,%function
.align 4
bsaes_dec_key_convert:
@@ -1077,7 +1074,6 @@ bsaes_dec_key_convert:
.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
.globl bsaes_decrypt_128
-.hidden bsaes_decrypt_128
.type bsaes_decrypt_128,%function
.align 4
bsaes_decrypt_128:
@@ -1117,7 +1113,6 @@ $code.=<<___;
.extern AES_decrypt
.global bsaes_cbc_encrypt
-.hidden bsaes_cbc_encrypt
.type bsaes_cbc_encrypt,%function
.align 5
bsaes_cbc_encrypt:
@@ -1393,7 +1388,6 @@ my $keysched = "sp";
$code.=<<___;
.extern AES_encrypt
.global bsaes_ctr32_encrypt_blocks
-.hidden bsaes_ctr32_encrypt_blocks
.type bsaes_ctr32_encrypt_blocks,%function
.align 5
bsaes_ctr32_encrypt_blocks:
@@ -1635,7 +1629,6 @@ my @T=@XMM[6..7];
$code.=<<___;
.globl bsaes_xts_encrypt
-.hidden bsaes_xts_encrypt
.type bsaes_xts_encrypt,%function
.align 4
bsaes_xts_encrypt:
@@ -2050,7 +2043,6 @@ $code.=<<___;
.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
.globl bsaes_xts_decrypt
-.hidden bsaes_xts_decrypt
.type bsaes_xts_decrypt,%function
.align 4
bsaes_xts_decrypt:
diff --git a/src/crypto/aes/mode_wrappers.c b/src/crypto/aes/mode_wrappers.c
index dc657dcd..4929920f 100644
--- a/src/crypto/aes/mode_wrappers.c
+++ b/src/crypto/aes/mode_wrappers.c
@@ -96,13 +96,17 @@ void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num) {
- CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+ unsigned num_u = (unsigned)(*num);
+ CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u,
(block128_f)AES_encrypt);
+ *num = (int)num_u;
}
void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num,
int enc) {
- CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+ unsigned num_u = (unsigned)(*num);
+ CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc,
(block128_f)AES_encrypt);
+ *num = (int)num_u;
}
diff --git a/src/crypto/asn1/CMakeLists.txt b/src/crypto/asn1/CMakeLists.txt
index 41e31224..f0667fcd 100644
--- a/src/crypto/asn1/CMakeLists.txt
+++ b/src/crypto/asn1/CMakeLists.txt
@@ -32,7 +32,6 @@ add_library(
f_int.c
f_string.c
t_bitst.c
- t_pkey.c
tasn_dec.c
tasn_enc.c
tasn_fre.c
@@ -43,3 +42,14 @@ add_library(
x_bignum.c
x_long.c
)
+
+add_executable(
+ asn1_test
+
+ asn1_test.cc
+
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(asn1_test crypto)
+add_dependencies(all_tests asn1_test)
diff --git a/src/crypto/asn1/a_bitstr.c b/src/crypto/asn1/a_bitstr.c
index 8bad3394..2705ea56 100644
--- a/src/crypto/asn1/a_bitstr.c
+++ b/src/crypto/asn1/a_bitstr.c
@@ -33,7 +33,7 @@
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
+ * 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
@@ -61,195 +61,203 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
-{ return M_ASN1_BIT_STRING_set(x, d, len); }
+{
+ return M_ASN1_BIT_STRING_set(x, d, len);
+}
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
- {
- int ret,j,bits,len;
- unsigned char *p,*d;
-
- if (a == NULL) return(0);
-
- len=a->length;
-
- if (len > 0)
- {
- if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
- {
- bits=(int)a->flags&0x07;
- }
- else
- {
- for ( ; len > 0; len--)
- {
- if (a->data[len-1]) break;
- }
- j=a->data[len-1];
- if (j & 0x01) bits=0;
- else if (j & 0x02) bits=1;
- else if (j & 0x04) bits=2;
- else if (j & 0x08) bits=3;
- else if (j & 0x10) bits=4;
- else if (j & 0x20) bits=5;
- else if (j & 0x40) bits=6;
- else if (j & 0x80) bits=7;
- else bits=0; /* should not happen */
- }
- }
- else
- bits=0;
-
- ret=1+len;
- if (pp == NULL) return(ret);
-
- p= *pp;
-
- *(p++)=(unsigned char)bits;
- d=a->data;
- memcpy(p,d,len);
- p+=len;
- if (len > 0) p[-1]&=(0xff<<bits);
- *pp=p;
- return(ret);
- }
+{
+ int ret, j, bits, len;
+ unsigned char *p, *d;
+
+ if (a == NULL)
+ return (0);
+
+ len = a->length;
+
+ if (len > 0) {
+ if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
+ bits = (int)a->flags & 0x07;
+ } else {
+ for (; len > 0; len--) {
+ if (a->data[len - 1])
+ break;
+ }
+ j = a->data[len - 1];
+ if (j & 0x01)
+ bits = 0;
+ else if (j & 0x02)
+ bits = 1;
+ else if (j & 0x04)
+ bits = 2;
+ else if (j & 0x08)
+ bits = 3;
+ else if (j & 0x10)
+ bits = 4;
+ else if (j & 0x20)
+ bits = 5;
+ else if (j & 0x40)
+ bits = 6;
+ else if (j & 0x80)
+ bits = 7;
+ else
+ bits = 0; /* should not happen */
+ }
+ } else
+ bits = 0;
+
+ ret = 1 + len;
+ if (pp == NULL)
+ return (ret);
+
+ p = *pp;
+
+ *(p++) = (unsigned char)bits;
+ d = a->data;
+ memcpy(p, d, len);
+ p += len;
+ if (len > 0)
+ p[-1] &= (0xff << bits);
+ *pp = p;
+ return (ret);
+}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
- const unsigned char **pp, long len)
- {
- ASN1_BIT_STRING *ret=NULL;
- const unsigned char *p;
- unsigned char *s;
- int padding;
-
- if (len < 1)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
- goto err;
- }
-
- if ((a == NULL) || ((*a) == NULL))
- {
- if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
- }
- else
- ret=(*a);
-
- p= *pp;
- padding = *(p++);
- if (padding > 7)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
- goto err;
- }
-
- /* We do this to preserve the settings. If we modify
- * the settings, via the _set_bit function, we will recalculate
- * on output */
- ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
- ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
-
- if (len-- > 1) /* using one because of the bits left byte */
- {
- s=(unsigned char *)OPENSSL_malloc((int)len);
- if (s == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memcpy(s,p,(int)len);
- s[len-1]&=(0xff<<padding);
- p+=len;
- }
- else
- s=NULL;
-
- ret->length=(int)len;
- if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->data=s;
- ret->type=V_ASN1_BIT_STRING;
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- M_ASN1_BIT_STRING_free(ret);
- return(NULL);
- }
-
-/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
+ const unsigned char **pp, long len)
+{
+ ASN1_BIT_STRING *ret = NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ int padding;
+
+ if (len < 1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
+ goto err;
+ }
+
+ if ((a == NULL) || ((*a) == NULL)) {
+ if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
+ return (NULL);
+ } else
+ ret = (*a);
+
+ p = *pp;
+ padding = *(p++);
+ if (padding > 7) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ goto err;
+ }
+
+ /*
+ * We do this to preserve the settings. If we modify the settings, via
+ * the _set_bit function, we will recalculate on output
+ */
+ ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
+ ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
+
+ if (len-- > 1) { /* using one because of the bits left byte */
+ s = (unsigned char *)OPENSSL_malloc((int)len);
+ if (s == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(s, p, (int)len);
+ s[len - 1] &= (0xff << padding);
+ p += len;
+ } else
+ s = NULL;
+
+ ret->length = (int)len;
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ ret->data = s;
+ ret->type = V_ASN1_BIT_STRING;
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_BIT_STRING_free(ret);
+ return (NULL);
+}
+
+/*
+ * These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
- {
- int w,v,iv;
- unsigned char *c;
-
- w=n/8;
- v=1<<(7-(n&0x07));
- iv= ~v;
- if (!value) v=0;
-
- if (a == NULL)
- return 0;
-
- a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
-
- if ((a->length < (w+1)) || (a->data == NULL))
- {
- if (!value) return(1); /* Don't need to set */
- if (a->data == NULL)
- c=(unsigned char *)OPENSSL_malloc(w+1);
- else
- c=(unsigned char *)OPENSSL_realloc_clean(a->data,
- a->length,
- w+1);
- if (c == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length);
- a->data=c;
- a->length=w+1;
- }
- a->data[w]=((a->data[w])&iv)|v;
- while ((a->length > 0) && (a->data[a->length-1] == 0))
- a->length--;
- return(1);
- }
+{
+ int w, v, iv;
+ unsigned char *c;
+
+ w = n / 8;
+ v = 1 << (7 - (n & 0x07));
+ iv = ~v;
+ if (!value)
+ v = 0;
+
+ if (a == NULL)
+ return 0;
+
+ a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
+
+ if ((a->length < (w + 1)) || (a->data == NULL)) {
+ if (!value)
+ return (1); /* Don't need to set */
+ if (a->data == NULL)
+ c = (unsigned char *)OPENSSL_malloc(w + 1);
+ else
+ c = (unsigned char *)OPENSSL_realloc_clean(a->data,
+ a->length, w + 1);
+ if (c == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (w + 1 - a->length > 0)
+ memset(c + a->length, 0, w + 1 - a->length);
+ a->data = c;
+ a->length = w + 1;
+ }
+ a->data[w] = ((a->data[w]) & iv) | v;
+ while ((a->length > 0) && (a->data[a->length - 1] == 0))
+ a->length--;
+ return (1);
+}
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
- {
- int w,v;
+{
+ int w, v;
- w=n/8;
- v=1<<(7-(n&0x07));
- if ((a == NULL) || (a->length < (w+1)) || (a->data == NULL))
- return(0);
- return((a->data[w]&v) != 0);
- }
+ w = n / 8;
+ v = 1 << (7 - (n & 0x07));
+ if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
+ return (0);
+ return ((a->data[w] & v) != 0);
+}
/*
- * Checks if the given bit string contains only bits specified by
+ * Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
- unsigned char *flags, int flags_len)
- {
- int i, ok;
- /* Check if there is one bit set at all. */
- if (!a || !a->data) return 1;
-
- /* Check each byte of the internal representation of the bit string. */
- ok = 1;
- for (i = 0; i < a->length && ok; ++i)
- {
- unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
- /* We are done if there is an unneeded bit set. */
- ok = (a->data[i] & mask) == 0;
- }
- return ok;
- }
+ unsigned char *flags, int flags_len)
+{
+ int i, ok;
+ /* Check if there is one bit set at all. */
+ if (!a || !a->data)
+ return 1;
+
+ /*
+ * Check each byte of the internal representation of the bit string.
+ */
+ ok = 1;
+ for (i = 0; i < a->length && ok; ++i) {
+ unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
+ /* We are done if there is an unneeded bit set. */
+ ok = (a->data[i] & mask) == 0;
+ }
+ return ok;
+}
diff --git a/src/crypto/asn1/a_bool.c b/src/crypto/asn1/a_bool.c
index 826bcf43..64a079ec 100644
--- a/src/crypto/asn1/a_bool.c
+++ b/src/crypto/asn1/a_bool.c
@@ -33,7 +33,7 @@
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
+ * 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
@@ -59,54 +59,52 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
- {
- int r;
- unsigned char *p;
+{
+ int r;
+ unsigned char *p;
- r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
- if (pp == NULL) return(r);
- p= *pp;
+ r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
+ if (pp == NULL)
+ return (r);
+ p = *pp;
- ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
- *(p++)= (unsigned char)a;
- *pp=p;
- return(r);
- }
+ ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
+ *(p++) = (unsigned char)a;
+ *pp = p;
+ return (r);
+}
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
- {
- int ret= -1;
- const unsigned char *p;
- long len;
- int inf,tag,xclass;
- int i=0;
+{
+ int ret = -1;
+ const unsigned char *p;
+ long len;
+ int inf, tag, xclass;
+ int i = 0;
- p= *pp;
- inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
- if (inf & 0x80)
- {
- i=ASN1_R_BAD_OBJECT_HEADER;
- goto err;
- }
+ p = *pp;
+ inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (inf & 0x80) {
+ i = ASN1_R_BAD_OBJECT_HEADER;
+ goto err;
+ }
- if (tag != V_ASN1_BOOLEAN)
- {
- i=ASN1_R_EXPECTING_A_BOOLEAN;
- goto err;
- }
+ if (tag != V_ASN1_BOOLEAN) {
+ i = ASN1_R_EXPECTING_A_BOOLEAN;
+ goto err;
+ }
- if (len != 1)
- {
- i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
- goto err;
- }
- ret= (int)*(p++);
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- return(ret);
- }
+ if (len != 1) {
+ i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
+ goto err;
+ }
+ ret = (int)*(p++);
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ return (ret);
+}
diff --git a/src/crypto/asn1/a_bytes.c b/src/crypto/asn1/a_bytes.c
index 19043755..7e2f85dc 100644
--- a/src/crypto/asn1/a_bytes.c
+++ b/src/crypto/asn1/a_bytes.c
@@ -62,256 +62,247 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
-/* type is a 'bitmap' of acceptable string types.
+/*
+ * type is a 'bitmap' of acceptable string types.
*/
ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
- long length, int type)
- {
- ASN1_STRING *ret=NULL;
- const unsigned char *p;
- unsigned char *s;
- long len;
- int inf,tag,xclass;
- int i=0;
-
- p= *pp;
- inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
- if (inf & 0x80) goto err;
-
- if (tag >= 32)
- {
- i=ASN1_R_TAG_VALUE_TOO_HIGH;
- goto err;
- }
- if (!(ASN1_tag2bit(tag) & type))
- {
- i=ASN1_R_WRONG_TYPE;
- goto err;
- }
-
- /* If a bit-string, exit early */
- if (tag == V_ASN1_BIT_STRING)
- return(d2i_ASN1_BIT_STRING(a,pp,length));
-
- if ((a == NULL) || ((*a) == NULL))
- {
- if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
- }
- else
- ret=(*a);
-
- if (len != 0)
- {
- s=(unsigned char *)OPENSSL_malloc((int)len+1);
- if (s == NULL)
- {
- i=ERR_R_MALLOC_FAILURE;
- goto err;
- }
- memcpy(s,p,(int)len);
- s[len]='\0';
- p+=len;
- }
- else
- s=NULL;
-
- if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->length=(int)len;
- ret->data=s;
- ret->type=tag;
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- ASN1_STRING_free(ret);
- return(NULL);
- }
+ long length, int type)
+{
+ ASN1_STRING *ret = NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ long len;
+ int inf, tag, xclass;
+ int i = 0;
+
+ p = *pp;
+ inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (inf & 0x80)
+ goto err;
+
+ if (tag >= 32) {
+ i = ASN1_R_TAG_VALUE_TOO_HIGH;
+ goto err;
+ }
+ if (!(ASN1_tag2bit(tag) & type)) {
+ i = ASN1_R_WRONG_TYPE;
+ goto err;
+ }
+
+ /* If a bit-string, exit early */
+ if (tag == V_ASN1_BIT_STRING)
+ return (d2i_ASN1_BIT_STRING(a, pp, length));
+
+ if ((a == NULL) || ((*a) == NULL)) {
+ if ((ret = ASN1_STRING_new()) == NULL)
+ return (NULL);
+ } else
+ ret = (*a);
+
+ if (len != 0) {
+ s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ if (s == NULL) {
+ i = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ memcpy(s, p, (int)len);
+ s[len] = '\0';
+ p += len;
+ } else
+ s = NULL;
+
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ ret->length = (int)len;
+ ret->data = s;
+ ret->type = tag;
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_STRING_free(ret);
+ return (NULL);
+}
int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
- {
- int ret,r,constructed;
- unsigned char *p;
-
- if (a == NULL) return(0);
-
- if (tag == V_ASN1_BIT_STRING)
- return(i2d_ASN1_BIT_STRING(a,pp));
-
- ret=a->length;
- r=ASN1_object_size(0,ret,tag);
- if (pp == NULL) return(r);
- p= *pp;
-
- if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
- constructed=1;
- else
- constructed=0;
- ASN1_put_object(&p,constructed,ret,tag,xclass);
- memcpy(p,a->data,a->length);
- p+=a->length;
- *pp= p;
- return(r);
- }
+{
+ int ret, r, constructed;
+ unsigned char *p;
+
+ if (a == NULL)
+ return (0);
+
+ if (tag == V_ASN1_BIT_STRING)
+ return (i2d_ASN1_BIT_STRING(a, pp));
+
+ ret = a->length;
+ r = ASN1_object_size(0, ret, tag);
+ if (pp == NULL)
+ return (r);
+ p = *pp;
+
+ if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
+ constructed = 1;
+ else
+ constructed = 0;
+ ASN1_put_object(&p, constructed, ret, tag, xclass);
+ memcpy(p, a->data, a->length);
+ p += a->length;
+ *pp = p;
+ return (r);
+}
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
- long length, int Ptag, int Pclass)
- {
- ASN1_STRING *ret=NULL;
- const unsigned char *p;
- unsigned char *s;
- long len;
- int inf,tag,xclass;
- int i=0;
-
- if ((a == NULL) || ((*a) == NULL))
- {
- if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
- }
- else
- ret=(*a);
-
- p= *pp;
- inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
- if (inf & 0x80)
- {
- i=ASN1_R_BAD_OBJECT_HEADER;
- goto err;
- }
-
- if (tag != Ptag)
- {
- i=ASN1_R_WRONG_TAG;
- goto err;
- }
-
- if (inf & V_ASN1_CONSTRUCTED)
- {
- ASN1_const_CTX c;
-
- c.pp=pp;
- c.p=p;
- c.inf=inf;
- c.slen=len;
- c.tag=Ptag;
- c.xclass=Pclass;
- c.max=(length == 0)?0:(p+length);
- if (!asn1_collate_primitive(ret,&c))
- goto err;
- else
- {
- p=c.p;
- }
- }
- else
- {
- if (len != 0)
- {
- if ((ret->length < len) || (ret->data == NULL))
- {
- if (ret->data != NULL) OPENSSL_free(ret->data);
- s=(unsigned char *)OPENSSL_malloc((int)len + 1);
- if (s == NULL)
- {
- i=ERR_R_MALLOC_FAILURE;
- goto err;
- }
- }
- else
- s=ret->data;
- memcpy(s,p,(int)len);
- s[len] = '\0';
- p+=len;
- }
- else
- {
- s=NULL;
- if (ret->data != NULL) OPENSSL_free(ret->data);
- }
-
- ret->length=(int)len;
- ret->data=s;
- ret->type=Ptag;
- }
-
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- ASN1_STRING_free(ret);
- OPENSSL_PUT_ERROR(ASN1, i);
- return(NULL);
- }
-
-
-/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
- * them into the one structure that is then returned */
-/* There have been a few bug fixes for this function from
- * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
+ long length, int Ptag, int Pclass)
+{
+ ASN1_STRING *ret = NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ long len;
+ int inf, tag, xclass;
+ int i = 0;
+
+ if ((a == NULL) || ((*a) == NULL)) {
+ if ((ret = ASN1_STRING_new()) == NULL)
+ return (NULL);
+ } else
+ ret = (*a);
+
+ p = *pp;
+ inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (inf & 0x80) {
+ i = ASN1_R_BAD_OBJECT_HEADER;
+ goto err;
+ }
+
+ if (tag != Ptag) {
+ i = ASN1_R_WRONG_TAG;
+ goto err;
+ }
+
+ if (inf & V_ASN1_CONSTRUCTED) {
+ ASN1_const_CTX c;
+
+ c.pp = pp;
+ c.p = p;
+ c.inf = inf;
+ c.slen = len;
+ c.tag = Ptag;
+ c.xclass = Pclass;
+ c.max = (length == 0) ? 0 : (p + length);
+ if (!asn1_collate_primitive(ret, &c))
+ goto err;
+ else {
+ p = c.p;
+ }
+ } else {
+ if (len != 0) {
+ if ((ret->length < len) || (ret->data == NULL)) {
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ if (s == NULL) {
+ i = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ } else
+ s = ret->data;
+ memcpy(s, p, (int)len);
+ s[len] = '\0';
+ p += len;
+ } else {
+ s = NULL;
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ }
+
+ ret->length = (int)len;
+ ret->data = s;
+ ret->type = Ptag;
+ }
+
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_STRING_free(ret);
+ OPENSSL_PUT_ERROR(ASN1, i);
+ return (NULL);
+}
+
+/*
+ * We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them
+ * into the one structure that is then returned
+ */
+/*
+ * There have been a few bug fixes for this function from Paul Keogh
+ * <paul.keogh@sse.ie>, many thanks to him
+ */
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
- {
- ASN1_STRING *os=NULL;
- BUF_MEM b;
- int num;
-
- b.length=0;
- b.max=0;
- b.data=NULL;
-
- if (a == NULL)
- {
- c->error=ERR_R_PASSED_NULL_PARAMETER;
- goto err;
- }
-
- num=0;
- for (;;)
- {
- if (c->inf & 1)
- {
- c->eos=ASN1_const_check_infinite_end(&c->p,
- (long)(c->max-c->p));
- if (c->eos) break;
- }
- else
- {
- if (c->slen <= 0) break;
- }
-
- c->q=c->p;
- if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
- == NULL)
- {
- c->error=ERR_R_ASN1_LIB;
- goto err;
- }
-
- if (!BUF_MEM_grow_clean(&b,num+os->length))
- {
- c->error=ERR_R_BUF_LIB;
- goto err;
- }
- memcpy(&(b.data[num]),os->data,os->length);
- if (!(c->inf & 1))
- c->slen-=(c->p-c->q);
- num+=os->length;
- }
-
- if (!asn1_const_Finish(c)) goto err;
-
- a->length=num;
- if (a->data != NULL) OPENSSL_free(a->data);
- a->data=(unsigned char *)b.data;
- if (os != NULL) ASN1_STRING_free(os);
- return(1);
-err:
- OPENSSL_PUT_ERROR(ASN1, c->error);
- if (os != NULL) ASN1_STRING_free(os);
- if (b.data != NULL) OPENSSL_free(b.data);
- return(0);
- }
-
+{
+ ASN1_STRING *os = NULL;
+ BUF_MEM b;
+ int num;
+
+ b.length = 0;
+ b.max = 0;
+ b.data = NULL;
+
+ if (a == NULL) {
+ c->error = ERR_R_PASSED_NULL_PARAMETER;
+ goto err;
+ }
+
+ num = 0;
+ for (;;) {
+ if (c->inf & 1) {
+ c->eos = ASN1_const_check_infinite_end(&c->p,
+ (long)(c->max - c->p));
+ if (c->eos)
+ break;
+ } else {
+ if (c->slen <= 0)
+ break;
+ }
+
+ c->q = c->p;
+ if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
+ == NULL) {
+ c->error = ERR_R_ASN1_LIB;
+ goto err;
+ }
+
+ if (!BUF_MEM_grow_clean(&b, num + os->length)) {
+ c->error = ERR_R_BUF_LIB;
+ goto err;
+ }
+ memcpy(&(b.data[num]), os->data, os->length);
+ if (!(c->inf & 1))
+ c->slen -= (c->p - c->q);
+ num += os->length;
+ }
+
+ if (!asn1_const_Finish(c))
+ goto err;
+
+ a->length = num;
+ if (a->data != NULL)
+ OPENSSL_free(a->data);
+ a->data = (unsigned char *)b.data;
+ if (os != NULL)
+ ASN1_STRING_free(os);
+ return (1);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, c->error);
+ if (os != NULL)
+ ASN1_STRING_free(os);
+ if (b.data != NULL)
+ OPENSSL_free(b.data);
+ return (0);
+}
diff --git a/src/crypto/asn1/a_d2i_fp.c b/src/crypto/asn1/a_d2i_fp.c
index 97ec75b5..b5449719 100644
--- a/src/crypto/asn1/a_d2i_fp.c
+++ b/src/crypto/asn1/a_d2i_fp.c
@@ -62,225 +62,221 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
#ifndef NO_OLD_ASN1
-#ifndef OPENSSL_NO_FP_API
+# ifndef OPENSSL_NO_FP_API
-void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
- {
- BIO *b;
- void *ret;
+void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
+{
+ BIO *b;
+ void *ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return(NULL);
- }
- BIO_set_fp(b,in,BIO_NOCLOSE);
- ret=ASN1_d2i_bio(xnew,d2i,b,x);
- BIO_free(b);
- return(ret);
- }
-#endif
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+ return (NULL);
+ }
+ BIO_set_fp(b, in, BIO_NOCLOSE);
+ ret = ASN1_d2i_bio(xnew, d2i, b, x);
+ BIO_free(b);
+ return (ret);
+}
+# endif
-void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
- {
- BUF_MEM *b = NULL;
- const unsigned char *p;
- void *ret=NULL;
- int len;
+void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
+{
+ BUF_MEM *b = NULL;
+ const unsigned char *p;
+ void *ret = NULL;
+ int len;
- len = asn1_d2i_read_bio(in, &b);
- if(len < 0) goto err;
+ len = asn1_d2i_read_bio(in, &b);
+ if (len < 0)
+ goto err;
- p=(unsigned char *)b->data;
- ret=d2i(x,&p,len);
-err:
- if (b != NULL) BUF_MEM_free(b);
- return(ret);
- }
+ p = (unsigned char *)b->data;
+ ret = d2i(x, &p, len);
+ err:
+ if (b != NULL)
+ BUF_MEM_free(b);
+ return (ret);
+}
#endif
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
- {
- BUF_MEM *b = NULL;
- const unsigned char *p;
- void *ret=NULL;
- int len;
+{
+ BUF_MEM *b = NULL;
+ const unsigned char *p;
+ void *ret = NULL;
+ int len;
- len = asn1_d2i_read_bio(in, &b);
- if(len < 0) goto err;
+ len = asn1_d2i_read_bio(in, &b);
+ if (len < 0)
+ goto err;
- p=(const unsigned char *)b->data;
- ret=ASN1_item_d2i(x,&p,len, it);
-err:
- if (b != NULL) BUF_MEM_free(b);
- return(ret);
- }
+ p = (const unsigned char *)b->data;
+ ret = ASN1_item_d2i(x, &p, len, it);
+ err:
+ if (b != NULL)
+ BUF_MEM_free(b);
+ return (ret);
+}
#ifndef OPENSSL_NO_FP_API
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
- {
- BIO *b;
- char *ret;
+{
+ BIO *b;
+ char *ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return(NULL);
- }
- BIO_set_fp(b,in,BIO_NOCLOSE);
- ret=ASN1_item_d2i_bio(it,b,x);
- BIO_free(b);
- return(ret);
- }
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+ return (NULL);
+ }
+ BIO_set_fp(b, in, BIO_NOCLOSE);
+ ret = ASN1_item_d2i_bio(it, b, x);
+ BIO_free(b);
+ return (ret);
+}
#endif
#define HEADER_SIZE 8
+#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
- {
- BUF_MEM *b;
- unsigned char *p;
- int i;
- ASN1_const_CTX c;
- size_t want=HEADER_SIZE;
- int eos=0;
- size_t off=0;
- size_t len=0;
+{
+ BUF_MEM *b;
+ unsigned char *p;
+ int i;
+ ASN1_const_CTX c;
+ size_t want = HEADER_SIZE;
+ int eos = 0;
+ size_t off = 0;
+ size_t len = 0;
- b=BUF_MEM_new();
- if (b == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return -1;
- }
+ b = BUF_MEM_new();
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
- ERR_clear_error();
- for (;;)
- {
- if (want >= (len-off))
- {
- want-=(len-off);
+ ERR_clear_error();
+ for (;;) {
+ if (want >= (len - off)) {
+ want -= (len - off);
- if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- i=BIO_read(in,&(b->data[len]),want);
- if ((i < 0) && ((len-off) == 0))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
- goto err;
- }
- if (i > 0)
- {
- if (len+i < len)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
- len+=i;
- }
- }
- /* else data already loaded */
+ if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ i = BIO_read(in, &(b->data[len]), want);
+ if ((i < 0) && ((len - off) == 0)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
+ goto err;
+ }
+ if (i > 0) {
+ if (len + i < len) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ len += i;
+ }
+ }
+ /* else data already loaded */
+
+ p = (unsigned char *)&(b->data[off]);
+ c.p = p;
+ c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
+ len - off);
+ if (c.inf & 0x80) {
+ uint32_t e;
- p=(unsigned char *)&(b->data[off]);
- c.p=p;
- c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
- len-off);
- if (c.inf & 0x80)
- {
- uint32_t e;
+ e = ERR_GET_REASON(ERR_peek_error());
+ if (e != ASN1_R_TOO_LONG)
+ goto err;
+ else
+ ERR_clear_error(); /* clear error */
+ }
+ i = c.p - p; /* header length */
+ off += i; /* end of data */
- e=ERR_GET_REASON(ERR_peek_error());
- if (e != ASN1_R_TOO_LONG)
- goto err;
- else
- ERR_clear_error(); /* clear error */
- }
- i=c.p-p;/* header length */
- off+=i; /* end of data */
+ if (c.inf & 1) {
+ /* no data body so go round again */
+ eos++;
+ if (eos < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
+ goto err;
+ }
+ want = HEADER_SIZE;
+ } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
+ /* eos value, so go back and read another header */
+ eos--;
+ if (eos <= 0)
+ break;
+ else
+ want = HEADER_SIZE;
+ } else {
+ /* suck in c.slen bytes of data */
+ want = c.slen;
+ if (want > (len - off)) {
+ size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
+ want -= (len - off);
+ if (want > INT_MAX /* BIO_read takes an int length */ ||
+ len + want < len) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ while (want > 0) {
+ /*
+ * Read content in chunks of increasing size
+ * so we can return an error for EOF without
+ * having to allocate the entire content length
+ * in one go.
+ */
+ size_t chunk = want > chunk_max ? chunk_max : want;
- if (c.inf & 1)
- {
- /* no data body so go round again */
- eos++;
- if (eos < 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
- goto err;
- }
- want=HEADER_SIZE;
- }
- else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
- {
- /* eos value, so go back and read another header */
- eos--;
- if (eos <= 0)
- break;
- else
- want=HEADER_SIZE;
- }
- else
- {
- /* suck in c.slen bytes of data */
- want=c.slen;
- if (want > (len-off))
- {
- want-=(len-off);
- if (want > INT_MAX /* BIO_read takes an int length */ ||
- len+want < len)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
- if (!BUF_MEM_grow_clean(b,len+want))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- while (want > 0)
- {
- i=BIO_read(in,&(b->data[len]),want);
- if (i <= 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
- goto err;
- }
- /* This can't overflow because
- * |len+want| didn't overflow. */
- len+=i;
- want-=i;
- }
- }
- if (off + c.slen < off)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
- off+=c.slen;
- if (eos <= 0)
- {
- break;
- }
- else
- want=HEADER_SIZE;
- }
- }
+ if (!BUF_MEM_grow_clean(b, len + chunk)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ want -= chunk;
+ while (chunk > 0) {
+ i = BIO_read(in, &(b->data[len]), chunk);
+ if (i <= 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
+ goto err;
+ }
+ /*
+ * This can't overflow because |len+want| didn't
+ * overflow.
+ */
+ len += i;
+ chunk -= i;
+ }
+ if (chunk_max < INT_MAX/2)
+ chunk_max *= 2;
+ }
+ }
+ if (off + c.slen < off) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ off += c.slen;
+ if (eos <= 0) {
+ break;
+ } else
+ want = HEADER_SIZE;
+ }
+ }
- if (off > INT_MAX)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
+ if (off > INT_MAX) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ goto err;
+ }
- *pb = b;
- return off;
-err:
- if (b != NULL) BUF_MEM_free(b);
- return -1;
- }
+ *pb = b;
+ return off;
+ err:
+ if (b != NULL)
+ BUF_MEM_free(b);
+ return -1;
+}
diff --git a/src/crypto/asn1/a_dup.c b/src/crypto/asn1/a_dup.c
index 5e87457c..57394f58 100644
--- a/src/crypto/asn1/a_dup.c
+++ b/src/crypto/asn1/a_dup.c
@@ -59,45 +59,53 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
- {
- unsigned char *b,*p;
- const unsigned char *p2;
- int i;
- char *ret;
+{
+ unsigned char *b, *p;
+ const unsigned char *p2;
+ int i;
+ char *ret;
- if (x == NULL) return(NULL);
+ if (x == NULL)
+ return (NULL);
- i=i2d(x,NULL);
- b=OPENSSL_malloc(i+10);
- if (b == NULL)
- { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
- p= b;
- i=i2d(x,&p);
- p2= b;
- ret=d2i(NULL,&p2,i);
- OPENSSL_free(b);
- return(ret);
- }
+ i = i2d(x, NULL);
+ b = OPENSSL_malloc(i + 10);
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ p = b;
+ i = i2d(x, &p);
+ p2 = b;
+ ret = d2i(NULL, &p2, i);
+ OPENSSL_free(b);
+ return (ret);
+}
-/* ASN1_ITEM version of dup: this follows the model above except we don't need
- * to allocate the buffer. At some point this could be rewritten to directly dup
- * the underlying structure instead of doing and encode and decode. */
+/*
+ * ASN1_ITEM version of dup: this follows the model above except we don't
+ * need to allocate the buffer. At some point this could be rewritten to
+ * directly dup the underlying structure instead of doing and encode and
+ * decode.
+ */
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
- {
- unsigned char *b = NULL;
- const unsigned char *p;
- long i;
- void *ret;
+{
+ unsigned char *b = NULL;
+ const unsigned char *p;
+ long i;
+ void *ret;
- if (x == NULL) return(NULL);
+ if (x == NULL)
+ return (NULL);
- i=ASN1_item_i2d(x,&b,it);
- if (b == NULL)
- { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
- p= b;
- ret=ASN1_item_d2i(NULL,&p,i, it);
- OPENSSL_free(b);
- return(ret);
- }
+ i = ASN1_item_i2d(x, &b, it);
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ p = b;
+ ret = ASN1_item_d2i(NULL, &p, i, it);
+ OPENSSL_free(b);
+ return (ret);
+}
diff --git a/src/crypto/asn1/a_enum.c b/src/crypto/asn1/a_enum.c
index 579dafd3..0b95fc95 100644
--- a/src/crypto/asn1/a_enum.c
+++ b/src/crypto/asn1/a_enum.c
@@ -61,123 +61,121 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
-/*
+/*
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
* for comments on encoding see a_int.c
*/
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
- {
- int j,k;
- unsigned int i;
- unsigned char buf[sizeof(long)+1];
- long d;
-
- a->type=V_ASN1_ENUMERATED;
- if (a->length < (int)(sizeof(long)+1))
- {
- if (a->data != NULL)
- OPENSSL_free(a->data);
- if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
- memset((char *)a->data,0,sizeof(long)+1);
- }
- if (a->data == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(0);
- }
- d=v;
- if (d < 0)
- {
- d= -d;
- a->type=V_ASN1_NEG_ENUMERATED;
- }
-
- for (i=0; i<sizeof(long); i++)
- {
- if (d == 0) break;
- buf[i]=(int)d&0xff;
- d>>=8;
- }
- j=0;
- for (k=i-1; k >=0; k--)
- a->data[j++]=buf[k];
- a->length=j;
- return(1);
- }
+{
+ int j, k;
+ unsigned int i;
+ unsigned char buf[sizeof(long) + 1];
+ long d;
+
+ a->type = V_ASN1_ENUMERATED;
+ if (a->length < (int)(sizeof(long) + 1)) {
+ if (a->data != NULL)
+ OPENSSL_free(a->data);
+ if ((a->data =
+ (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
+ memset((char *)a->data, 0, sizeof(long) + 1);
+ }
+ if (a->data == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ d = v;
+ if (d < 0) {
+ d = -d;
+ a->type = V_ASN1_NEG_ENUMERATED;
+ }
+
+ for (i = 0; i < sizeof(long); i++) {
+ if (d == 0)
+ break;
+ buf[i] = (int)d & 0xff;
+ d >>= 8;
+ }
+ j = 0;
+ for (k = i - 1; k >= 0; k--)
+ a->data[j++] = buf[k];
+ a->length = j;
+ return (1);
+}
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
- {
- int neg=0,i;
- long r=0;
-
- if (a == NULL) return(0L);
- i=a->type;
- if (i == V_ASN1_NEG_ENUMERATED)
- neg=1;
- else if (i != V_ASN1_ENUMERATED)
- return -1;
-
- if (a->length > (int)sizeof(long))
- {
- /* hmm... a bit ugly */
- return(0xffffffffL);
- }
- if (a->data == NULL)
- return 0;
-
- for (i=0; i<a->length; i++)
- {
- r<<=8;
- r|=(unsigned char)a->data[i];
- }
- if (neg) r= -r;
- return(r);
- }
+{
+ int neg = 0, i;
+ long r = 0;
+
+ if (a == NULL)
+ return (0L);
+ i = a->type;
+ if (i == V_ASN1_NEG_ENUMERATED)
+ neg = 1;
+ else if (i != V_ASN1_ENUMERATED)
+ return -1;
+
+ if (a->length > (int)sizeof(long)) {
+ /* hmm... a bit ugly */
+ return (0xffffffffL);
+ }
+ if (a->data == NULL)
+ return 0;
+
+ for (i = 0; i < a->length; i++) {
+ r <<= 8;
+ r |= (unsigned char)a->data[i];
+ }
+ if (neg)
+ r = -r;
+ return (r);
+}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
- {
- ASN1_ENUMERATED *ret;
- int len,j;
-
- if (ai == NULL)
- ret=M_ASN1_ENUMERATED_new();
- else
- ret=ai;
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
- else ret->type=V_ASN1_ENUMERATED;
- j=BN_num_bits(bn);
- len=((j == 0)?0:((j/8)+1));
- if (ret->length < len+4)
- {
- unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
- if (!new_data)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ret->data=new_data;
- }
-
- ret->length=BN_bn2bin(bn,ret->data);
- return(ret);
-err:
- if (ret != ai) M_ASN1_ENUMERATED_free(ret);
- return(NULL);
- }
+{
+ ASN1_ENUMERATED *ret;
+ int len, j;
+
+ if (ai == NULL)
+ ret = M_ASN1_ENUMERATED_new();
+ else
+ ret = ai;
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ if (BN_is_negative(bn))
+ ret->type = V_ASN1_NEG_ENUMERATED;
+ else
+ ret->type = V_ASN1_ENUMERATED;
+ j = BN_num_bits(bn);
+ len = ((j == 0) ? 0 : ((j / 8) + 1));
+ if (ret->length < len + 4) {
+ unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
+ if (!new_data) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ret->data = new_data;
+ }
+
+ ret->length = BN_bn2bin(bn, ret->data);
+ return (ret);
+ err:
+ if (ret != ai)
+ M_ASN1_ENUMERATED_free(ret);
+ return (NULL);
+}
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
- {
- BIGNUM *ret;
-
- if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
- else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
- return(ret);
- }
+{
+ BIGNUM *ret;
+
+ if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
+ else if (ai->type == V_ASN1_NEG_ENUMERATED)
+ BN_set_negative(ret, 1);
+ return (ret);
+}
diff --git a/src/crypto/asn1/a_gentm.c b/src/crypto/asn1/a_gentm.c
index 7cb18a95..ee6b3db5 100644
--- a/src/crypto/asn1/a_gentm.c
+++ b/src/crypto/asn1/a_gentm.c
@@ -63,193 +63,194 @@
#include <openssl/mem.h>
#include <openssl/time_support.h>
+#include "asn1_locl.h"
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
- {
- static const int min[9]={ 0, 0, 1, 1, 0, 0, 0, 0, 0};
- static const int max[9]={99, 99,12,31,23,59,59,12,59};
- char *a;
- int n,i,l,o;
-
- if (d->type != V_ASN1_GENERALIZEDTIME) return(0);
- l=d->length;
- a=(char *)d->data;
- o=0;
- /* GENERALIZEDTIME is similar to UTCTIME except the year is
- * represented as YYYY. This stuff treats everything as a two digit
- * field so make first two fields 00 to 99
- */
- if (l < 13) goto err;
- for (i=0; i<7; i++)
- {
- if ((i == 6) && ((a[o] == 'Z') ||
- (a[o] == '+') || (a[o] == '-')))
- {
- i++;
- if (tm)
- tm->tm_sec = 0;
- break;
- }
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n= a[o]-'0';
- if (++o > l) goto err;
-
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n=(n*10)+ a[o]-'0';
- if (++o > l) goto err;
-
- if ((n < min[i]) || (n > max[i])) goto err;
- if (tm)
- {
- switch(i)
- {
- case 0:
- tm->tm_year = n * 100 - 1900;
- break;
- case 1:
- tm->tm_year += n;
- break;
- case 2:
- tm->tm_mon = n - 1;
- break;
- case 3:
- tm->tm_mday = n;
- break;
- case 4:
- tm->tm_hour = n;
- break;
- case 5:
- tm->tm_min = n;
- break;
- case 6:
- tm->tm_sec = n;
- break;
- }
- }
- }
- /* Optional fractional seconds: decimal point followed by one
- * or more digits.
- */
- if (a[o] == '.')
- {
- if (++o > l) goto err;
- i = o;
- while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
- o++;
- /* Must have at least one digit after decimal point */
- if (i == o) goto err;
- }
-
- if (a[o] == 'Z')
- o++;
- else if ((a[o] == '+') || (a[o] == '-'))
- {
- int offsign = a[o] == '-' ? -1 : 1, offset = 0;
- o++;
- if (o+4 > l) goto err;
- for (i=7; i<9; i++)
- {
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n= a[o]-'0';
- o++;
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n=(n*10)+ a[o]-'0';
- if ((n < min[i]) || (n > max[i])) goto err;
- if (tm)
- {
- if (i == 7)
- offset = n * 3600;
- else if (i == 8)
- offset += n * 60;
- }
- o++;
- }
- if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
- return 0;
- }
- else if (a[o])
- {
- /* Missing time zone information. */
- goto err;
- }
- return(o == l);
-err:
- return(0);
- }
+{
+ static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
+ static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
+ char *a;
+ int n, i, l, o;
+
+ if (d->type != V_ASN1_GENERALIZEDTIME)
+ return (0);
+ l = d->length;
+ a = (char *)d->data;
+ o = 0;
+ /*
+ * GENERALIZEDTIME is similar to UTCTIME except the year is represented
+ * as YYYY. This stuff treats everything as a two digit field so make
+ * first two fields 00 to 99
+ */
+ if (l < 13)
+ goto err;
+ for (i = 0; i < 7; i++) {
+ if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
+ i++;
+ if (tm)
+ tm->tm_sec = 0;
+ break;
+ }
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = a[o] - '0';
+ if (++o > l)
+ goto err;
+
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = (n * 10) + a[o] - '0';
+ if (++o > l)
+ goto err;
+
+ if ((n < min[i]) || (n > max[i]))
+ goto err;
+ if (tm) {
+ switch (i) {
+ case 0:
+ tm->tm_year = n * 100 - 1900;
+ break;
+ case 1:
+ tm->tm_year += n;
+ break;
+ case 2:
+ tm->tm_mon = n - 1;
+ break;
+ case 3:
+ tm->tm_mday = n;
+ break;
+ case 4:
+ tm->tm_hour = n;
+ break;
+ case 5:
+ tm->tm_min = n;
+ break;
+ case 6:
+ tm->tm_sec = n;
+ break;
+ }
+ }
+ }
+ /*
+ * Optional fractional seconds: decimal point followed by one or more
+ * digits.
+ */
+ if (a[o] == '.') {
+ if (++o > l)
+ goto err;
+ i = o;
+ while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
+ o++;
+ /* Must have at least one digit after decimal point */
+ if (i == o)
+ goto err;
+ }
+
+ if (a[o] == 'Z')
+ o++;
+ else if ((a[o] == '+') || (a[o] == '-')) {
+ int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+ o++;
+ if (o + 4 > l)
+ goto err;
+ for (i = 7; i < 9; i++) {
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = a[o] - '0';
+ o++;
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = (n * 10) + a[o] - '0';
+ if ((n < min[i]) || (n > max[i]))
+ goto err;
+ if (tm) {
+ if (i == 7)
+ offset = n * 3600;
+ else if (i == 8)
+ offset += n * 60;
+ }
+ o++;
+ }
+ if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+ return 0;
+ } else if (a[o]) {
+ /* Missing time zone information. */
+ goto err;
+ }
+ return (o == l);
+ err:
+ return (0);
+}
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
- {
- return asn1_generalizedtime_to_tm(NULL, d);
- }
+{
+ return asn1_generalizedtime_to_tm(NULL, d);
+}
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
- {
- ASN1_GENERALIZEDTIME t;
-
- t.type=V_ASN1_GENERALIZEDTIME;
- t.length=strlen(str);
- t.data=(unsigned char *)str;
- if (ASN1_GENERALIZEDTIME_check(&t))
- {
- if (s != NULL)
- {
- if (!ASN1_STRING_set((ASN1_STRING *)s,
- (unsigned char *)str,t.length))
- return 0;
- s->type=V_ASN1_GENERALIZEDTIME;
- }
- return(1);
- }
- else
- return(0);
- }
+{
+ ASN1_GENERALIZEDTIME t;
+
+ t.type = V_ASN1_GENERALIZEDTIME;
+ t.length = strlen(str);
+ t.data = (unsigned char *)str;
+ if (ASN1_GENERALIZEDTIME_check(&t)) {
+ if (s != NULL) {
+ if (!ASN1_STRING_set((ASN1_STRING *)s,
+ (unsigned char *)str, t.length))
+ return 0;
+ s->type = V_ASN1_GENERALIZEDTIME;
+ }
+ return (1);
+ } else
+ return (0);
+}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
- time_t t)
- {
- return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
- }
+ time_t t)
+{
+ return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
+}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
- time_t t, int offset_day, long offset_sec)
- {
- char *p;
- struct tm *ts;
- struct tm data;
- size_t len = 20;
-
- if (s == NULL)
- s=M_ASN1_GENERALIZEDTIME_new();
- if (s == NULL)
- return(NULL);
-
- ts=OPENSSL_gmtime(&t, &data);
- if (ts == NULL)
- return(NULL);
-
- if (offset_day || offset_sec)
- {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
- return NULL;
- }
-
- p=(char *)s->data;
- if ((p == NULL) || ((size_t)s->length < len))
- {
- p=OPENSSL_malloc(len);
- if (p == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
- if (s->data != NULL)
- OPENSSL_free(s->data);
- s->data=(unsigned char *)p;
- }
-
- BIO_snprintf(p,len,"%04d%02d%02d%02d%02d%02dZ",ts->tm_year + 1900,
- ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
- s->length=strlen(p);
- s->type=V_ASN1_GENERALIZEDTIME;
- return(s);
- }
+ time_t t, int offset_day,
+ long offset_sec)
+{
+ char *p;
+ struct tm *ts;
+ struct tm data;
+ size_t len = 20;
+
+ if (s == NULL)
+ s = M_ASN1_GENERALIZEDTIME_new();
+ if (s == NULL)
+ return (NULL);
+
+ ts = OPENSSL_gmtime(&t, &data);
+ if (ts == NULL)
+ return (NULL);
+
+ if (offset_day || offset_sec) {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ return NULL;
+ }
+
+ p = (char *)s->data;
+ if ((p == NULL) || ((size_t)s->length < len)) {
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ if (s->data != NULL)
+ OPENSSL_free(s->data);
+ s->data = (unsigned char *)p;
+ }
+
+ BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
+ ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
+ ts->tm_sec);
+ s->length = strlen(p);
+ s->type = V_ASN1_GENERALIZEDTIME;
+ return (s);
+}
diff --git a/src/crypto/asn1/a_i2d_fp.c b/src/crypto/asn1/a_i2d_fp.c
index 74ded78b..486207ed 100644
--- a/src/crypto/asn1/a_i2d_fp.c
+++ b/src/crypto/asn1/a_i2d_fp.c
@@ -59,96 +59,89 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
- {
- BIO *b;
- int ret;
+{
+ BIO *b;
+ int ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,out,BIO_NOCLOSE);
- ret=ASN1_i2d_bio(i2d,b,x);
- BIO_free(b);
- return(ret);
- }
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, out, BIO_NOCLOSE);
+ ret = ASN1_i2d_bio(i2d, b, x);
+ BIO_free(b);
+ return (ret);
+}
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
- {
- char *b;
- unsigned char *p;
- int i,j=0,n,ret=1;
+{
+ char *b;
+ unsigned char *p;
+ int i, j = 0, n, ret = 1;
+
+ n = i2d(x, NULL);
+ b = (char *)OPENSSL_malloc(n);
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
- n=i2d(x,NULL);
- b=(char *)OPENSSL_malloc(n);
- if (b == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(0);
- }
+ p = (unsigned char *)b;
+ i2d(x, &p);
- p=(unsigned char *)b;
- i2d(x,&p);
-
- for (;;)
- {
- i=BIO_write(out,&(b[j]),n);
- if (i == n) break;
- if (i <= 0)
- {
- ret=0;
- break;
- }
- j+=i;
- n-=i;
- }
- OPENSSL_free(b);
- return(ret);
- }
+ for (;;) {
+ i = BIO_write(out, &(b[j]), n);
+ if (i == n)
+ break;
+ if (i <= 0) {
+ ret = 0;
+ break;
+ }
+ j += i;
+ n -= i;
+ }
+ OPENSSL_free(b);
+ return (ret);
+}
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
- {
- BIO *b;
- int ret;
+{
+ BIO *b;
+ int ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,out,BIO_NOCLOSE);
- ret=ASN1_item_i2d_bio(it,b,x);
- BIO_free(b);
- return(ret);
- }
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, out, BIO_NOCLOSE);
+ ret = ASN1_item_i2d_bio(it, b, x);
+ BIO_free(b);
+ return (ret);
+}
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
- {
- unsigned char *b = NULL;
- int i,j=0,n,ret=1;
+{
+ unsigned char *b = NULL;
+ int i, j = 0, n, ret = 1;
- n = ASN1_item_i2d(x, &b, it);
- if (b == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(0);
- }
+ n = ASN1_item_i2d(x, &b, it);
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
- for (;;)
- {
- i=BIO_write(out,&(b[j]),n);
- if (i == n) break;
- if (i <= 0)
- {
- ret=0;
- break;
- }
- j+=i;
- n-=i;
- }
- OPENSSL_free(b);
- return(ret);
- }
+ for (;;) {
+ i = BIO_write(out, &(b[j]), n);
+ if (i == n)
+ break;
+ if (i <= 0) {
+ ret = 0;
+ break;
+ }
+ j += i;
+ n -= i;
+ }
+ OPENSSL_free(b);
+ return (ret);
+}
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
index 9a565343..38a01bcb 100644
--- a/src/crypto/asn1/a_int.c
+++ b/src/crypto/asn1/a_int.c
@@ -61,47 +61,46 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
-{ return M_ASN1_INTEGER_dup(x);}
+{
+ return M_ASN1_INTEGER_dup(x);
+}
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
- {
- int neg, ret;
- /* Compare signs */
- neg = x->type & V_ASN1_NEG;
- if (neg != (y->type & V_ASN1_NEG))
- {
- if (neg)
- return -1;
- else
- return 1;
- }
-
- ret = ASN1_STRING_cmp(x, y);
-
- if (neg)
- return -ret;
- else
- return ret;
- }
-
-
-/*
+{
+ int neg, ret;
+ /* Compare signs */
+ neg = x->type & V_ASN1_NEG;
+ if (neg != (y->type & V_ASN1_NEG)) {
+ if (neg)
+ return -1;
+ else
+ return 1;
+ }
+
+ ret = ASN1_STRING_cmp(x, y);
+
+ if (neg)
+ return -ret;
+ else
+ return ret;
+}
+
+/*
* This converts an ASN1 INTEGER into its content encoding.
* The internal representation is an ASN1_STRING whose data is a big endian
* representation of the value, ignoring the sign. The sign is determined by
- * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
+ * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
*
* Positive integers are no problem: they are almost the same as the DER
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
*
* Negative integers are a bit trickier...
* The DER representation of negative integers is in 2s complement form.
- * The internal form is converted by complementing each octet and finally
+ * The internal form is converted by complementing each octet and finally
* adding one to the result. This can be done less messily with a little trick.
* If the internal form has trailing zeroes then they will become FF by the
- * complement and 0 by the add one (due to carry) so just copy as many trailing
+ * complement and 0 by the add one (due to carry) so just copy as many trailing
* zeros to the destination as there are in the source. The carry will add one
* to the last none zero octet: so complement this octet and add one and finally
* complement any left over until you get to the start of the string.
@@ -113,344 +112,349 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
- {
- int pad=0,ret,i,neg;
- unsigned char *p,*n,pb=0;
-
- if (a == NULL) return(0);
- neg=a->type & V_ASN1_NEG;
- if (a->length == 0)
- ret=1;
- else
- {
- ret=a->length;
- i=a->data[0];
- if (!neg && (i > 127)) {
- pad=1;
- pb=0;
- } else if(neg) {
- if(i>128) {
- pad=1;
- pb=0xFF;
- } else if(i == 128) {
- /*
- * Special case: if any other bytes non zero we pad:
- * otherwise we don't.
- */
- for(i = 1; i < a->length; i++) if(a->data[i]) {
- pad=1;
- pb=0xFF;
- break;
- }
- }
- }
- ret+=pad;
- }
- if (pp == NULL) return(ret);
- p= *pp;
-
- if (pad) *(p++)=pb;
- if (a->length == 0) *(p++)=0;
- else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
- else {
- /* Begin at the end of the encoding */
- n=a->data + a->length - 1;
- p += a->length - 1;
- i = a->length;
- /* Copy zeros to destination as long as source is zero */
- while(!*n) {
- *(p--) = 0;
- n--;
- i--;
- }
- /* Complement and increment next octet */
- *(p--) = ((*(n--)) ^ 0xff) + 1;
- i--;
- /* Complement any octets left */
- for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
- }
-
- *pp+=ret;
- return(ret);
- }
+{
+ int pad = 0, ret, i, neg;
+ unsigned char *p, *n, pb = 0;
+
+ if (a == NULL)
+ return (0);
+ neg = a->type & V_ASN1_NEG;
+ if (a->length == 0)
+ ret = 1;
+ else {
+ ret = a->length;
+ i = a->data[0];
+ if (ret == 1 && i == 0)
+ neg = 0;
+ if (!neg && (i > 127)) {
+ pad = 1;
+ pb = 0;
+ } else if (neg) {
+ if (i > 128) {
+ pad = 1;
+ pb = 0xFF;
+ } else if (i == 128) {
+ /*
+ * Special case: if any other bytes non zero we pad:
+ * otherwise we don't.
+ */
+ for (i = 1; i < a->length; i++)
+ if (a->data[i]) {
+ pad = 1;
+ pb = 0xFF;
+ break;
+ }
+ }
+ }
+ ret += pad;
+ }
+ if (pp == NULL)
+ return (ret);
+ p = *pp;
+
+ if (pad)
+ *(p++) = pb;
+ if (a->length == 0)
+ *(p++) = 0;
+ else if (!neg)
+ memcpy(p, a->data, (unsigned int)a->length);
+ else {
+ /* Begin at the end of the encoding */
+ n = a->data + a->length - 1;
+ p += a->length - 1;
+ i = a->length;
+ /* Copy zeros to destination as long as source is zero */
+ while (!*n && i > 1) {
+ *(p--) = 0;
+ n--;
+ i--;
+ }
+ /* Complement and increment next octet */
+ *(p--) = ((*(n--)) ^ 0xff) + 1;
+ i--;
+ /* Complement any octets left */
+ for (; i > 0; i--)
+ *(p--) = *(n--) ^ 0xff;
+ }
+
+ *pp += ret;
+ return (ret);
+}
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
- long len)
- {
- ASN1_INTEGER *ret=NULL;
- const unsigned char *p, *pend;
- unsigned char *to,*s;
- int i;
-
- if ((a == NULL) || ((*a) == NULL))
- {
- if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
- ret->type=V_ASN1_INTEGER;
- }
- else
- ret=(*a);
-
- p= *pp;
- pend = p + len;
-
- /* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
- * signifies a missing NULL parameter. */
- s=(unsigned char *)OPENSSL_malloc((int)len+1);
- if (s == NULL)
- {
- i=ERR_R_MALLOC_FAILURE;
- goto err;
- }
- to=s;
- if(!len) {
- /* Strictly speaking this is an illegal INTEGER but we
- * tolerate it.
- */
- ret->type=V_ASN1_INTEGER;
- } else if (*p & 0x80) /* a negative number */
- {
- ret->type=V_ASN1_NEG_INTEGER;
- if ((*p == 0xff) && (len != 1)) {
- p++;
- len--;
- }
- i = len;
- p += i - 1;
- to += i - 1;
- while((!*p) && i) {
- *(to--) = 0;
- i--;
- p--;
- }
- /* Special case: if all zeros then the number will be of
- * the form FF followed by n zero bytes: this corresponds to
- * 1 followed by n zero bytes. We've already written n zeros
- * so we just append an extra one and set the first byte to
- * a 1. This is treated separately because it is the only case
- * where the number of bytes is larger than len.
- */
- if(!i) {
- *s = 1;
- s[len] = 0;
- len++;
- } else {
- *(to--) = (*(p--) ^ 0xff) + 1;
- i--;
- for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
- }
- } else {
- ret->type=V_ASN1_INTEGER;
- if ((*p == 0) && (len != 1))
- {
- p++;
- len--;
- }
- memcpy(s,p,(int)len);
- }
-
- if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->data=s;
- ret->length=(int)len;
- if (a != NULL) (*a)=ret;
- *pp=pend;
- return(ret);
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- M_ASN1_INTEGER_free(ret);
- return(NULL);
- }
-
-
-/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
- * ASN1 integers: some broken software can encode a positive INTEGER
- * with its MSB set as negative (it doesn't add a padding zero).
+ long len)
+{
+ ASN1_INTEGER *ret = NULL;
+ const unsigned char *p, *pend;
+ unsigned char *to, *s;
+ int i;
+
+ if ((a == NULL) || ((*a) == NULL)) {
+ if ((ret = M_ASN1_INTEGER_new()) == NULL)
+ return (NULL);
+ ret->type = V_ASN1_INTEGER;
+ } else
+ ret = (*a);
+
+ p = *pp;
+ pend = p + len;
+
+ /*
+ * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
+ * a missing NULL parameter.
+ */
+ s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ if (s == NULL) {
+ i = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ to = s;
+ if (!len) {
+ /*
+ * Strictly speaking this is an illegal INTEGER but we tolerate it.
+ */
+ ret->type = V_ASN1_INTEGER;
+ } else if (*p & 0x80) { /* a negative number */
+ ret->type = V_ASN1_NEG_INTEGER;
+ if ((*p == 0xff) && (len != 1)) {
+ p++;
+ len--;
+ }
+ i = len;
+ p += i - 1;
+ to += i - 1;
+ while ((!*p) && i) {
+ *(to--) = 0;
+ i--;
+ p--;
+ }
+ /*
+ * Special case: if all zeros then the number will be of the form FF
+ * followed by n zero bytes: this corresponds to 1 followed by n zero
+ * bytes. We've already written n zeros so we just append an extra
+ * one and set the first byte to a 1. This is treated separately
+ * because it is the only case where the number of bytes is larger
+ * than len.
+ */
+ if (!i) {
+ *s = 1;
+ s[len] = 0;
+ len++;
+ } else {
+ *(to--) = (*(p--) ^ 0xff) + 1;
+ i--;
+ for (; i > 0; i--)
+ *(to--) = *(p--) ^ 0xff;
+ }
+ } else {
+ ret->type = V_ASN1_INTEGER;
+ if ((*p == 0) && (len != 1)) {
+ p++;
+ len--;
+ }
+ memcpy(s, p, (int)len);
+ }
+
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ ret->data = s;
+ ret->length = (int)len;
+ if (a != NULL)
+ (*a) = ret;
+ *pp = pend;
+ return (ret);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_INTEGER_free(ret);
+ return (NULL);
+}
+
+/*
+ * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
+ * integers: some broken software can encode a positive INTEGER with its MSB
+ * set as negative (it doesn't add a padding zero).
*/
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
- long length)
- {
- ASN1_INTEGER *ret=NULL;
- const unsigned char *p;
- unsigned char *s;
- long len;
- int inf,tag,xclass;
- int i;
-
- if ((a == NULL) || ((*a) == NULL))
- {
- if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
- ret->type=V_ASN1_INTEGER;
- }
- else
- ret=(*a);
-
- p= *pp;
- inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
- if (inf & 0x80)
- {
- i=ASN1_R_BAD_OBJECT_HEADER;
- goto err;
- }
-
- if (tag != V_ASN1_INTEGER)
- {
- i=ASN1_R_EXPECTING_AN_INTEGER;
- goto err;
- }
-
- /* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
- * signifies a missing NULL parameter. */
- s=(unsigned char *)OPENSSL_malloc((int)len+1);
- if (s == NULL)
- {
- i=ERR_R_MALLOC_FAILURE;
- goto err;
- }
- ret->type=V_ASN1_INTEGER;
- if(len) {
- if ((*p == 0) && (len != 1))
- {
- p++;
- len--;
- }
- memcpy(s,p,(int)len);
- p+=len;
- }
-
- if (ret->data != NULL) OPENSSL_free(ret->data);
- ret->data=s;
- ret->length=(int)len;
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- M_ASN1_INTEGER_free(ret);
- return(NULL);
- }
+ long length)
+{
+ ASN1_INTEGER *ret = NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ long len;
+ int inf, tag, xclass;
+ int i;
+
+ if ((a == NULL) || ((*a) == NULL)) {
+ if ((ret = M_ASN1_INTEGER_new()) == NULL)
+ return (NULL);
+ ret->type = V_ASN1_INTEGER;
+ } else
+ ret = (*a);
+
+ p = *pp;
+ inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (inf & 0x80) {
+ i = ASN1_R_BAD_OBJECT_HEADER;
+ goto err;
+ }
+
+ if (tag != V_ASN1_INTEGER) {
+ i = ASN1_R_EXPECTING_AN_INTEGER;
+ goto err;
+ }
+
+ /*
+ * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
+ * a missing NULL parameter.
+ */
+ s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ if (s == NULL) {
+ i = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ ret->type = V_ASN1_INTEGER;
+ if (len) {
+ if ((*p == 0) && (len != 1)) {
+ p++;
+ len--;
+ }
+ memcpy(s, p, (int)len);
+ p += len;
+ }
+
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
+ ret->data = s;
+ ret->length = (int)len;
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_INTEGER_free(ret);
+ return (NULL);
+}
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
- {
- int j,k;
- unsigned int i;
- unsigned char buf[sizeof(long)+1];
- long d;
-
- a->type=V_ASN1_INTEGER;
- if (a->length < (int)(sizeof(long)+1))
- {
- if (a->data != NULL)
- OPENSSL_free(a->data);
- if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
- memset((char *)a->data,0,sizeof(long)+1);
- }
- if (a->data == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(0);
- }
- d=v;
- if (d < 0)
- {
- d= -d;
- a->type=V_ASN1_NEG_INTEGER;
- }
-
- for (i=0; i<sizeof(long); i++)
- {
- if (d == 0) break;
- buf[i]=(int)d&0xff;
- d>>=8;
- }
- j=0;
- for (k=i-1; k >=0; k--)
- a->data[j++]=buf[k];
- a->length=j;
- return(1);
- }
+{
+ int j, k;
+ unsigned int i;
+ unsigned char buf[sizeof(long) + 1];
+ long d;
+
+ a->type = V_ASN1_INTEGER;
+ if (a->length < (int)(sizeof(long) + 1)) {
+ if (a->data != NULL)
+ OPENSSL_free(a->data);
+ if ((a->data =
+ (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
+ memset((char *)a->data, 0, sizeof(long) + 1);
+ }
+ if (a->data == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ d = v;
+ if (d < 0) {
+ d = -d;
+ a->type = V_ASN1_NEG_INTEGER;
+ }
+
+ for (i = 0; i < sizeof(long); i++) {
+ if (d == 0)
+ break;
+ buf[i] = (int)d & 0xff;
+ d >>= 8;
+ }
+ j = 0;
+ for (k = i - 1; k >= 0; k--)
+ a->data[j++] = buf[k];
+ a->length = j;
+ return (1);
+}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
- {
- int neg=0,i;
- long r=0;
-
- if (a == NULL) return(0L);
- i=a->type;
- if (i == V_ASN1_NEG_INTEGER)
- neg=1;
- else if (i != V_ASN1_INTEGER)
- return -1;
-
- if (a->length > (int)sizeof(long))
- {
- /* hmm... a bit ugly, return all ones */
- return -1;
- }
- if (a->data == NULL)
- return 0;
-
- for (i=0; i<a->length; i++)
- {
- r<<=8;
- r|=(unsigned char)a->data[i];
- }
- if (neg) r= -r;
- return(r);
- }
+{
+ int neg = 0, i;
+ long r = 0;
+
+ if (a == NULL)
+ return (0L);
+ i = a->type;
+ if (i == V_ASN1_NEG_INTEGER)
+ neg = 1;
+ else if (i != V_ASN1_INTEGER)
+ return -1;
+
+ if (a->length > (int)sizeof(long)) {
+ /* hmm... a bit ugly, return all ones */
+ return -1;
+ }
+ if (a->data == NULL)
+ return 0;
+
+ for (i = 0; i < a->length; i++) {
+ r <<= 8;
+ r |= (unsigned char)a->data[i];
+ }
+ if (neg)
+ r = -r;
+ return (r);
+}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
- {
- ASN1_INTEGER *ret;
- int len,j;
-
- if (ai == NULL)
- ret=M_ASN1_INTEGER_new();
- else
- ret=ai;
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- if (BN_is_negative(bn) && !BN_is_zero(bn))
- ret->type = V_ASN1_NEG_INTEGER;
- else ret->type=V_ASN1_INTEGER;
- j=BN_num_bits(bn);
- len=((j == 0)?0:((j/8)+1));
- if (ret->length < len+4)
- {
- unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
- if (!new_data)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ret->data=new_data;
- }
- ret->length=BN_bn2bin(bn,ret->data);
- /* Correct zero case */
- if(!ret->length)
- {
- ret->data[0] = 0;
- ret->length = 1;
- }
- return(ret);
-err:
- if (ret != ai) M_ASN1_INTEGER_free(ret);
- return(NULL);
- }
+{
+ ASN1_INTEGER *ret;
+ int len, j;
+
+ if (ai == NULL)
+ ret = M_ASN1_INTEGER_new();
+ else
+ ret = ai;
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ if (BN_is_negative(bn) && !BN_is_zero(bn))
+ ret->type = V_ASN1_NEG_INTEGER;
+ else
+ ret->type = V_ASN1_INTEGER;
+ j = BN_num_bits(bn);
+ len = ((j == 0) ? 0 : ((j / 8) + 1));
+ if (ret->length < len + 4) {
+ unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
+ if (!new_data) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ret->data = new_data;
+ }
+ ret->length = BN_bn2bin(bn, ret->data);
+ /* Correct zero case */
+ if (!ret->length) {
+ ret->data[0] = 0;
+ ret->length = 1;
+ }
+ return (ret);
+ err:
+ if (ret != ai)
+ M_ASN1_INTEGER_free(ret);
+ return (NULL);
+}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
- {
- BIGNUM *ret;
-
- if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
- else if(ai->type == V_ASN1_NEG_INTEGER)
- BN_set_negative(ret, 1);
- return(ret);
- }
+{
+ BIGNUM *ret;
+
+ if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
+ else if (ai->type == V_ASN1_NEG_INTEGER)
+ BN_set_negative(ret, 1);
+ return (ret);
+}
diff --git a/src/crypto/asn1/a_mbstr.c b/src/crypto/asn1/a_mbstr.c
index 42806d1a..30fff82a 100644
--- a/src/crypto/asn1/a_mbstr.c
+++ b/src/crypto/asn1/a_mbstr.c
@@ -61,9 +61,9 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
static int traverse_string(const unsigned char *p, int len, int inform,
- int (*rfunc)(unsigned long value, void *in), void *arg);
+ int (*rfunc) (unsigned long value, void *in),
+ void *arg);
static int in_utf8(unsigned long value, void *arg);
static int out_utf8(unsigned long value, void *arg);
static int type_str(unsigned long value, void *arg);
@@ -73,208 +73,219 @@ static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
static int is_printable(unsigned long value);
-/* These functions take a string in UTF8, ASCII or multibyte form and
- * a mask of permissible ASN1 string types. It then works out the minimal
- * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
- * and creates a string of the correct type with the supplied data.
- * Yes this is horrible: it has to be :-(
- * The 'ncopy' form checks minimum and maximum size limits too.
+/*
+ * These functions take a string in UTF8, ASCII or multibyte form and a mask
+ * of permissible ASN1 string types. It then works out the minimal type
+ * (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
+ * creates a string of the correct type with the supplied data. Yes this is
+ * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
+ * size limits too.
*/
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
- int inform, unsigned long mask)
+ int inform, unsigned long mask)
{
- return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
+ return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
- int inform, unsigned long mask,
- long minsize, long maxsize)
+ int inform, unsigned long mask,
+ long minsize, long maxsize)
{
- int str_type;
- int ret;
- char free_out;
- int outform, outlen = 0;
- ASN1_STRING *dest;
- unsigned char *p;
- int nchar;
- char strbuf[32];
- int (*cpyfunc)(unsigned long,void *) = NULL;
- if(len == -1) len = strlen((const char *)in);
- if(!mask) mask = DIRSTRING_TYPE;
-
- /* First do a string check and work out the number of characters */
- switch(inform) {
-
- case MBSTRING_BMP:
- if(len & 1) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
- return -1;
- }
- nchar = len >> 1;
- break;
-
- case MBSTRING_UNIV:
- if(len & 3) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
- return -1;
- }
- nchar = len >> 2;
- break;
-
- case MBSTRING_UTF8:
- nchar = 0;
- /* This counts the characters and does utf8 syntax checking */
- ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
- if(ret < 0) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
- return -1;
- }
- break;
-
- case MBSTRING_ASC:
- nchar = len;
- break;
-
- default:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
- return -1;
- }
-
- if((minsize > 0) && (nchar < minsize)) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
- BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
- ERR_add_error_data(2, "minsize=", strbuf);
- return -1;
- }
-
- if((maxsize > 0) && (nchar > maxsize)) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
- BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
- ERR_add_error_data(2, "maxsize=", strbuf);
- return -1;
- }
-
- /* Now work out minimal type (if any) */
- if(traverse_string(in, len, inform, type_str, &mask) < 0) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
- return -1;
- }
-
-
- /* Now work out output format and string type */
- outform = MBSTRING_ASC;
- if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
- else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
- else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
- else if(mask & B_ASN1_BMPSTRING) {
- str_type = V_ASN1_BMPSTRING;
- outform = MBSTRING_BMP;
- } else if(mask & B_ASN1_UNIVERSALSTRING) {
- str_type = V_ASN1_UNIVERSALSTRING;
- outform = MBSTRING_UNIV;
- } else {
- str_type = V_ASN1_UTF8STRING;
- outform = MBSTRING_UTF8;
- }
- if(!out) return str_type;
- if(*out) {
- free_out = 0;
- dest = *out;
- if(dest->data) {
- dest->length = 0;
- OPENSSL_free(dest->data);
- dest->data = NULL;
- }
- dest->type = str_type;
- } else {
- free_out = 1;
- dest = ASN1_STRING_type_new(str_type);
- if(!dest) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- *out = dest;
- }
- /* If both the same type just copy across */
- if(inform == outform) {
- if(!ASN1_STRING_set(dest, in, len)) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- return str_type;
- }
-
- /* Work out how much space the destination will need */
- switch(outform) {
- case MBSTRING_ASC:
- outlen = nchar;
- cpyfunc = cpy_asc;
- break;
-
- case MBSTRING_BMP:
- outlen = nchar << 1;
- cpyfunc = cpy_bmp;
- break;
-
- case MBSTRING_UNIV:
- outlen = nchar << 2;
- cpyfunc = cpy_univ;
- break;
-
- case MBSTRING_UTF8:
- outlen = 0;
- traverse_string(in, len, inform, out_utf8, &outlen);
- cpyfunc = cpy_utf8;
- break;
- }
- if(!(p = OPENSSL_malloc(outlen + 1))) {
- if(free_out) ASN1_STRING_free(dest);
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- dest->length = outlen;
- dest->data = p;
- p[outlen] = 0;
- traverse_string(in, len, inform, cpyfunc, &p);
- return str_type;
+ int str_type;
+ int ret;
+ char free_out;
+ int outform, outlen = 0;
+ ASN1_STRING *dest;
+ unsigned char *p;
+ int nchar;
+ char strbuf[32];
+ int (*cpyfunc) (unsigned long, void *) = NULL;
+ if (len == -1)
+ len = strlen((const char *)in);
+ if (!mask)
+ mask = DIRSTRING_TYPE;
+
+ /* First do a string check and work out the number of characters */
+ switch (inform) {
+
+ case MBSTRING_BMP:
+ if (len & 1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
+ return -1;
+ }
+ nchar = len >> 1;
+ break;
+
+ case MBSTRING_UNIV:
+ if (len & 3) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+ return -1;
+ }
+ nchar = len >> 2;
+ break;
+
+ case MBSTRING_UTF8:
+ nchar = 0;
+ /* This counts the characters and does utf8 syntax checking */
+ ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
+ if (ret < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
+ return -1;
+ }
+ break;
+
+ case MBSTRING_ASC:
+ nchar = len;
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+
+ if ((minsize > 0) && (nchar < minsize)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
+ BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
+ ERR_add_error_data(2, "minsize=", strbuf);
+ return -1;
+ }
+
+ if ((maxsize > 0) && (nchar > maxsize)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
+ BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
+ ERR_add_error_data(2, "maxsize=", strbuf);
+ return -1;
+ }
+
+ /* Now work out minimal type (if any) */
+ if (traverse_string(in, len, inform, type_str, &mask) < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
+ return -1;
+ }
+
+ /* Now work out output format and string type */
+ outform = MBSTRING_ASC;
+ if (mask & B_ASN1_PRINTABLESTRING)
+ str_type = V_ASN1_PRINTABLESTRING;
+ else if (mask & B_ASN1_IA5STRING)
+ str_type = V_ASN1_IA5STRING;
+ else if (mask & B_ASN1_T61STRING)
+ str_type = V_ASN1_T61STRING;
+ else if (mask & B_ASN1_BMPSTRING) {
+ str_type = V_ASN1_BMPSTRING;
+ outform = MBSTRING_BMP;
+ } else if (mask & B_ASN1_UNIVERSALSTRING) {
+ str_type = V_ASN1_UNIVERSALSTRING;
+ outform = MBSTRING_UNIV;
+ } else {
+ str_type = V_ASN1_UTF8STRING;
+ outform = MBSTRING_UTF8;
+ }
+ if (!out)
+ return str_type;
+ if (*out) {
+ free_out = 0;
+ dest = *out;
+ if (dest->data) {
+ dest->length = 0;
+ OPENSSL_free(dest->data);
+ dest->data = NULL;
+ }
+ dest->type = str_type;
+ } else {
+ free_out = 1;
+ dest = ASN1_STRING_type_new(str_type);
+ if (!dest) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ *out = dest;
+ }
+ /* If both the same type just copy across */
+ if (inform == outform) {
+ if (!ASN1_STRING_set(dest, in, len)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ return str_type;
+ }
+
+ /* Work out how much space the destination will need */
+ switch (outform) {
+ case MBSTRING_ASC:
+ outlen = nchar;
+ cpyfunc = cpy_asc;
+ break;
+
+ case MBSTRING_BMP:
+ outlen = nchar << 1;
+ cpyfunc = cpy_bmp;
+ break;
+
+ case MBSTRING_UNIV:
+ outlen = nchar << 2;
+ cpyfunc = cpy_univ;
+ break;
+
+ case MBSTRING_UTF8:
+ outlen = 0;
+ traverse_string(in, len, inform, out_utf8, &outlen);
+ cpyfunc = cpy_utf8;
+ break;
+ }
+ if (!(p = OPENSSL_malloc(outlen + 1))) {
+ if (free_out)
+ ASN1_STRING_free(dest);
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ dest->length = outlen;
+ dest->data = p;
+ p[outlen] = 0;
+ traverse_string(in, len, inform, cpyfunc, &p);
+ return str_type;
}
-/* This function traverses a string and passes the value of each character
- * to an optional function along with a void * argument.
+/*
+ * This function traverses a string and passes the value of each character to
+ * an optional function along with a void * argument.
*/
static int traverse_string(const unsigned char *p, int len, int inform,
- int (*rfunc)(unsigned long value, void *in), void *arg)
+ int (*rfunc) (unsigned long value, void *in),
+ void *arg)
{
- unsigned long value;
- int ret;
- while(len) {
- if(inform == MBSTRING_ASC) {
- value = *p++;
- len--;
- } else if(inform == MBSTRING_BMP) {
- value = *p++ << 8;
- value |= *p++;
- len -= 2;
- } else if(inform == MBSTRING_UNIV) {
- value = ((unsigned long)*p++) << 24;
- value |= ((unsigned long)*p++) << 16;
- value |= *p++ << 8;
- value |= *p++;
- len -= 4;
- } else {
- ret = UTF8_getc(p, len, &value);
- if(ret < 0) return -1;
- len -= ret;
- p += ret;
- }
- if(rfunc) {
- ret = rfunc(value, arg);
- if(ret <= 0) return ret;
- }
- }
- return 1;
+ unsigned long value;
+ int ret;
+ while (len) {
+ if (inform == MBSTRING_ASC) {
+ value = *p++;
+ len--;
+ } else if (inform == MBSTRING_BMP) {
+ value = *p++ << 8;
+ value |= *p++;
+ len -= 2;
+ } else if (inform == MBSTRING_UNIV) {
+ value = ((unsigned long)*p++) << 24;
+ value |= ((unsigned long)*p++) << 16;
+ value |= *p++ << 8;
+ value |= *p++;
+ len -= 4;
+ } else {
+ ret = UTF8_getc(p, len, &value);
+ if (ret < 0)
+ return -1;
+ len -= ret;
+ p += ret;
+ }
+ if (rfunc) {
+ ret = rfunc(value, arg);
+ if (ret <= 0)
+ return ret;
+ }
+ }
+ return 1;
}
/* Various utility functions for traverse_string */
@@ -283,108 +294,116 @@ static int traverse_string(const unsigned char *p, int len, int inform,
static int in_utf8(unsigned long value, void *arg)
{
- int *nchar;
- nchar = arg;
- (*nchar)++;
- return 1;
+ int *nchar;
+ nchar = arg;
+ (*nchar)++;
+ return 1;
}
/* Determine size of output as a UTF8 String */
static int out_utf8(unsigned long value, void *arg)
{
- int *outlen;
- outlen = arg;
- *outlen += UTF8_putc(NULL, -1, value);
- return 1;
+ int *outlen;
+ outlen = arg;
+ *outlen += UTF8_putc(NULL, -1, value);
+ return 1;
}
-/* Determine the "type" of a string: check each character against a
- * supplied "mask".
+/*
+ * Determine the "type" of a string: check each character against a supplied
+ * "mask".
*/
static int type_str(unsigned long value, void *arg)
{
- unsigned long types;
- types = *((unsigned long *)arg);
- if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
- types &= ~B_ASN1_PRINTABLESTRING;
- if((types & B_ASN1_IA5STRING) && (value > 127))
- types &= ~B_ASN1_IA5STRING;
- if((types & B_ASN1_T61STRING) && (value > 0xff))
- types &= ~B_ASN1_T61STRING;
- if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
- types &= ~B_ASN1_BMPSTRING;
- if(!types) return -1;
- *((unsigned long *)arg) = types;
- return 1;
+ unsigned long types;
+ types = *((unsigned long *)arg);
+ if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
+ types &= ~B_ASN1_PRINTABLESTRING;
+ if ((types & B_ASN1_IA5STRING) && (value > 127))
+ types &= ~B_ASN1_IA5STRING;
+ if ((types & B_ASN1_T61STRING) && (value > 0xff))
+ types &= ~B_ASN1_T61STRING;
+ if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
+ types &= ~B_ASN1_BMPSTRING;
+ if (!types)
+ return -1;
+ *((unsigned long *)arg) = types;
+ return 1;
}
/* Copy one byte per character ASCII like strings */
static int cpy_asc(unsigned long value, void *arg)
{
- unsigned char **p, *q;
- p = arg;
- q = *p;
- *q = (unsigned char) value;
- (*p)++;
- return 1;
+ unsigned char **p, *q;
+ p = arg;
+ q = *p;
+ *q = (unsigned char)value;
+ (*p)++;
+ return 1;
}
/* Copy two byte per character BMPStrings */
static int cpy_bmp(unsigned long value, void *arg)
{
- unsigned char **p, *q;
- p = arg;
- q = *p;
- *q++ = (unsigned char) ((value >> 8) & 0xff);
- *q = (unsigned char) (value & 0xff);
- *p += 2;
- return 1;
+ unsigned char **p, *q;
+ p = arg;
+ q = *p;
+ *q++ = (unsigned char)((value >> 8) & 0xff);
+ *q = (unsigned char)(value & 0xff);
+ *p += 2;
+ return 1;
}
/* Copy four byte per character UniversalStrings */
static int cpy_univ(unsigned long value, void *arg)
{
- unsigned char **p, *q;
- p = arg;
- q = *p;
- *q++ = (unsigned char) ((value >> 24) & 0xff);
- *q++ = (unsigned char) ((value >> 16) & 0xff);
- *q++ = (unsigned char) ((value >> 8) & 0xff);
- *q = (unsigned char) (value & 0xff);
- *p += 4;
- return 1;
+ unsigned char **p, *q;
+ p = arg;
+ q = *p;
+ *q++ = (unsigned char)((value >> 24) & 0xff);
+ *q++ = (unsigned char)((value >> 16) & 0xff);
+ *q++ = (unsigned char)((value >> 8) & 0xff);
+ *q = (unsigned char)(value & 0xff);
+ *p += 4;
+ return 1;
}
/* Copy to a UTF8String */
static int cpy_utf8(unsigned long value, void *arg)
{
- unsigned char **p;
- int ret;
- p = arg;
- /* We already know there is enough room so pass 0xff as the length */
- ret = UTF8_putc(*p, 0xff, value);
- *p += ret;
- return 1;
+ unsigned char **p;
+ int ret;
+ p = arg;
+ /* We already know there is enough room so pass 0xff as the length */
+ ret = UTF8_putc(*p, 0xff, value);
+ *p += ret;
+ return 1;
}
/* Return 1 if the character is permitted in a PrintableString */
static int is_printable(unsigned long value)
{
- int ch;
- if(value > 0x7f) return 0;
- ch = (int) value;
- /* Note: we can't use 'isalnum' because certain accented
- * characters may count as alphanumeric in some environments.
- */
- if((ch >= 'a') && (ch <= 'z')) return 1;
- if((ch >= 'A') && (ch <= 'Z')) return 1;
- if((ch >= '0') && (ch <= '9')) return 1;
- if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
- return 0;
+ int ch;
+ if (value > 0x7f)
+ return 0;
+ ch = (int)value;
+ /*
+ * Note: we can't use 'isalnum' because certain accented characters may
+ * count as alphanumeric in some environments.
+ */
+ if ((ch >= 'a') && (ch <= 'z'))
+ return 1;
+ if ((ch >= 'A') && (ch <= 'Z'))
+ return 1;
+ if ((ch >= '0') && (ch <= '9'))
+ return 1;
+ if ((ch == ' ') || strchr("'()+,-./:=?", ch))
+ return 1;
+ return 0;
}
diff --git a/src/crypto/asn1/a_object.c b/src/crypto/asn1/a_object.c
index 6ddfca92..10f38398 100644
--- a/src/crypto/asn1/a_object.c
+++ b/src/crypto/asn1/a_object.c
@@ -63,350 +63,334 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
-
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
- {
- unsigned char *p;
- int objsize;
+{
+ unsigned char *p;
+ int objsize;
- if ((a == NULL) || (a->data == NULL)) return(0);
+ if ((a == NULL) || (a->data == NULL))
+ return (0);
- objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
- if (pp == NULL) return objsize;
+ objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
+ if (pp == NULL)
+ return objsize;
- p= *pp;
- ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
- memcpy(p,a->data,a->length);
- p+=a->length;
+ p = *pp;
+ ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
+ memcpy(p, a->data, a->length);
+ p += a->length;
- *pp=p;
- return(objsize);
- }
+ *pp = p;
+ return (objsize);
+}
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
- {
- int i,first,len=0,c, use_bn;
- char ftmp[24], *tmp = ftmp;
- int tmpsize = sizeof ftmp;
- const char *p;
- unsigned long l;
- BIGNUM *bl = NULL;
+{
+ int i, first, len = 0, c, use_bn;
+ char ftmp[24], *tmp = ftmp;
+ int tmpsize = sizeof ftmp;
+ const char *p;
+ unsigned long l;
+ BIGNUM *bl = NULL;
- if (num == 0)
- return(0);
- else if (num == -1)
- num=strlen(buf);
+ if (num == 0)
+ return (0);
+ else if (num == -1)
+ num = strlen(buf);
- p=buf;
- c= *(p++);
- num--;
- if ((c >= '0') && (c <= '2'))
- {
- first= c-'0';
- }
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
- goto err;
- }
+ p = buf;
+ c = *(p++);
+ num--;
+ if ((c >= '0') && (c <= '2')) {
+ first = c - '0';
+ } else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
+ goto err;
+ }
- if (num <= 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
- goto err;
- }
- c= *(p++);
- num--;
- for (;;)
- {
- if (num <= 0) break;
- if ((c != '.') && (c != ' '))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
- goto err;
- }
- l=0;
- use_bn = 0;
- for (;;)
- {
- if (num <= 0) break;
- num--;
- c= *(p++);
- if ((c == ' ') || (c == '.'))
- break;
- if ((c < '0') || (c > '9'))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
- goto err;
- }
- if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
- {
- use_bn = 1;
- if (!bl)
- bl = BN_new();
- if (!bl || !BN_set_word(bl, l))
- goto err;
- }
- if (use_bn)
- {
- if (!BN_mul_word(bl, 10L)
- || !BN_add_word(bl, c-'0'))
- goto err;
- }
- else
- l=l*10L+(long)(c-'0');
- }
- if (len == 0)
- {
- if ((first < 2) && (l >= 40))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
- goto err;
- }
- if (use_bn)
- {
- if (!BN_add_word(bl, first * 40))
- goto err;
- }
- else
- l+=(long)first*40;
- }
- i=0;
- if (use_bn)
- {
- int blsize;
- blsize = BN_num_bits(bl);
- blsize = (blsize + 6)/7;
- if (blsize > tmpsize)
- {
- if (tmp != ftmp)
- OPENSSL_free(tmp);
- tmpsize = blsize + 32;
- tmp = OPENSSL_malloc(tmpsize);
- if (!tmp)
- goto err;
- }
- while(blsize--)
- tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
- }
- else
- {
-
- for (;;)
- {
- tmp[i++]=(unsigned char)l&0x7f;
- l>>=7L;
- if (l == 0L) break;
- }
+ if (num <= 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
+ goto err;
+ }
+ c = *(p++);
+ num--;
+ for (;;) {
+ if (num <= 0)
+ break;
+ if ((c != '.') && (c != ' ')) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
+ goto err;
+ }
+ l = 0;
+ use_bn = 0;
+ for (;;) {
+ if (num <= 0)
+ break;
+ num--;
+ c = *(p++);
+ if ((c == ' ') || (c == '.'))
+ break;
+ if ((c < '0') || (c > '9')) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
+ goto err;
+ }
+ if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
+ use_bn = 1;
+ if (!bl)
+ bl = BN_new();
+ if (!bl || !BN_set_word(bl, l))
+ goto err;
+ }
+ if (use_bn) {
+ if (!BN_mul_word(bl, 10L)
+ || !BN_add_word(bl, c - '0'))
+ goto err;
+ } else
+ l = l * 10L + (long)(c - '0');
+ }
+ if (len == 0) {
+ if ((first < 2) && (l >= 40)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
+ goto err;
+ }
+ if (use_bn) {
+ if (!BN_add_word(bl, first * 40))
+ goto err;
+ } else
+ l += (long)first *40;
+ }
+ i = 0;
+ if (use_bn) {
+ int blsize;
+ blsize = BN_num_bits(bl);
+ blsize = (blsize + 6) / 7;
+ if (blsize > tmpsize) {
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ tmpsize = blsize + 32;
+ tmp = OPENSSL_malloc(tmpsize);
+ if (!tmp)
+ goto err;
+ }
+ while (blsize--)
+ tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
+ } else {
- }
- if (out != NULL)
- {
- if (len+i > olen)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
- goto err;
- }
- while (--i > 0)
- out[len++]=tmp[i]|0x80;
- out[len++]=tmp[0];
- }
- else
- len+=i;
- }
- if (tmp != ftmp)
- OPENSSL_free(tmp);
- if (bl)
- BN_free(bl);
- return(len);
-err:
- if (tmp != ftmp)
- OPENSSL_free(tmp);
- if (bl)
- BN_free(bl);
- return(0);
- }
+ for (;;) {
+ tmp[i++] = (unsigned char)l & 0x7f;
+ l >>= 7L;
+ if (l == 0L)
+ break;
+ }
+
+ }
+ if (out != NULL) {
+ if (len + i > olen) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
+ goto err;
+ }
+ while (--i > 0)
+ out[len++] = tmp[i] | 0x80;
+ out[len++] = tmp[0];
+ } else
+ len += i;
+ }
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ if (bl)
+ BN_free(bl);
+ return (len);
+ err:
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ if (bl)
+ BN_free(bl);
+ return (0);
+}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
- return OBJ_obj2txt(buf, buf_len, a, 0);
+ return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
- {
- char buf[80], *p = buf;
- int i;
+{
+ char buf[80], *p = buf;
+ int i;
- if ((a == NULL) || (a->data == NULL))
- return(BIO_write(bp,"NULL",4));
- i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
- if (i > (int)(sizeof(buf) - 1))
- {
- p = OPENSSL_malloc(i + 1);
- if (!p)
- return -1;
- i2t_ASN1_OBJECT(p,i + 1,a);
- }
- if (i <= 0)
- return BIO_write(bp, "<INVALID>", 9);
- BIO_write(bp,p,i);
- if (p != buf)
- OPENSSL_free(p);
- return(i);
- }
+ if ((a == NULL) || (a->data == NULL))
+ return (BIO_write(bp, "NULL", 4));
+ i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
+ if (i > (int)(sizeof(buf) - 1)) {
+ p = OPENSSL_malloc(i + 1);
+ if (!p)
+ return -1;
+ i2t_ASN1_OBJECT(p, i + 1, a);
+ }
+ if (i <= 0)
+ return BIO_write(bp, "<INVALID>", 9);
+ BIO_write(bp, p, i);
+ if (p != buf)
+ OPENSSL_free(p);
+ return (i);
+}
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
- long length)
+ long length)
{
- const unsigned char *p;
- long len;
- int tag,xclass;
- int inf,i;
- ASN1_OBJECT *ret = NULL;
- p= *pp;
- inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
- if (inf & 0x80)
- {
- i=ASN1_R_BAD_OBJECT_HEADER;
- goto err;
- }
+ const unsigned char *p;
+ long len;
+ int tag, xclass;
+ int inf, i;
+ ASN1_OBJECT *ret = NULL;
+ p = *pp;
+ inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (inf & 0x80) {
+ i = ASN1_R_BAD_OBJECT_HEADER;
+ goto err;
+ }
- if (tag != V_ASN1_OBJECT)
- {
- i=ASN1_R_EXPECTING_AN_OBJECT;
- goto err;
- }
- ret = c2i_ASN1_OBJECT(a, &p, len);
- if(ret) *pp = p;
- return ret;
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- return(NULL);
+ if (tag != V_ASN1_OBJECT) {
+ i = ASN1_R_EXPECTING_AN_OBJECT;
+ goto err;
+ }
+ ret = c2i_ASN1_OBJECT(a, &p, len);
+ if (ret)
+ *pp = p;
+ return ret;
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ return (NULL);
}
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
- long len)
- {
- ASN1_OBJECT *ret=NULL;
- const unsigned char *p;
- unsigned char *data;
- int i, length;
+ long len)
+{
+ ASN1_OBJECT *ret = NULL;
+ const unsigned char *p;
+ unsigned char *data;
+ int i, length;
- /* Sanity check OID encoding.
- * Need at least one content octet.
- * MSB must be clear in the last octet.
- * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
- */
- if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
- p[len - 1] & 0x80)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
- return NULL;
- }
- /* Now 0 < len <= INT_MAX, so the cast is safe. */
- length = (int)len;
- for (i = 0; i < length; i++, p++)
- {
- if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
- return NULL;
- }
- }
+ /*
+ * Sanity check OID encoding. Need at least one content octet. MSB must
+ * be clear in the last octet. can't have leading 0x80 in subidentifiers,
+ * see: X.690 8.19.2
+ */
+ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+ p[len - 1] & 0x80) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ /* Now 0 < len <= INT_MAX, so the cast is safe. */
+ length = (int)len;
+ for (i = 0; i < length; i++, p++) {
+ if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ }
- /* only the ASN1_OBJECTs from the 'table' will have values
- * for ->sn or ->ln */
- if ((a == NULL) || ((*a) == NULL) ||
- !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
- {
- if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
- }
- else ret=(*a);
+ /*
+ * only the ASN1_OBJECTs from the 'table' will have values for ->sn or
+ * ->ln
+ */
+ if ((a == NULL) || ((*a) == NULL) ||
+ !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
+ if ((ret = ASN1_OBJECT_new()) == NULL)
+ return (NULL);
+ } else
+ ret = (*a);
- p= *pp;
- /* detach data from object */
- data = (unsigned char *)ret->data;
- ret->data = NULL;
- /* once detached we can change it */
- if ((data == NULL) || (ret->length < length))
- {
- ret->length=0;
- if (data != NULL) OPENSSL_free(data);
- data=(unsigned char *)OPENSSL_malloc(length);
- if (data == NULL)
- { i=ERR_R_MALLOC_FAILURE; goto err; }
- ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
- }
- memcpy(data,p,length);
- /* reattach data to object, after which it remains const */
- ret->data =data;
- ret->length=length;
- ret->sn=NULL;
- ret->ln=NULL;
- /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
- p+=length;
+ p = *pp;
+ /* detach data from object */
+ data = (unsigned char *)ret->data;
+ ret->data = NULL;
+ /* once detached we can change it */
+ if ((data == NULL) || (ret->length < length)) {
+ ret->length = 0;
+ if (data != NULL)
+ OPENSSL_free(data);
+ data = (unsigned char *)OPENSSL_malloc(length);
+ if (data == NULL) {
+ i = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+ }
+ memcpy(data, p, length);
+ /* reattach data to object, after which it remains const */
+ ret->data = data;
+ ret->length = length;
+ ret->sn = NULL;
+ ret->ln = NULL;
+ /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
+ p += length;
- if (a != NULL) (*a)=ret;
- *pp=p;
- return(ret);
-err:
- OPENSSL_PUT_ERROR(ASN1, i);
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- ASN1_OBJECT_free(ret);
- return(NULL);
- }
+ if (a != NULL)
+ (*a) = ret;
+ *pp = p;
+ return (ret);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_OBJECT_free(ret);
+ return (NULL);
+}
ASN1_OBJECT *ASN1_OBJECT_new(void)
- {
- ASN1_OBJECT *ret;
+{
+ ASN1_OBJECT *ret;
- ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
- ret->length=0;
- ret->data=NULL;
- ret->nid=0;
- ret->sn=NULL;
- ret->ln=NULL;
- ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
- return(ret);
- }
+ ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ ret->length = 0;
+ ret->data = NULL;
+ ret->nid = 0;
+ ret->sn = NULL;
+ ret->ln = NULL;
+ ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
+ return (ret);
+}
void ASN1_OBJECT_free(ASN1_OBJECT *a)
- {
- if (a == NULL) return;
- if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
- {
-#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
- if (a->sn != NULL) OPENSSL_free((void *)a->sn);
- if (a->ln != NULL) OPENSSL_free((void *)a->ln);
+{
+ if (a == NULL)
+ return;
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
+#ifndef CONST_STRICT /* disable purely for compile-time strict
+ * const checking. Doing this on a "real"
+ * compile will cause memory leaks */
+ if (a->sn != NULL)
+ OPENSSL_free((void *)a->sn);
+ if (a->ln != NULL)
+ OPENSSL_free((void *)a->ln);
#endif
- a->sn=a->ln=NULL;
- }
- if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
- {
- if (a->data != NULL) OPENSSL_free((void *)a->data);
- a->data=NULL;
- a->length=0;
- }
- if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
- OPENSSL_free(a);
- }
+ a->sn = a->ln = NULL;
+ }
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
+ if (a->data != NULL)
+ OPENSSL_free((void *)a->data);
+ a->data = NULL;
+ a->length = 0;
+ }
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
+ OPENSSL_free(a);
+}
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
- const char *sn, const char *ln)
- {
- ASN1_OBJECT o;
+ const char *sn, const char *ln)
+{
+ ASN1_OBJECT o;
- o.sn=sn;
- o.ln=ln;
- o.data=data;
- o.nid=nid;
- o.length=len;
- o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
- ASN1_OBJECT_FLAG_DYNAMIC_DATA;
- return(OBJ_dup(&o));
- }
+ o.sn = sn;
+ o.ln = ln;
+ o.data = data;
+ o.nid = nid;
+ o.length = len;
+ o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+ ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+ return (OBJ_dup(&o));
+}
diff --git a/src/crypto/asn1/a_octet.c b/src/crypto/asn1/a_octet.c
index 583c9e9d..2e74d6bf 100644
--- a/src/crypto/asn1/a_octet.c
+++ b/src/crypto/asn1/a_octet.c
@@ -59,12 +59,19 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
-{ return M_ASN1_OCTET_STRING_dup(x); }
+{
+ return M_ASN1_OCTET_STRING_dup(x);
+}
-int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
-{ return M_ASN1_OCTET_STRING_cmp(a, b); }
+int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
+ const ASN1_OCTET_STRING *b)
+{
+ return M_ASN1_OCTET_STRING_cmp(a, b);
+}
-int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
-{ return M_ASN1_OCTET_STRING_set(x, d, len); }
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
+ int len)
+{
+ return M_ASN1_OCTET_STRING_set(x, d, len);
+}
diff --git a/src/crypto/asn1/a_print.c b/src/crypto/asn1/a_print.c
index 3b6be10b..aee54fa4 100644
--- a/src/crypto/asn1/a_print.c
+++ b/src/crypto/asn1/a_print.c
@@ -59,61 +59,63 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
- {
- int c;
- int ia5=0;
- int t61=0;
+{
+ int c;
+ int ia5 = 0;
+ int t61 = 0;
- if (len <= 0) len= -1;
- if (s == NULL) return(V_ASN1_PRINTABLESTRING);
+ if (len <= 0)
+ len = -1;
+ if (s == NULL)
+ return (V_ASN1_PRINTABLESTRING);
- while ((*s) && (len-- != 0))
- {
- c= *(s++);
- if (!( ((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- (c == ' ') ||
- ((c >= '0') && (c <= '9')) ||
- (c == ' ') || (c == '\'') ||
- (c == '(') || (c == ')') ||
- (c == '+') || (c == ',') ||
- (c == '-') || (c == '.') ||
- (c == '/') || (c == ':') ||
- (c == '=') || (c == '?')))
- ia5=1;
- if (c&0x80)
- t61=1;
- }
- if (t61) return(V_ASN1_T61STRING);
- if (ia5) return(V_ASN1_IA5STRING);
- return(V_ASN1_PRINTABLESTRING);
- }
+ while ((*s) && (len-- != 0)) {
+ c = *(s++);
+ if (!(((c >= 'a') && (c <= 'z')) ||
+ ((c >= 'A') && (c <= 'Z')) ||
+ (c == ' ') ||
+ ((c >= '0') && (c <= '9')) ||
+ (c == ' ') || (c == '\'') ||
+ (c == '(') || (c == ')') ||
+ (c == '+') || (c == ',') ||
+ (c == '-') || (c == '.') ||
+ (c == '/') || (c == ':') || (c == '=') || (c == '?')))
+ ia5 = 1;
+ if (c & 0x80)
+ t61 = 1;
+ }
+ if (t61)
+ return (V_ASN1_T61STRING);
+ if (ia5)
+ return (V_ASN1_IA5STRING);
+ return (V_ASN1_PRINTABLESTRING);
+}
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
- {
- int i;
- unsigned char *p;
+{
+ int i;
+ unsigned char *p;
- if (s->type != V_ASN1_UNIVERSALSTRING) return(0);
- if ((s->length%4) != 0) return(0);
- p=s->data;
- for (i=0; i<s->length; i+=4)
- {
- if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
- break;
- else
- p+=4;
- }
- if (i < s->length) return(0);
- p=s->data;
- for (i=3; i<s->length; i+=4)
- {
- *(p++)=s->data[i];
- }
- *(p)='\0';
- s->length/=4;
- s->type=ASN1_PRINTABLE_type(s->data,s->length);
- return(1);
- }
+ if (s->type != V_ASN1_UNIVERSALSTRING)
+ return (0);
+ if ((s->length % 4) != 0)
+ return (0);
+ p = s->data;
+ for (i = 0; i < s->length; i += 4) {
+ if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
+ break;
+ else
+ p += 4;
+ }
+ if (i < s->length)
+ return (0);
+ p = s->data;
+ for (i = 3; i < s->length; i += 4) {
+ *(p++) = s->data[i];
+ }
+ *(p) = '\0';
+ s->length /= 4;
+ s->type = ASN1_PRINTABLE_type(s->data, s->length);
+ return (1);
+}
diff --git a/src/crypto/asn1/a_strnid.c b/src/crypto/asn1/a_strnid.c
index d4316f72..ba1224ef 100644
--- a/src/crypto/asn1/a_strnid.c
+++ b/src/crypto/asn1/a_strnid.c
@@ -56,231 +56,253 @@
#include <openssl/asn1.h>
-#include <stdlib.h> /* For bsearch */
+#include <stdlib.h> /* For bsearch */
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
-
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
-/* This is the global mask for the mbstring functions: this is use to
- * mask out certain types (such as BMPString and UTF8String) because
- * certain software (e.g. Netscape) has problems with them.
+/*
+ * This is the global mask for the mbstring functions: this is use to mask
+ * out certain types (such as BMPString and UTF8String) because certain
+ * software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void ASN1_STRING_set_default_mask(unsigned long mask)
{
- global_mask = mask;
+ global_mask = mask;
}
unsigned long ASN1_STRING_get_default_mask(void)
{
- return global_mask;
+ return global_mask;
}
-/* This function sets the default to various "flavours" of configuration.
- * based on an ASCII string. Currently this is:
- * MASK:XXXX : a numerical mask value.
- * nobmp : Don't use BMPStrings (just Printable, T61).
- * pkix : PKIX recommendation in RFC2459.
- * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
- * default: the default value, Printable, T61, BMP.
+/*
+ * This function sets the default to various "flavours" of configuration.
+ * based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
+ * value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
+ * recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
+ * recommendation for 2004). default: the default value, Printable, T61, BMP.
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
{
- unsigned long mask;
- char *end;
- if(!strncmp(p, "MASK:", 5)) {
- if(!p[5]) return 0;
- mask = strtoul(p + 5, &end, 0);
- if(*end) return 0;
- } else if(!strcmp(p, "nombstr"))
- mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
- else if(!strcmp(p, "pkix"))
- mask = ~((unsigned long)B_ASN1_T61STRING);
- else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
- else if(!strcmp(p, "default"))
- mask = 0xFFFFFFFFL;
- else return 0;
- ASN1_STRING_set_default_mask(mask);
- return 1;
+ unsigned long mask;
+ char *end;
+ if (!strncmp(p, "MASK:", 5)) {
+ if (!p[5])
+ return 0;
+ mask = strtoul(p + 5, &end, 0);
+ if (*end)
+ return 0;
+ } else if (!strcmp(p, "nombstr"))
+ mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
+ else if (!strcmp(p, "pkix"))
+ mask = ~((unsigned long)B_ASN1_T61STRING);
+ else if (!strcmp(p, "utf8only"))
+ mask = B_ASN1_UTF8STRING;
+ else if (!strcmp(p, "default"))
+ mask = 0xFFFFFFFFL;
+ else
+ return 0;
+ ASN1_STRING_set_default_mask(mask);
+ return 1;
}
-/* The following function generates an ASN1_STRING based on limits in a table.
- * Frequently the types and length of an ASN1_STRING are restricted by a
- * corresponding OID. For example certificates and certificate requests.
+/*
+ * The following function generates an ASN1_STRING based on limits in a
+ * table. Frequently the types and length of an ASN1_STRING are restricted by
+ * a corresponding OID. For example certificates and certificate requests.
*/
-ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
- int inlen, int inform, int nid)
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+ const unsigned char *in, int inlen,
+ int inform, int nid)
{
- ASN1_STRING_TABLE *tbl;
- ASN1_STRING *str = NULL;
- unsigned long mask;
- int ret;
- if(!out) out = &str;
- tbl = ASN1_STRING_TABLE_get(nid);
- if(tbl) {
- mask = tbl->mask;
- if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask;
- ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
- tbl->minsize, tbl->maxsize);
- } else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask);
- if(ret <= 0) return NULL;
- return *out;
+ ASN1_STRING_TABLE *tbl;
+ ASN1_STRING *str = NULL;
+ unsigned long mask;
+ int ret;
+ if (!out)
+ out = &str;
+ tbl = ASN1_STRING_TABLE_get(nid);
+ if (tbl) {
+ mask = tbl->mask;
+ if (!(tbl->flags & STABLE_NO_MASK))
+ mask &= global_mask;
+ ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
+ tbl->minsize, tbl->maxsize);
+ } else
+ ret =
+ ASN1_mbstring_copy(out, in, inlen, inform,
+ DIRSTRING_TYPE & global_mask);
+ if (ret <= 0)
+ return NULL;
+ return *out;
}
-/* Now the tables and helper functions for the string table:
+/*
+ * Now the tables and helper functions for the string table:
*/
/* size limits: this stuff is taken straight from RFC3280 */
-#define ub_name 32768
-#define ub_common_name 64
-#define ub_locality_name 128
-#define ub_state_name 128
-#define ub_organization_name 64
-#define ub_organization_unit_name 64
-#define ub_title 64
-#define ub_email_address 128
-#define ub_serial_number 64
-
+#define ub_name 32768
+#define ub_common_name 64
+#define ub_locality_name 128
+#define ub_state_name 128
+#define ub_organization_name 64
+#define ub_organization_unit_name 64
+#define ub_title 64
+#define ub_email_address 128
+#define ub_serial_number 64
/* This table must be kept in NID order */
static const ASN1_STRING_TABLE tbl_standard[] = {
-{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
-{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
-{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
-{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
-{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
-{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
-{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
-{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
-{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
-{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
-{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
-{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
-{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
-{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
-{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
-{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
+ {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
+ {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+ {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
+ {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
+ {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
+ {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
+ 0},
+ {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
+ STABLE_NO_MASK},
+ {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
+ {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
+ {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
+ {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
+ {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
+ {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
+ {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
+ STABLE_NO_MASK},
+ {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
+ {NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
+ {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+ {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
+ {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
};
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
- const ASN1_STRING_TABLE **b)
+ const ASN1_STRING_TABLE **b)
{
- return (*a)->nid - (*b)->nid;
+ return (*a)->nid - (*b)->nid;
}
static int table_cmp(const void *in_a, const void *in_b)
{
- const ASN1_STRING_TABLE *a = in_a;
- const ASN1_STRING_TABLE *b = in_b;
- return a->nid - b->nid;
+ const ASN1_STRING_TABLE *a = in_a;
+ const ASN1_STRING_TABLE *b = in_b;
+ return a->nid - b->nid;
}
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
- int found;
- size_t idx;
- ASN1_STRING_TABLE *ttmp;
- ASN1_STRING_TABLE fnd;
- fnd.nid = nid;
-
- ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
- if(ttmp) return ttmp;
- if(!stable) return NULL;
- found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
- if (!found) return NULL;
- return sk_ASN1_STRING_TABLE_value(stable, idx);
+ int found;
+ size_t idx;
+ ASN1_STRING_TABLE *ttmp;
+ ASN1_STRING_TABLE fnd;
+ fnd.nid = nid;
+
+ ttmp =
+ bsearch(&fnd, tbl_standard,
+ sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
+ sizeof(ASN1_STRING_TABLE), table_cmp);
+ if (ttmp)
+ return ttmp;
+ if (!stable)
+ return NULL;
+ found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
+ if (!found)
+ return NULL;
+ return sk_ASN1_STRING_TABLE_value(stable, idx);
}
-
+
int ASN1_STRING_TABLE_add(int nid,
- long minsize, long maxsize, unsigned long mask,
- unsigned long flags)
+ long minsize, long maxsize, unsigned long mask,
+ unsigned long flags)
{
- ASN1_STRING_TABLE *tmp;
- char new_nid = 0;
- flags &= ~STABLE_FLAGS_MALLOC;
- if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
- if(!stable) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
- tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
- if(!tmp) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- tmp->flags = flags | STABLE_FLAGS_MALLOC;
- tmp->nid = nid;
- new_nid = 1;
- } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
- if(minsize != -1) tmp->minsize = minsize;
- if(maxsize != -1) tmp->maxsize = maxsize;
- tmp->mask = mask;
- if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
- return 1;
+ ASN1_STRING_TABLE *tmp;
+ char new_nid = 0;
+ flags &= ~STABLE_FLAGS_MALLOC;
+ if (!stable)
+ stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
+ if (!stable) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
+ tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
+ if (!tmp) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ tmp->flags = flags | STABLE_FLAGS_MALLOC;
+ tmp->nid = nid;
+ new_nid = 1;
+ } else
+ tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
+ if (minsize != -1)
+ tmp->minsize = minsize;
+ if (maxsize != -1)
+ tmp->maxsize = maxsize;
+ tmp->mask = mask;
+ if (new_nid)
+ sk_ASN1_STRING_TABLE_push(stable, tmp);
+ return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
- STACK_OF(ASN1_STRING_TABLE) *tmp;
- tmp = stable;
- if(!tmp) return;
- stable = NULL;
- sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
+ STACK_OF(ASN1_STRING_TABLE) *tmp;
+ tmp = stable;
+ if (!tmp)
+ return;
+ stable = NULL;
+ sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
static void st_free(ASN1_STRING_TABLE *tbl)
{
- if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
+ if (tbl->flags & STABLE_FLAGS_MALLOC)
+ OPENSSL_free(tbl);
}
-
#ifdef STRING_TABLE_TEST
-int
-main(void)
+int main(void)
{
- ASN1_STRING_TABLE *tmp;
- int i, last_nid = -1;
-
- for (tmp = tbl_standard, i = 0;
- i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
- {
- if (tmp->nid < last_nid)
- {
- last_nid = 0;
- break;
- }
- last_nid = tmp->nid;
- }
-
- if (last_nid != 0)
- {
- printf("Table order OK\n");
- exit(0);
- }
-
- for (tmp = tbl_standard, i = 0;
- i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
- printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
- OBJ_nid2ln(tmp->nid));
-
- return 0;
+ ASN1_STRING_TABLE *tmp;
+ int i, last_nid = -1;
+
+ for (tmp = tbl_standard, i = 0;
+ i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
+ if (tmp->nid < last_nid) {
+ last_nid = 0;
+ break;
+ }
+ last_nid = tmp->nid;
+ }
+
+ if (last_nid != 0) {
+ printf("Table order OK\n");
+ exit(0);
+ }
+
+ for (tmp = tbl_standard, i = 0;
+ i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
+ printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
+ OBJ_nid2ln(tmp->nid));
+
+ return 0;
}
#endif
diff --git a/src/crypto/asn1/a_time.c b/src/crypto/asn1/a_time.c
index ac2cb485..4391092a 100644
--- a/src/crypto/asn1/a_time.c
+++ b/src/crypto/asn1/a_time.c
@@ -67,12 +67,10 @@
#include "asn1_locl.h"
-
-/* This is an implementation of the ASN1 Time structure which is:
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * written by Steve Henson.
+/*
+ * This is an implementation of the ASN1 Time structure which is: Time ::=
+ * CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
+ * Henson.
*/
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
@@ -81,141 +79,139 @@ IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
#if 0
int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
- {
- if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
- return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
- a->type ,V_ASN1_UNIVERSAL));
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
- return -1;
- }
+{
+ if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
+ return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
+ a->type, V_ASN1_UNIVERSAL));
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
+ return -1;
+}
#endif
-
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
- {
- return ASN1_TIME_adj(s, t, 0, 0);
- }
+{
+ return ASN1_TIME_adj(s, t, 0, 0);
+}
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
- int offset_day, long offset_sec)
- {
- struct tm *ts;
- struct tm data;
-
- ts=OPENSSL_gmtime(&t,&data);
- if (ts == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
- return NULL;
- }
- if (offset_day || offset_sec)
- {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
- return NULL;
- }
- if((ts->tm_year >= 50) && (ts->tm_year < 150))
- return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
- return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
- }
+ int offset_day, long offset_sec)
+{
+ struct tm *ts;
+ struct tm data;
+
+ ts = OPENSSL_gmtime(&t, &data);
+ if (ts == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
+ return NULL;
+ }
+ if (offset_day || offset_sec) {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ return NULL;
+ }
+ if ((ts->tm_year >= 50) && (ts->tm_year < 150))
+ return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
+ return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
+}
int ASN1_TIME_check(ASN1_TIME *t)
- {
- if (t->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_check(t);
- else if (t->type == V_ASN1_UTCTIME)
- return ASN1_UTCTIME_check(t);
- return 0;
- }
+{
+ if (t->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_check(t);
+ else if (t->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_check(t);
+ return 0;
+}
/* Convert an ASN1_TIME structure to GeneralizedTime */
-ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
- {
- ASN1_GENERALIZEDTIME *ret;
- char *str;
- int newlen;
-
- if (!ASN1_TIME_check(t)) return NULL;
-
- if (!out || !*out)
- {
- if (!(ret = ASN1_GENERALIZEDTIME_new ()))
- return NULL;
- if (out) *out = ret;
- }
- else ret = *out;
-
- /* If already GeneralizedTime just copy across */
- if (t->type == V_ASN1_GENERALIZEDTIME)
- {
- if(!ASN1_STRING_set(ret, t->data, t->length))
- return NULL;
- return ret;
- }
-
- /* grow the string */
- if (!ASN1_STRING_set(ret, NULL, t->length + 2))
- return NULL;
- /* ASN1_STRING_set() allocated 'len + 1' bytes. */
- newlen = t->length + 2 + 1;
- str = (char *)ret->data;
- /* Work out the century and prepend */
- if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
- else BUF_strlcpy(str, "20", newlen);
-
- BUF_strlcat(str, (char *)t->data, newlen);
-
- return ret;
- }
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
+ ASN1_GENERALIZEDTIME **out)
+{
+ ASN1_GENERALIZEDTIME *ret;
+ char *str;
+ int newlen;
+
+ if (!ASN1_TIME_check(t))
+ return NULL;
+
+ if (!out || !*out) {
+ if (!(ret = ASN1_GENERALIZEDTIME_new()))
+ return NULL;
+ if (out)
+ *out = ret;
+ } else
+ ret = *out;
+
+ /* If already GeneralizedTime just copy across */
+ if (t->type == V_ASN1_GENERALIZEDTIME) {
+ if (!ASN1_STRING_set(ret, t->data, t->length))
+ return NULL;
+ return ret;
+ }
+
+ /* grow the string */
+ if (!ASN1_STRING_set(ret, NULL, t->length + 2))
+ return NULL;
+ /* ASN1_STRING_set() allocated 'len + 1' bytes. */
+ newlen = t->length + 2 + 1;
+ str = (char *)ret->data;
+ /* Work out the century and prepend */
+ if (t->data[0] >= '5')
+ BUF_strlcpy(str, "19", newlen);
+ else
+ BUF_strlcpy(str, "20", newlen);
+
+ BUF_strlcat(str, (char *)t->data, newlen);
+
+ return ret;
+}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
- {
- ASN1_TIME t;
-
- t.length = strlen(str);
- t.data = (unsigned char *)str;
- t.flags = 0;
-
- t.type = V_ASN1_UTCTIME;
-
- if (!ASN1_TIME_check(&t))
- {
- t.type = V_ASN1_GENERALIZEDTIME;
- if (!ASN1_TIME_check(&t))
- return 0;
- }
-
- if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
- return 0;
-
- return 1;
- }
+{
+ ASN1_TIME t;
+
+ t.length = strlen(str);
+ t.data = (unsigned char *)str;
+ t.flags = 0;
+
+ t.type = V_ASN1_UTCTIME;
+
+ if (!ASN1_TIME_check(&t)) {
+ t.type = V_ASN1_GENERALIZEDTIME;
+ if (!ASN1_TIME_check(&t))
+ return 0;
+ }
+
+ if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
+ return 0;
+
+ return 1;
+}
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
- {
- if (t == NULL)
- {
- time_t now_t;
- time(&now_t);
- if (OPENSSL_gmtime(&now_t, tm))
- return 1;
- return 0;
- }
-
- if (t->type == V_ASN1_UTCTIME)
- return asn1_utctime_to_tm(tm, t);
- else if (t->type == V_ASN1_GENERALIZEDTIME)
- return asn1_generalizedtime_to_tm(tm, t);
-
- return 0;
- }
+{
+ if (t == NULL) {
+ time_t now_t;
+ time(&now_t);
+ if (OPENSSL_gmtime(&now_t, tm))
+ return 1;
+ return 0;
+ }
+
+ if (t->type == V_ASN1_UTCTIME)
+ return asn1_utctime_to_tm(tm, t);
+ else if (t->type == V_ASN1_GENERALIZEDTIME)
+ return asn1_generalizedtime_to_tm(tm, t);
+
+ return 0;
+}
int ASN1_TIME_diff(int *pday, int *psec,
- const ASN1_TIME *from, const ASN1_TIME *to)
- {
- struct tm tm_from, tm_to;
- if (!asn1_time_to_tm(&tm_from, from))
- return 0;
- if (!asn1_time_to_tm(&tm_to, to))
- return 0;
- return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
- }
+ const ASN1_TIME *from, const ASN1_TIME *to)
+{
+ struct tm tm_from, tm_to;
+ if (!asn1_time_to_tm(&tm_from, from))
+ return 0;
+ if (!asn1_time_to_tm(&tm_to, to))
+ return 0;
+ return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
+}
diff --git a/src/crypto/asn1/a_type.c b/src/crypto/asn1/a_type.c
index fd3d5b11..ecd47342 100644
--- a/src/crypto/asn1/a_type.c
+++ b/src/crypto/asn1/a_type.c
@@ -61,100 +61,93 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
-
int ASN1_TYPE_get(ASN1_TYPE *a)
- {
- if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
- return(a->type);
- else
- return(0);
- }
+{
+ if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
+ return (a->type);
+ else
+ return (0);
+}
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
- {
- if (a->value.ptr != NULL)
- {
- ASN1_TYPE **tmp_a = &a;
- ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
- }
- a->type=type;
- if (type == V_ASN1_BOOLEAN)
- a->value.boolean = value ? 0xff : 0;
- else
- a->value.ptr=value;
- }
+{
+ if (a->value.ptr != NULL) {
+ ASN1_TYPE **tmp_a = &a;
+ ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
+ }
+ a->type = type;
+ if (type == V_ASN1_BOOLEAN)
+ a->value.boolean = value ? 0xff : 0;
+ else
+ 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(value);
- if (!sdup)
- return 0;
- ASN1_TYPE_set(a, type, sdup);
- }
- return 1;
- }
+{
+ 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(value);
+ if (!sdup)
+ return 0;
+ ASN1_TYPE_set(a, type, sdup);
+ }
+ return 1;
+}
/* Returns 0 if they are equal, != 0 otherwise. */
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
- {
- int result = -1;
+{
+ int result = -1;
- if (!a || !b || a->type != b->type) return -1;
+ if (!a || !b || a->type != b->type)
+ return -1;
- switch (a->type)
- {
- case V_ASN1_OBJECT:
- result = OBJ_cmp(a->value.object, b->value.object);
- break;
- case V_ASN1_NULL:
- result = 0; /* They do not have content. */
- break;
- case V_ASN1_BOOLEAN:
- result = a->value.boolean - b->value.boolean;
- break;
- case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
- case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
- case V_ASN1_BIT_STRING:
- case V_ASN1_OCTET_STRING:
- case V_ASN1_SEQUENCE:
- case V_ASN1_SET:
- case V_ASN1_NUMERICSTRING:
- case V_ASN1_PRINTABLESTRING:
- case V_ASN1_T61STRING:
- case V_ASN1_VIDEOTEXSTRING:
- case V_ASN1_IA5STRING:
- case V_ASN1_UTCTIME:
- case V_ASN1_GENERALIZEDTIME:
- case V_ASN1_GRAPHICSTRING:
- case V_ASN1_VISIBLESTRING:
- case V_ASN1_GENERALSTRING:
- case V_ASN1_UNIVERSALSTRING:
- case V_ASN1_BMPSTRING:
- case V_ASN1_UTF8STRING:
- case V_ASN1_OTHER:
- default:
- result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
- (ASN1_STRING *) b->value.ptr);
- break;
- }
+ switch (a->type) {
+ case V_ASN1_OBJECT:
+ result = OBJ_cmp(a->value.object, b->value.object);
+ break;
+ case V_ASN1_NULL:
+ result = 0; /* They do not have content. */
+ break;
+ case V_ASN1_BOOLEAN:
+ result = a->value.boolean - b->value.boolean;
+ break;
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_ENUMERATED:
+ case V_ASN1_BIT_STRING:
+ case V_ASN1_OCTET_STRING:
+ case V_ASN1_SEQUENCE:
+ case V_ASN1_SET:
+ case V_ASN1_NUMERICSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_VIDEOTEXSTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ case V_ASN1_GRAPHICSTRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_OTHER:
+ default:
+ result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
+ (ASN1_STRING *)b->value.ptr);
+ break;
+ }
- return result;
- }
+ return result;
+}
diff --git a/src/crypto/asn1/a_utctm.c b/src/crypto/asn1/a_utctm.c
index dbbbecb4..5a55bd24 100644
--- a/src/crypto/asn1/a_utctm.c
+++ b/src/crypto/asn1/a_utctm.c
@@ -63,280 +63,273 @@
#include <openssl/mem.h>
#include <openssl/time_support.h>
+#include "asn1_locl.h"
#if 0
int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
- {
- return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
- V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
- }
-
+{
+ return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
+ V_ASN1_UTCTIME, V_ASN1_UNIVERSAL));
+}
ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
- long length)
- {
- ASN1_UTCTIME *ret=NULL;
-
- ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
- V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
- return(NULL);
- }
- if (!ASN1_UTCTIME_check(ret))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
- goto err;
- }
-
- return(ret);
-err:
- if ((ret != NULL) && ((a == NULL) || (*a != ret)))
- M_ASN1_UTCTIME_free(ret);
- return(NULL);
- }
+ long length)
+{
+ ASN1_UTCTIME *ret = NULL;
+
+ ret = (ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length,
+ V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
+ return (NULL);
+ }
+ if (!ASN1_UTCTIME_check(ret)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
+ goto err;
+ }
+
+ return (ret);
+ err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_UTCTIME_free(ret);
+ return (NULL);
+}
#endif
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
- {
- static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
- static const int max[8]={99,12,31,23,59,59,12,59};
- char *a;
- int n,i,l,o;
-
- if (d->type != V_ASN1_UTCTIME) return(0);
- l=d->length;
- a=(char *)d->data;
- o=0;
-
- if (l < 11) goto err;
- for (i=0; i<6; i++)
- {
- if ((i == 5) && ((a[o] == 'Z') ||
- (a[o] == '+') || (a[o] == '-')))
- {
- i++;
- if (tm)
- tm->tm_sec = 0;
- break;
- }
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n= a[o]-'0';
- if (++o > l) goto err;
-
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n=(n*10)+ a[o]-'0';
- if (++o > l) goto err;
-
- if ((n < min[i]) || (n > max[i])) goto err;
- if (tm)
- {
- switch(i)
- {
- case 0:
- tm->tm_year = n < 50 ? n + 100 : n;
- break;
- case 1:
- tm->tm_mon = n - 1;
- break;
- case 2:
- tm->tm_mday = n;
- break;
- case 3:
- tm->tm_hour = n;
- break;
- case 4:
- tm->tm_min = n;
- break;
- case 5:
- tm->tm_sec = n;
- break;
- }
- }
- }
- if (a[o] == 'Z')
- o++;
- else if ((a[o] == '+') || (a[o] == '-'))
- {
- int offsign = a[o] == '-' ? -1 : 1, offset = 0;
- o++;
- if (o+4 > l) goto err;
- for (i=6; i<8; i++)
- {
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n= a[o]-'0';
- o++;
- if ((a[o] < '0') || (a[o] > '9')) goto err;
- n=(n*10)+ a[o]-'0';
- if ((n < min[i]) || (n > max[i])) goto err;
- if (tm)
- {
- if (i == 6)
- offset = n * 3600;
- else if (i == 7)
- offset += n * 60;
- }
- o++;
- }
- if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
- return 0;
- }
- return o == l;
-err:
- return 0;
- }
+{
+ static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
+ static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
+ char *a;
+ int n, i, l, o;
+
+ if (d->type != V_ASN1_UTCTIME)
+ return (0);
+ l = d->length;
+ a = (char *)d->data;
+ o = 0;
+
+ if (l < 11)
+ goto err;
+ for (i = 0; i < 6; i++) {
+ if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
+ i++;
+ if (tm)
+ tm->tm_sec = 0;
+ break;
+ }
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = a[o] - '0';
+ if (++o > l)
+ goto err;
+
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = (n * 10) + a[o] - '0';
+ if (++o > l)
+ goto err;
+
+ if ((n < min[i]) || (n > max[i]))
+ goto err;
+ if (tm) {
+ switch (i) {
+ case 0:
+ tm->tm_year = n < 50 ? n + 100 : n;
+ break;
+ case 1:
+ tm->tm_mon = n - 1;
+ break;
+ case 2:
+ tm->tm_mday = n;
+ break;
+ case 3:
+ tm->tm_hour = n;
+ break;
+ case 4:
+ tm->tm_min = n;
+ break;
+ case 5:
+ tm->tm_sec = n;
+ break;
+ }
+ }
+ }
+ if (a[o] == 'Z')
+ o++;
+ else if ((a[o] == '+') || (a[o] == '-')) {
+ int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+ o++;
+ if (o + 4 > l)
+ goto err;
+ for (i = 6; i < 8; i++) {
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = a[o] - '0';
+ o++;
+ if ((a[o] < '0') || (a[o] > '9'))
+ goto err;
+ n = (n * 10) + a[o] - '0';
+ if ((n < min[i]) || (n > max[i]))
+ goto err;
+ if (tm) {
+ if (i == 6)
+ offset = n * 3600;
+ else if (i == 7)
+ offset += n * 60;
+ }
+ o++;
+ }
+ if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+ return 0;
+ }
+ return o == l;
+ err:
+ return 0;
+}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
- {
- return asn1_utctime_to_tm(NULL, d);
- }
+{
+ return asn1_utctime_to_tm(NULL, d);
+}
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
- {
- ASN1_UTCTIME t;
-
- t.type=V_ASN1_UTCTIME;
- t.length=strlen(str);
- t.data=(unsigned char *)str;
- if (ASN1_UTCTIME_check(&t))
- {
- if (s != NULL)
- {
- if (!ASN1_STRING_set((ASN1_STRING *)s,
- (unsigned char *)str,t.length))
- return 0;
- s->type = V_ASN1_UTCTIME;
- }
- return(1);
- }
- else
- return(0);
- }
+{
+ ASN1_UTCTIME t;
+
+ t.type = V_ASN1_UTCTIME;
+ t.length = strlen(str);
+ t.data = (unsigned char *)str;
+ if (ASN1_UTCTIME_check(&t)) {
+ if (s != NULL) {
+ if (!ASN1_STRING_set((ASN1_STRING *)s,
+ (unsigned char *)str, t.length))
+ return 0;
+ s->type = V_ASN1_UTCTIME;
+ }
+ return (1);
+ } else
+ return (0);
+}
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
- {
- return ASN1_UTCTIME_adj(s, t, 0, 0);
- }
+{
+ return ASN1_UTCTIME_adj(s, t, 0, 0);
+}
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
- int offset_day, long offset_sec)
- {
- char *p;
- struct tm *ts;
- struct tm data;
- size_t len = 20;
- int free_s = 0;
-
- if (s == NULL)
- {
- free_s = 1;
- s=M_ASN1_UTCTIME_new();
- }
- if (s == NULL)
- goto err;
-
-
- ts=OPENSSL_gmtime(&t, &data);
- if (ts == NULL)
- goto err;
-
- if (offset_day || offset_sec)
- {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
- goto err;
- }
-
- if((ts->tm_year < 50) || (ts->tm_year >= 150))
- goto err;
-
- p=(char *)s->data;
- if ((p == NULL) || ((size_t)s->length < len))
- {
- p=OPENSSL_malloc(len);
- if (p == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (s->data != NULL)
- OPENSSL_free(s->data);
- s->data=(unsigned char *)p;
- }
-
- BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
- ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
- s->length=strlen(p);
- s->type=V_ASN1_UTCTIME;
- return(s);
- err:
- if (free_s && s)
- M_ASN1_UTCTIME_free(s);
- return NULL;
- }
-
+ int offset_day, long offset_sec)
+{
+ char *p;
+ struct tm *ts;
+ struct tm data;
+ size_t len = 20;
+ int free_s = 0;
+
+ if (s == NULL) {
+ free_s = 1;
+ s = M_ASN1_UTCTIME_new();
+ }
+ if (s == NULL)
+ goto err;
+
+ ts = OPENSSL_gmtime(&t, &data);
+ if (ts == NULL)
+ goto err;
+
+ if (offset_day || offset_sec) {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ goto err;
+ }
+
+ if ((ts->tm_year < 50) || (ts->tm_year >= 150))
+ goto err;
+
+ p = (char *)s->data;
+ if ((p == NULL) || ((size_t)s->length < len)) {
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (s->data != NULL)
+ OPENSSL_free(s->data);
+ s->data = (unsigned char *)p;
+ }
+
+ BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
+ ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
+ ts->tm_sec);
+ s->length = strlen(p);
+ s->type = V_ASN1_UTCTIME;
+ return (s);
+ err:
+ if (free_s && s)
+ M_ASN1_UTCTIME_free(s);
+ return NULL;
+}
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
- {
- struct tm stm, ttm;
- int day, sec;
-
- if (!asn1_utctime_to_tm(&stm, s))
- return -2;
-
- if (!OPENSSL_gmtime(&t, &ttm))
- return -2;
-
- if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
- return -2;
-
- if (day > 0)
- return 1;
- if (day < 0)
- return -1;
- if (sec > 0)
- return 1;
- if (sec < 0)
- return -1;
- return 0;
- }
-
+{
+ struct tm stm, ttm;
+ int day, sec;
+
+ if (!asn1_utctime_to_tm(&stm, s))
+ return -2;
+
+ if (!OPENSSL_gmtime(&t, &ttm))
+ return -2;
+
+ if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
+ return -2;
+
+ if (day > 0)
+ return 1;
+ if (day < 0)
+ return -1;
+ if (sec > 0)
+ return 1;
+ if (sec < 0)
+ return -1;
+ return 0;
+}
#if 0
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
- {
- struct tm tm;
- int offset;
-
- memset(&tm,'\0',sizeof tm);
-
-#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
- tm.tm_year=g2(s->data);
- if(tm.tm_year < 50)
- tm.tm_year+=100;
- tm.tm_mon=g2(s->data+2)-1;
- tm.tm_mday=g2(s->data+4);
- tm.tm_hour=g2(s->data+6);
- tm.tm_min=g2(s->data+8);
- tm.tm_sec=g2(s->data+10);
- if(s->data[12] == 'Z')
- offset=0;
- else
- {
- offset=g2(s->data+13)*60+g2(s->data+15);
- if(s->data[12] == '-')
- offset= -offset;
- }
-#undef g2
-
- return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
- * instead of UTC, and unless we rewrite OpenSSL
- * in Lisp we cannot locally change the timezone
- * without possibly interfering with other parts
- * of the program. timegm, which uses UTC, is
- * non-standard.
- * Also time_t is inappropriate for general
- * UTC times because it may a 32 bit type. */
- }
+{
+ struct tm tm;
+ int offset;
+
+ memset(&tm, '\0', sizeof tm);
+
+# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
+ tm.tm_year = g2(s->data);
+ if (tm.tm_year < 50)
+ tm.tm_year += 100;
+ tm.tm_mon = g2(s->data + 2) - 1;
+ tm.tm_mday = g2(s->data + 4);
+ tm.tm_hour = g2(s->data + 6);
+ tm.tm_min = g2(s->data + 8);
+ tm.tm_sec = g2(s->data + 10);
+ if (s->data[12] == 'Z')
+ offset = 0;
+ else {
+ offset = g2(s->data + 13) * 60 + g2(s->data + 15);
+ if (s->data[12] == '-')
+ offset = -offset;
+ }
+# undef g2
+
+ return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
+ * timezone instead of UTC, and unless
+ * we rewrite OpenSSL in Lisp we cannot
+ * locally change the timezone without
+ * possibly interfering with other
+ * parts of the program. timegm, which
+ * uses UTC, is non-standard. Also
+ * time_t is inappropriate for general
+ * UTC times because it may a 32 bit
+ * type. */
+}
#endif
diff --git a/src/crypto/asn1/a_utf8.c b/src/crypto/asn1/a_utf8.c
index ed6e98d3..17027686 100644
--- a/src/crypto/asn1/a_utf8.c
+++ b/src/crypto/asn1/a_utf8.c
@@ -59,152 +59,176 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
/* UTF8 utilities */
-/* This parses a UTF8 string one character at a time. It is passed a pointer
- * to the string and the length of the string. It sets 'value' to the value of
- * the current character. It returns the number of characters read or a
- * negative error code:
- * -1 = string too short
- * -2 = illegal character
- * -3 = subsequent characters not of the form 10xxxxxx
- * -4 = character encoded incorrectly (not minimal length).
+/*
+ * This parses a UTF8 string one character at a time. It is passed a pointer
+ * to the string and the length of the string. It sets 'value' to the value
+ * of the current character. It returns the number of characters read or a
+ * negative error code: -1 = string too short -2 = illegal character -3 =
+ * subsequent characters not of the form 10xxxxxx -4 = character encoded
+ * incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
- const unsigned char *p;
- unsigned long value;
- int ret;
- if(len <= 0) return 0;
- p = str;
+ const unsigned char *p;
+ unsigned long value;
+ int ret;
+ if (len <= 0)
+ return 0;
+ p = str;
- /* Check syntax and work out the encoded value (if correct) */
- if((*p & 0x80) == 0) {
- value = *p++ & 0x7f;
- ret = 1;
- } else if((*p & 0xe0) == 0xc0) {
- if(len < 2) return -1;
- if((p[1] & 0xc0) != 0x80) return -3;
- value = (*p++ & 0x1f) << 6;
- value |= *p++ & 0x3f;
- if(value < 0x80) return -4;
- ret = 2;
- } else if((*p & 0xf0) == 0xe0) {
- if(len < 3) return -1;
- if( ((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80) ) return -3;
- value = (*p++ & 0xf) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if(value < 0x800) return -4;
- ret = 3;
- } else if((*p & 0xf8) == 0xf0) {
- if(len < 4) return -1;
- if( ((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80)
- || ((p[3] & 0xc0) != 0x80) ) return -3;
- value = ((unsigned long)(*p++ & 0x7)) << 18;
- value |= (*p++ & 0x3f) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if(value < 0x10000) return -4;
- ret = 4;
- } else if((*p & 0xfc) == 0xf8) {
- if(len < 5) return -1;
- if( ((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80)
- || ((p[3] & 0xc0) != 0x80)
- || ((p[4] & 0xc0) != 0x80) ) return -3;
- value = ((unsigned long)(*p++ & 0x3)) << 24;
- value |= ((unsigned long)(*p++ & 0x3f)) << 18;
- value |= ((unsigned long)(*p++ & 0x3f)) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if(value < 0x200000) return -4;
- ret = 5;
- } else if((*p & 0xfe) == 0xfc) {
- if(len < 6) return -1;
- if( ((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80)
- || ((p[3] & 0xc0) != 0x80)
- || ((p[4] & 0xc0) != 0x80)
- || ((p[5] & 0xc0) != 0x80) ) return -3;
- value = ((unsigned long)(*p++ & 0x1)) << 30;
- value |= ((unsigned long)(*p++ & 0x3f)) << 24;
- value |= ((unsigned long)(*p++ & 0x3f)) << 18;
- value |= ((unsigned long)(*p++ & 0x3f)) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if(value < 0x4000000) return -4;
- ret = 6;
- } else return -2;
- *val = value;
- return ret;
+ /* Check syntax and work out the encoded value (if correct) */
+ if ((*p & 0x80) == 0) {
+ value = *p++ & 0x7f;
+ ret = 1;
+ } else if ((*p & 0xe0) == 0xc0) {
+ if (len < 2)
+ return -1;
+ if ((p[1] & 0xc0) != 0x80)
+ return -3;
+ value = (*p++ & 0x1f) << 6;
+ value |= *p++ & 0x3f;
+ if (value < 0x80)
+ return -4;
+ ret = 2;
+ } else if ((*p & 0xf0) == 0xe0) {
+ if (len < 3)
+ return -1;
+ if (((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80))
+ return -3;
+ value = (*p++ & 0xf) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if (value < 0x800)
+ return -4;
+ ret = 3;
+ } else if ((*p & 0xf8) == 0xf0) {
+ if (len < 4)
+ return -1;
+ if (((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80)
+ || ((p[3] & 0xc0) != 0x80))
+ return -3;
+ value = ((unsigned long)(*p++ & 0x7)) << 18;
+ value |= (*p++ & 0x3f) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if (value < 0x10000)
+ return -4;
+ ret = 4;
+ } else if ((*p & 0xfc) == 0xf8) {
+ if (len < 5)
+ return -1;
+ if (((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80)
+ || ((p[3] & 0xc0) != 0x80)
+ || ((p[4] & 0xc0) != 0x80))
+ return -3;
+ value = ((unsigned long)(*p++ & 0x3)) << 24;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if (value < 0x200000)
+ return -4;
+ ret = 5;
+ } else if ((*p & 0xfe) == 0xfc) {
+ if (len < 6)
+ return -1;
+ if (((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80)
+ || ((p[3] & 0xc0) != 0x80)
+ || ((p[4] & 0xc0) != 0x80)
+ || ((p[5] & 0xc0) != 0x80))
+ return -3;
+ value = ((unsigned long)(*p++ & 0x1)) << 30;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 24;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if (value < 0x4000000)
+ return -4;
+ ret = 6;
+ } else
+ return -2;
+ *val = value;
+ return ret;
}
-/* This takes a character 'value' and writes the UTF8 encoded value in
- * 'str' where 'str' is a buffer containing 'len' characters. Returns
- * the number of characters written or -1 if 'len' is too small. 'str' can
- * be set to NULL in which case it just returns the number of characters.
- * It will need at most 6 characters.
+/*
+ * This takes a character 'value' and writes the UTF8 encoded value in 'str'
+ * where 'str' is a buffer containing 'len' characters. Returns the number of
+ * characters written or -1 if 'len' is too small. 'str' can be set to NULL
+ * in which case it just returns the number of characters. It will need at
+ * most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, unsigned long value)
{
- if(!str) len = 6; /* Maximum we will need */
- else if(len <= 0) return -1;
- if(value < 0x80) {
- if(str) *str = (unsigned char)value;
- return 1;
- }
- if(value < 0x800) {
- if(len < 2) return -1;
- if(str) {
- *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 2;
- }
- if(value < 0x10000) {
- if(len < 3) return -1;
- if(str) {
- *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 3;
- }
- if(value < 0x200000) {
- if(len < 4) return -1;
- if(str) {
- *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
- *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 4;
- }
- if(value < 0x4000000) {
- if(len < 5) return -1;
- if(str) {
- *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
- *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 5;
- }
- if(len < 6) return -1;
- if(str) {
- *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
- *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 6;
+ if (!str)
+ len = 6; /* Maximum we will need */
+ else if (len <= 0)
+ return -1;
+ if (value < 0x80) {
+ if (str)
+ *str = (unsigned char)value;
+ return 1;
+ }
+ if (value < 0x800) {
+ if (len < 2)
+ return -1;
+ if (str) {
+ *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 2;
+ }
+ if (value < 0x10000) {
+ if (len < 3)
+ return -1;
+ if (str) {
+ *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 3;
+ }
+ if (value < 0x200000) {
+ if (len < 4)
+ return -1;
+ if (str) {
+ *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 4;
+ }
+ if (value < 0x4000000) {
+ if (len < 5)
+ return -1;
+ if (str) {
+ *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
+ *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 5;
+ }
+ if (len < 6)
+ return -1;
+ if (str) {
+ *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
+ *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 6;
}
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
index 0f2ce505..b637e795 100644
--- a/src/crypto/asn1/asn1_lib.c
+++ b/src/crypto/asn1/asn1_lib.c
@@ -63,12 +63,19 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
-/* Cross-module errors from crypto/x509/i2d_pr.c */
+/* Cross-module errors from crypto/x509/i2d_pr.c. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
-/* Cross-module errors from crypto/x509/asn1_gen.c.
- * TODO(davidben): Remove these once asn1_gen.c is gone. */
+/* Cross-module errors from crypto/x509/algorithm.c. */
+OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE);
+/*
+ * Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
+ * these once asn1_gen.c is gone.
+ */
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
@@ -93,414 +100,406 @@ OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
-static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
+static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
+ long max);
static void asn1_put_length(unsigned char **pp, int length);
static int _asn1_check_infinite_end(const unsigned char **p, long len)
- {
- /* If there is 0 or 1 byte left, the length check should pick
- * things up */
- if (len <= 0)
- return(1);
- else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
- {
- (*p)+=2;
- return(1);
- }
- return(0);
- }
+{
+ /*
+ * If there is 0 or 1 byte left, the length check should pick things up
+ */
+ if (len <= 0)
+ return (1);
+ else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
+ (*p) += 2;
+ return (1);
+ }
+ return (0);
+}
int ASN1_check_infinite_end(unsigned char **p, long len)
- {
- return _asn1_check_infinite_end((const unsigned char **)p, len);
- }
+{
+ return _asn1_check_infinite_end((const unsigned char **)p, len);
+}
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
- {
- return _asn1_check_infinite_end(p, len);
- }
-
+{
+ return _asn1_check_infinite_end(p, len);
+}
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
- int *pclass, long omax)
- {
- int i,ret;
- long l;
- const unsigned char *p= *pp;
- int tag,xclass,inf;
- long max=omax;
-
- if (!max) goto err;
- ret=(*p&V_ASN1_CONSTRUCTED);
- xclass=(*p&V_ASN1_PRIVATE);
- i= *p&V_ASN1_PRIMITIVE_TAG;
- if (i == V_ASN1_PRIMITIVE_TAG)
- { /* high-tag */
- p++;
- if (--max == 0) goto err;
- l=0;
- while (*p&0x80)
- {
- l<<=7L;
- l|= *(p++)&0x7f;
- if (--max == 0) goto err;
- if (l > (INT_MAX >> 7L)) goto err;
- }
- l<<=7L;
- l|= *(p++)&0x7f;
- tag=(int)l;
- if (--max == 0) goto err;
- }
- else
- {
- tag=i;
- p++;
- if (--max == 0) goto err;
- }
- *ptag=tag;
- *pclass=xclass;
- if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
-
- if (inf && !(ret & V_ASN1_CONSTRUCTED))
- goto err;
+ int *pclass, long omax)
+{
+ int i, ret;
+ long l;
+ const unsigned char *p = *pp;
+ int tag, xclass, inf;
+ long max = omax;
+
+ if (!max)
+ goto err;
+ ret = (*p & V_ASN1_CONSTRUCTED);
+ xclass = (*p & V_ASN1_PRIVATE);
+ i = *p & V_ASN1_PRIMITIVE_TAG;
+ if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
+ p++;
+ if (--max == 0)
+ goto err;
+ l = 0;
+ while (*p & 0x80) {
+ l <<= 7L;
+ l |= *(p++) & 0x7f;
+ if (--max == 0)
+ goto err;
+ if (l > (INT_MAX >> 7L))
+ goto err;
+ }
+ l <<= 7L;
+ l |= *(p++) & 0x7f;
+ tag = (int)l;
+ if (--max == 0)
+ goto err;
+ } else {
+ tag = i;
+ p++;
+ if (--max == 0)
+ goto err;
+ }
+
+ /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
+ if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
+ goto err;
+
+ *ptag = tag;
+ *pclass = xclass;
+ if (!asn1_get_length(&p, &inf, plength, max))
+ goto err;
+
+ if (inf && !(ret & V_ASN1_CONSTRUCTED))
+ goto err;
#if 0
- fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
- (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
- (int)(omax+ *pp));
+ fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
+ (int)p, *plength, omax, (int)*pp, (int)(p + *plength),
+ (int)(omax + *pp));
#endif
- if (*plength > (omax - (p - *pp)))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- /* Set this so that even if things are not long enough
- * the values are set correctly */
- ret|=0x80;
- }
- *pp=p;
- return(ret|inf);
-err:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
- return(0x80);
- }
-
-static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
- {
- const unsigned char *p= *pp;
- unsigned long ret=0;
- unsigned int i;
-
- if (max-- < 1) return(0);
- if (*p == 0x80)
- {
- *inf=1;
- ret=0;
- p++;
- }
- else
- {
- *inf=0;
- i= *p&0x7f;
- if (*(p++) & 0x80)
- {
- if (i > sizeof(long))
- return 0;
- if (max-- == 0) return(0);
- while (i-- > 0)
- {
- ret<<=8L;
- ret|= *(p++);
- if (max-- == 0) return(0);
- }
- }
- else
- ret=i;
- }
- if (ret > LONG_MAX)
- return 0;
- *pp=p;
- *rl=(long)ret;
- return(1);
- }
-
-/* class 0 is constructed
- * constructed == 2 for indefinite length constructed */
+ if (*plength > (omax - (p - *pp))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ /*
+ * Set this so that even if things are not long enough the values are
+ * set correctly
+ */
+ ret |= 0x80;
+ }
+ *pp = p;
+ return (ret | inf);
+ err:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
+ return (0x80);
+}
+
+static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
+ long max)
+{
+ const unsigned char *p = *pp;
+ unsigned long ret = 0;
+ unsigned long i;
+
+ if (max-- < 1)
+ return 0;
+ if (*p == 0x80) {
+ *inf = 1;
+ ret = 0;
+ p++;
+ } else {
+ *inf = 0;
+ i = *p & 0x7f;
+ if (*(p++) & 0x80) {
+ if (i > sizeof(ret) || max < (long)i)
+ return 0;
+ while (i-- > 0) {
+ ret <<= 8L;
+ ret |= *(p++);
+ }
+ } else
+ ret = i;
+ }
+ if (ret > LONG_MAX)
+ return 0;
+ *pp = p;
+ *rl = (long)ret;
+ return 1;
+}
+
+/*
+ * class 0 is constructed constructed == 2 for indefinite length constructed
+ */
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
- int xclass)
- {
- unsigned char *p= *pp;
- int i, ttag;
-
- i=(constructed)?V_ASN1_CONSTRUCTED:0;
- i|=(xclass&V_ASN1_PRIVATE);
- if (tag < 31)
- *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
- else
- {
- *(p++)=i|V_ASN1_PRIMITIVE_TAG;
- for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
- ttag = i;
- while(i-- > 0)
- {
- p[i] = tag & 0x7f;
- if(i != (ttag - 1)) p[i] |= 0x80;
- tag >>= 7;
- }
- p += ttag;
- }
- if (constructed == 2)
- *(p++)=0x80;
- else
- asn1_put_length(&p,length);
- *pp=p;
- }
+ int xclass)
+{
+ unsigned char *p = *pp;
+ int i, ttag;
+
+ i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
+ i |= (xclass & V_ASN1_PRIVATE);
+ if (tag < 31)
+ *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
+ else {
+ *(p++) = i | V_ASN1_PRIMITIVE_TAG;
+ for (i = 0, ttag = tag; ttag > 0; i++)
+ ttag >>= 7;
+ ttag = i;
+ while (i-- > 0) {
+ p[i] = tag & 0x7f;
+ if (i != (ttag - 1))
+ p[i] |= 0x80;
+ tag >>= 7;
+ }
+ p += ttag;
+ }
+ if (constructed == 2)
+ *(p++) = 0x80;
+ else
+ asn1_put_length(&p, length);
+ *pp = p;
+}
int ASN1_put_eoc(unsigned char **pp)
- {
- unsigned char *p = *pp;
- *p++ = 0;
- *p++ = 0;
- *pp = p;
- return 2;
- }
+{
+ unsigned char *p = *pp;
+ *p++ = 0;
+ *p++ = 0;
+ *pp = p;
+ return 2;
+}
static void asn1_put_length(unsigned char **pp, int length)
- {
- unsigned char *p= *pp;
- int i,l;
- if (length <= 127)
- *(p++)=(unsigned char)length;
- else
- {
- l=length;
- for (i=0; l > 0; i++)
- l>>=8;
- *(p++)=i|0x80;
- l=i;
- while (i-- > 0)
- {
- p[i]=length&0xff;
- length>>=8;
- }
- p+=l;
- }
- *pp=p;
- }
+{
+ unsigned char *p = *pp;
+ int i, l;
+ if (length <= 127)
+ *(p++) = (unsigned char)length;
+ else {
+ l = length;
+ for (i = 0; l > 0; i++)
+ l >>= 8;
+ *(p++) = i | 0x80;
+ l = i;
+ while (i-- > 0) {
+ p[i] = length & 0xff;
+ length >>= 8;
+ }
+ p += l;
+ }
+ *pp = p;
+}
int ASN1_object_size(int constructed, int length, int tag)
- {
- int ret;
-
- ret=length;
- ret++;
- if (tag >= 31)
- {
- while (tag > 0)
- {
- tag>>=7;
- ret++;
- }
- }
- if (constructed == 2)
- return ret + 3;
- ret++;
- if (length > 127)
- {
- while (length > 0)
- {
- length>>=8;
- ret++;
- }
- }
- return(ret);
- }
+{
+ int ret;
+
+ ret = length;
+ ret++;
+ if (tag >= 31) {
+ while (tag > 0) {
+ tag >>= 7;
+ ret++;
+ }
+ }
+ if (constructed == 2)
+ return ret + 3;
+ ret++;
+ if (length > 127) {
+ while (length > 0) {
+ length >>= 8;
+ ret++;
+ }
+ }
+ return (ret);
+}
static int _asn1_Finish(ASN1_const_CTX *c)
- {
- if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
- {
- if (!ASN1_const_check_infinite_end(&c->p,c->slen))
- {
- c->error=ASN1_R_MISSING_ASN1_EOS;
- return(0);
- }
- }
- if ( ((c->slen != 0) && !(c->inf & 1)) ||
- ((c->slen < 0) && (c->inf & 1)))
- {
- c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
- return(0);
- }
- return(1);
- }
+{
+ if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
+ if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
+ c->error = ASN1_R_MISSING_ASN1_EOS;
+ return (0);
+ }
+ }
+ if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
+ c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
+ return (0);
+ }
+ return (1);
+}
int asn1_Finish(ASN1_CTX *c)
- {
- return _asn1_Finish((ASN1_const_CTX *)c);
- }
+{
+ return _asn1_Finish((ASN1_const_CTX *)c);
+}
int asn1_const_Finish(ASN1_const_CTX *c)
- {
- return _asn1_Finish(c);
- }
+{
+ return _asn1_Finish(c);
+}
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
- {
- const unsigned char *q;
-
- q=c->p;
- c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
- *length);
- if (c->inf & 0x80)
- {
- c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
- return(0);
- }
- if (c->tag != V_ASN1_SEQUENCE)
- {
- c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
- return(0);
- }
- (*length)-=(c->p-q);
- if (c->max && (*length < 0))
- {
- c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
- return(0);
- }
- if (c->inf == (1|V_ASN1_CONSTRUCTED))
- c->slen= *length+ *(c->pp)-c->p;
- c->eos=0;
- return(1);
- }
+{
+ const unsigned char *q;
+
+ q = c->p;
+ c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass),
+ *length);
+ if (c->inf & 0x80) {
+ c->error = ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
+ return (0);
+ }
+ if (c->tag != V_ASN1_SEQUENCE) {
+ c->error = ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
+ return (0);
+ }
+ (*length) -= (c->p - q);
+ if (c->max && (*length < 0)) {
+ c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
+ return (0);
+ }
+ if (c->inf == (1 | V_ASN1_CONSTRUCTED))
+ c->slen = *length + *(c->pp) - c->p;
+ c->eos = 0;
+ return (1);
+}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
- {
- if (str == NULL)
- return 0;
- dst->type = str->type;
- if (!ASN1_STRING_set(dst,str->data,str->length))
- return 0;
- dst->flags = str->flags;
- return 1;
- }
+{
+ if (str == NULL)
+ return 0;
+ dst->type = str->type;
+ if (!ASN1_STRING_set(dst, str->data, str->length))
+ return 0;
+ dst->flags = str->flags;
+ return 1;
+}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
- {
- ASN1_STRING *ret;
- if (!str)
- return NULL;
- ret=ASN1_STRING_new();
- if (!ret)
- return NULL;
- if (!ASN1_STRING_copy(ret,str))
- {
- ASN1_STRING_free(ret);
- return NULL;
- }
- return ret;
- }
+{
+ ASN1_STRING *ret;
+ if (!str)
+ return NULL;
+ ret = ASN1_STRING_new();
+ if (!ret)
+ return NULL;
+ if (!ASN1_STRING_copy(ret, str)) {
+ ASN1_STRING_free(ret);
+ return NULL;
+ }
+ return ret;
+}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
- {
- unsigned char *c;
- const char *data=_data;
-
- if (len < 0)
- {
- if (data == NULL)
- return(0);
- else
- len=strlen(data);
- }
- if ((str->length < len) || (str->data == NULL))
- {
- c=str->data;
- if (c == NULL)
- str->data=OPENSSL_malloc(len+1);
- else
- str->data=OPENSSL_realloc(c,len+1);
-
- if (str->data == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- str->data=c;
- return(0);
- }
- }
- str->length=len;
- if (data != NULL)
- {
- memcpy(str->data,data,len);
- /* an allowance for strings :-) */
- str->data[len]='\0';
- }
- return(1);
- }
+{
+ unsigned char *c;
+ const char *data = _data;
+
+ if (len < 0) {
+ if (data == NULL)
+ return (0);
+ else
+ len = strlen(data);
+ }
+ if ((str->length < len) || (str->data == NULL)) {
+ c = str->data;
+ if (c == NULL)
+ str->data = OPENSSL_malloc(len + 1);
+ else
+ str->data = OPENSSL_realloc(c, len + 1);
+
+ if (str->data == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ str->data = c;
+ return (0);
+ }
+ }
+ str->length = len;
+ if (data != NULL) {
+ memcpy(str->data, data, len);
+ /* an allowance for strings :-) */
+ str->data[len] = '\0';
+ }
+ 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;
- }
+{
+ 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));
- }
-
+{
+ return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
+}
ASN1_STRING *ASN1_STRING_type_new(int type)
- {
- ASN1_STRING *ret;
-
- ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
- ret->length=0;
- ret->type=type;
- ret->data=NULL;
- ret->flags=0;
- return(ret);
- }
+{
+ ASN1_STRING *ret;
+
+ ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ ret->length = 0;
+ ret->type = type;
+ ret->data = NULL;
+ ret->flags = 0;
+ return (ret);
+}
void ASN1_STRING_free(ASN1_STRING *a)
- {
- if (a == NULL) return;
- if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
- OPENSSL_free(a->data);
- OPENSSL_free(a);
- }
+{
+ if (a == NULL)
+ return;
+ if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
+ OPENSSL_free(a->data);
+ OPENSSL_free(a);
+}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
- {
- int i;
-
- i=(a->length-b->length);
- if (i == 0)
- {
- i=memcmp(a->data,b->data,a->length);
- if (i == 0)
- return(a->type-b->type);
- else
- return(i);
- }
- else
- return(i);
- }
+{
+ int i;
+
+ i = (a->length - b->length);
+ if (i == 0) {
+ i = memcmp(a->data, b->data, a->length);
+ if (i == 0)
+ return (a->type - b->type);
+ else
+ return (i);
+ } else
+ return (i);
+}
int ASN1_STRING_length(const ASN1_STRING *x)
-{ return M_ASN1_STRING_length(x); }
+{
+ return M_ASN1_STRING_length(x);
+}
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
-{ M_ASN1_STRING_length_set(x, len); return; }
+{
+ M_ASN1_STRING_length_set(x, len);
+ return;
+}
int ASN1_STRING_type(ASN1_STRING *x)
-{ return M_ASN1_STRING_type(x); }
-
-unsigned char * ASN1_STRING_data(ASN1_STRING *x)
-{ return M_ASN1_STRING_data(x); }
+{
+ return M_ASN1_STRING_type(x);
+}
+
+unsigned char *ASN1_STRING_data(ASN1_STRING *x)
+{
+ return M_ASN1_STRING_data(x);
+}
diff --git a/src/crypto/asn1/asn1_locl.h b/src/crypto/asn1/asn1_locl.h
index ca5f6120..49eceb6b 100644
--- a/src/crypto/asn1/asn1_locl.h
+++ b/src/crypto/asn1/asn1_locl.h
@@ -1,6 +1,7 @@
/* asn1t.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2006.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,11 +64,10 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
/* ASN1 print context structure */
-struct asn1_pctx_st
- {
- unsigned long flags;
- unsigned long nm_flags;
- unsigned long cert_flags;
- unsigned long oid_flags;
- unsigned long str_flags;
- } /* ASN1_PCTX */;
+struct asn1_pctx_st {
+ unsigned long flags;
+ unsigned long nm_flags;
+ unsigned long cert_flags;
+ unsigned long oid_flags;
+ unsigned long str_flags;
+} /* ASN1_PCTX */ ;
diff --git a/src/crypto/asn1/asn1_par.c b/src/crypto/asn1/asn1_par.c
index e04aa1e7..d1f66402 100644
--- a/src/crypto/asn1/asn1_par.c
+++ b/src/crypto/asn1/asn1_par.c
@@ -60,385 +60,352 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
#define ASN1_PARSE_MAXDEPTH 128
-static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
- int indent);
+static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
+ int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
- int offset, int depth, int indent, int dump);
+ int offset, int depth, int indent, int dump);
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent)
- {
- static const char fmt[]="%-18s";
- char str[128];
- const char *p;
+ int indent)
+{
+ static const char fmt[] = "%-18s";
+ char str[128];
+ const char *p;
- if (constructed & V_ASN1_CONSTRUCTED)
- p="cons: ";
- else
- p="prim: ";
- if (BIO_write(bp,p,6) < 6) goto err;
- BIO_indent(bp,indent,128);
+ if (constructed & V_ASN1_CONSTRUCTED)
+ p = "cons: ";
+ else
+ p = "prim: ";
+ if (BIO_write(bp, p, 6) < 6)
+ goto err;
+ BIO_indent(bp, indent, 128);
- p=str;
- if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
- else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
- else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
- else if (tag > 30)
- BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
- else
- p = ASN1_tag2str(tag);
+ p = str;
+ if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ BIO_snprintf(str, sizeof str, "priv [ %d ] ", tag);
+ else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ BIO_snprintf(str, sizeof str, "cont [ %d ]", tag);
+ else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ BIO_snprintf(str, sizeof str, "appl [ %d ]", tag);
+ else if (tag > 30)
+ BIO_snprintf(str, sizeof str, "<ASN1 %d>", tag);
+ else
+ p = ASN1_tag2str(tag);
- if (BIO_printf(bp,fmt,p) <= 0)
- goto err;
- return(1);
-err:
- return(0);
- }
+ if (BIO_printf(bp, fmt, p) <= 0)
+ goto err;
+ return (1);
+ err:
+ return (0);
+}
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
- {
- return(asn1_parse2(bp,&pp,len,0,0,indent,0));
- }
+{
+ return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
+}
-int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
- {
- return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
- }
+int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
+ int dump)
+{
+ return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
+}
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
- int depth, int indent, int dump)
- {
- const unsigned char *p,*ep,*tot,*op,*opp;
- long len;
- int tag,xclass,ret=0;
- int nl,hl,j,r;
- ASN1_OBJECT *o=NULL;
- ASN1_OCTET_STRING *os=NULL;
- /* ASN1_BMPSTRING *bmp=NULL;*/
- int dump_indent;
+static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
+ int offset, int depth, int indent, int dump)
+{
+ const unsigned char *p, *ep, *tot, *op, *opp;
+ long len;
+ int tag, xclass, ret = 0;
+ int nl, hl, j, r;
+ ASN1_OBJECT *o = NULL;
+ ASN1_OCTET_STRING *os = NULL;
+ /* ASN1_BMPSTRING *bmp=NULL; */
+ int dump_indent;
#if 0
- dump_indent = indent;
+ dump_indent = indent;
#else
- dump_indent = 6; /* Because we know BIO_dump_indent() */
+ dump_indent = 6; /* Because we know BIO_dump_indent() */
#endif
- if (depth > ASN1_PARSE_MAXDEPTH)
- {
- BIO_puts(bp, "BAD RECURSION DEPTH\n");
- return 0;
- }
+ if (depth > ASN1_PARSE_MAXDEPTH) {
+ BIO_puts(bp, "BAD RECURSION DEPTH\n");
+ return 0;
+ }
- p= *pp;
- tot=p+length;
- op=p-1;
- while ((p < tot) && (op < p))
- {
- op=p;
- j=ASN1_get_object(&p,&len,&tag,&xclass,length);
+ p = *pp;
+ tot = p + length;
+ op = p - 1;
+ while ((p < tot) && (op < p)) {
+ op = p;
+ j = ASN1_get_object(&p, &len, &tag, &xclass, length);
#ifdef LINT
- j=j;
+ j = j;
#endif
- if (j & 0x80)
- {
- if (BIO_puts(bp, "Error in encoding\n") <= 0)
- goto end;
- ret=0;
- goto end;
- }
- hl=(p-op);
- length-=hl;
- /* if j == 0x21 it is a constructed indefinite length object */
- if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
- <= 0) goto end;
+ if (j & 0x80) {
+ if (BIO_puts(bp, "Error in encoding\n") <= 0)
+ goto end;
+ ret = 0;
+ goto end;
+ }
+ hl = (p - op);
+ length -= hl;
+ /*
+ * if j == 0x21 it is a constructed indefinite length object
+ */
+ if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
+ <= 0)
+ goto end;
+
+ if (j != (V_ASN1_CONSTRUCTED | 1)) {
+ if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
+ depth, (long)hl, len) <= 0)
+ goto end;
+ } else {
+ if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
+ goto end;
+ }
+ if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
+ goto end;
+ if (j & V_ASN1_CONSTRUCTED) {
+ const unsigned char *sp;
- if (j != (V_ASN1_CONSTRUCTED | 1))
- {
- if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
- depth,(long)hl,len) <= 0)
- goto end;
- }
- else
- {
- if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ",
- depth,(long)hl) <= 0)
- goto end;
- }
- if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
- goto end;
- if (j & V_ASN1_CONSTRUCTED)
- {
- ep=p+len;
- if (BIO_puts(bp, "\n") <= 0) goto end;
- if (len > length)
- {
- BIO_printf(bp,
- "length is greater than %ld\n",length);
- ret=0;
- goto end;
- }
- if ((j == 0x21) && (len == 0))
- {
- for (;;)
- {
- r=asn1_parse2(bp,&p,(long)(tot-p),
- offset+(p - *pp),depth+1,
- indent,dump);
- if (r == 0) { ret=0; goto end; }
- if ((r == 2) || (p >= tot)) break;
- }
- }
- else
- while (p < ep)
- {
- r=asn1_parse2(bp,&p,(long)len,
- offset+(p - *pp),depth+1,
- indent,dump);
- if (r == 0) { ret=0; goto end; }
- }
- }
- else if (xclass != 0)
- {
- p+=len;
- if (BIO_puts(bp, "\n") <= 0) goto end;
- }
- else
- {
- nl=0;
- if ( (tag == V_ASN1_PRINTABLESTRING) ||
- (tag == V_ASN1_T61STRING) ||
- (tag == V_ASN1_IA5STRING) ||
- (tag == V_ASN1_VISIBLESTRING) ||
- (tag == V_ASN1_NUMERICSTRING) ||
- (tag == V_ASN1_UTF8STRING) ||
- (tag == V_ASN1_UTCTIME) ||
- (tag == V_ASN1_GENERALIZEDTIME))
- {
- if (BIO_puts(bp, ":") <= 0) goto end;
- if ((len > 0) &&
- BIO_write(bp,(const char *)p,(int)len)
- != (int)len)
- goto end;
- }
- else if (tag == V_ASN1_OBJECT)
- {
- opp=op;
- if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
- {
- if (BIO_puts(bp, ":") <= 0) goto end;
- i2a_ASN1_OBJECT(bp,o);
- }
- else
- {
- if (BIO_puts(bp, ":BAD OBJECT") <= 0)
- goto end;
- }
- }
- else if (tag == V_ASN1_BOOLEAN)
- {
- int ii;
+ ep = p + len;
+ if (BIO_puts(bp, "\n") <= 0)
+ goto end;
+ if (len > length) {
+ BIO_printf(bp, "length is greater than %ld\n", length);
+ ret = 0;
+ goto end;
+ }
+ if ((j == 0x21) && (len == 0)) {
+ sp = p;
+ for (;;) {
+ r = asn1_parse2(bp, &p, (long)(tot - p),
+ offset + (p - *pp), depth + 1,
+ indent, dump);
+ if (r == 0) {
+ ret = 0;
+ goto end;
+ }
+ if ((r == 2) || (p >= tot)) {
+ len = p - sp;
+ break;
+ }
+ }
+ } else {
+ long tmp = len;
- opp=op;
- ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
- if (ii < 0)
- {
- if (BIO_puts(bp, "Bad boolean\n") <= 0)
- goto end;
- }
- BIO_printf(bp,":%d",ii);
- }
- else if (tag == V_ASN1_BMPSTRING)
- {
- /* do the BMP thang */
- }
- else if (tag == V_ASN1_OCTET_STRING)
- {
- int i,printable=1;
+ while (p < ep) {
+ sp = p;
+ r = asn1_parse2(bp, &p, tmp, offset + (p - *pp), depth + 1,
+ indent, dump);
+ if (r == 0) {
+ ret = 0;
+ goto end;
+ }
+ tmp -= p - sp;
+ }
+ }
+ } else if (xclass != 0) {
+ p += len;
+ if (BIO_puts(bp, "\n") <= 0)
+ goto end;
+ } else {
+ nl = 0;
+ if ((tag == V_ASN1_PRINTABLESTRING) ||
+ (tag == V_ASN1_T61STRING) ||
+ (tag == V_ASN1_IA5STRING) ||
+ (tag == V_ASN1_VISIBLESTRING) ||
+ (tag == V_ASN1_NUMERICSTRING) ||
+ (tag == V_ASN1_UTF8STRING) ||
+ (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
+ if (BIO_puts(bp, ":") <= 0)
+ goto end;
+ if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
+ != (int)len)
+ goto end;
+ } else if (tag == V_ASN1_OBJECT) {
+ opp = op;
+ if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
+ if (BIO_puts(bp, ":") <= 0)
+ goto end;
+ i2a_ASN1_OBJECT(bp, o);
+ } else {
+ if (BIO_puts(bp, ":BAD OBJECT") <= 0)
+ goto end;
+ }
+ } else if (tag == V_ASN1_BOOLEAN) {
+ int ii;
- opp=op;
- os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
- if (os != NULL && os->length > 0)
- {
- opp = os->data;
- /* testing whether the octet string is
- * printable */
- for (i=0; i<os->length; i++)
- {
- if (( (opp[i] < ' ') &&
- (opp[i] != '\n') &&
- (opp[i] != '\r') &&
- (opp[i] != '\t')) ||
- (opp[i] > '~'))
- {
- printable=0;
- break;
- }
- }
- if (printable)
- /* printable string */
- {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- if (BIO_write(bp,(const char *)opp,
- os->length) <= 0)
- goto end;
- }
- else if (!dump)
- /* not printable => print octet string
- * as hex dump */
- {
- if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
- goto end;
- for (i=0; i<os->length; i++)
- {
- if (BIO_printf(bp,"%02X"
- , opp[i]) <= 0)
- goto end;
- }
- }
- else
- /* print the normal dump */
- {
- if (!nl)
- {
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- }
- if (!BIO_hexdump(bp, opp,
- ((dump == -1 || dump >
- os->length)?os->length:dump),
- dump_indent))
- goto end;
- nl=1;
- }
- }
- if (os != NULL)
- {
- M_ASN1_OCTET_STRING_free(os);
- os=NULL;
- }
- }
- else if (tag == V_ASN1_INTEGER)
- {
- ASN1_INTEGER *bs;
- int i;
+ opp = op;
+ ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
+ if (ii < 0) {
+ if (BIO_puts(bp, "Bad boolean\n") <= 0)
+ goto end;
+ }
+ BIO_printf(bp, ":%d", ii);
+ } else if (tag == V_ASN1_BMPSTRING) {
+ /* do the BMP thang */
+ } else if (tag == V_ASN1_OCTET_STRING) {
+ int i, printable = 1;
- opp=op;
- bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
- if (bs != NULL)
- {
- if (BIO_puts(bp, ":") <= 0) goto end;
- if (bs->type == V_ASN1_NEG_INTEGER)
- if (BIO_puts(bp, "-") <= 0)
- goto end;
- for (i=0; i<bs->length; i++)
- {
- if (BIO_printf(bp,"%02X",
- bs->data[i]) <= 0)
- goto end;
- }
- if (bs->length == 0)
- {
- if (BIO_puts(bp, "00") <= 0)
- goto end;
- }
- }
- else
- {
- if (BIO_puts(bp, "BAD INTEGER") <= 0)
- goto end;
- }
- M_ASN1_INTEGER_free(bs);
- }
- else if (tag == V_ASN1_ENUMERATED)
- {
- ASN1_ENUMERATED *bs;
- int i;
+ opp = op;
+ os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
+ if (os != NULL && os->length > 0) {
+ opp = os->data;
+ /*
+ * testing whether the octet string is printable
+ */
+ for (i = 0; i < os->length; i++) {
+ if (((opp[i] < ' ') &&
+ (opp[i] != '\n') &&
+ (opp[i] != '\r') &&
+ (opp[i] != '\t')) || (opp[i] > '~')) {
+ printable = 0;
+ break;
+ }
+ }
+ if (printable)
+ /* printable string */
+ {
+ if (BIO_puts(bp, ":") <= 0)
+ goto end;
+ if (BIO_write(bp, (const char *)opp, os->length) <= 0)
+ goto end;
+ } else if (!dump)
+ /*
+ * not printable => print octet string as hex dump
+ */
+ {
+ if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
+ goto end;
+ for (i = 0; i < os->length; i++) {
+ if (BIO_printf(bp, "%02X", opp[i]) <= 0)
+ goto end;
+ }
+ } else
+ /* print the normal dump */
+ {
+ if (!nl) {
+ if (BIO_puts(bp, "\n") <= 0)
+ goto end;
+ }
+ if (!BIO_hexdump(bp, opp,
+ ((dump == -1 || dump >
+ os->length) ? os->length : dump),
+ dump_indent))
+ goto end;
+ nl = 1;
+ }
+ }
+ if (os != NULL) {
+ M_ASN1_OCTET_STRING_free(os);
+ os = NULL;
+ }
+ } else if (tag == V_ASN1_INTEGER) {
+ ASN1_INTEGER *bs;
+ int i;
- opp=op;
- bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
- if (bs != NULL)
- {
- if (BIO_puts(bp, ":") <= 0) goto end;
- if (bs->type == V_ASN1_NEG_ENUMERATED)
- if (BIO_puts(bp, "-") <= 0)
- goto end;
- for (i=0; i<bs->length; i++)
- {
- if (BIO_printf(bp,"%02X",
- bs->data[i]) <= 0)
- goto end;
- }
- if (bs->length == 0)
- {
- if (BIO_puts(bp, "00") <= 0)
- goto end;
- }
- }
- else
- {
- if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
- goto end;
- }
- M_ASN1_ENUMERATED_free(bs);
- }
- else if (len > 0 && dump)
- {
- if (!nl)
- {
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- }
- if (!BIO_hexdump(bp,p,
- ((dump == -1 || dump > len)?len:dump),
- dump_indent))
- goto end;
- nl=1;
- }
+ opp = op;
+ bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
+ if (bs != NULL) {
+ if (BIO_puts(bp, ":") <= 0)
+ goto end;
+ if (bs->type == V_ASN1_NEG_INTEGER)
+ if (BIO_puts(bp, "-") <= 0)
+ goto end;
+ for (i = 0; i < bs->length; i++) {
+ if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
+ goto end;
+ }
+ if (bs->length == 0) {
+ if (BIO_puts(bp, "00") <= 0)
+ goto end;
+ }
+ } else {
+ if (BIO_puts(bp, "BAD INTEGER") <= 0)
+ goto end;
+ }
+ M_ASN1_INTEGER_free(bs);
+ } else if (tag == V_ASN1_ENUMERATED) {
+ ASN1_ENUMERATED *bs;
+ int i;
- if (!nl)
- {
- if (BIO_puts(bp, "\n") <= 0) goto end;
- }
- p+=len;
- if ((tag == V_ASN1_EOC) && (xclass == 0))
- {
- ret=2; /* End of sequence */
- goto end;
- }
- }
- length-=len;
- }
- ret=1;
-end:
- if (o != NULL) ASN1_OBJECT_free(o);
- if (os != NULL) M_ASN1_OCTET_STRING_free(os);
- *pp=p;
- return(ret);
- }
+ opp = op;
+ bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
+ if (bs != NULL) {
+ if (BIO_puts(bp, ":") <= 0)
+ goto end;
+ if (bs->type == V_ASN1_NEG_ENUMERATED)
+ if (BIO_puts(bp, "-") <= 0)
+ goto end;
+ for (i = 0; i < bs->length; i++) {
+ if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
+ goto end;
+ }
+ if (bs->length == 0) {
+ if (BIO_puts(bp, "00") <= 0)
+ goto end;
+ }
+ } else {
+ if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
+ goto end;
+ }
+ M_ASN1_ENUMERATED_free(bs);
+ } else if (len > 0 && dump) {
+ if (!nl) {
+ if (BIO_puts(bp, "\n") <= 0)
+ goto end;
+ }
+ if (!BIO_hexdump(bp, p,
+ ((dump == -1 || dump > len) ? len : dump),
+ dump_indent))
+ goto end;
+ nl = 1;
+ }
+
+ if (!nl) {
+ if (BIO_puts(bp, "\n") <= 0)
+ goto end;
+ }
+ p += len;
+ if ((tag == V_ASN1_EOC) && (xclass == 0)) {
+ ret = 2; /* End of sequence */
+ goto end;
+ }
+ }
+ length -= len;
+ }
+ ret = 1;
+ end:
+ if (o != NULL)
+ ASN1_OBJECT_free(o);
+ if (os != NULL)
+ M_ASN1_OCTET_STRING_free(os);
+ *pp = p;
+ return (ret);
+}
const char *ASN1_tag2str(int tag)
{
- static const char * const tag2str[] = {
- "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
- "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
- "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
- "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
- "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
- "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
- "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
- "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
- };
+ static const char *const tag2str[] = {
+ "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
+ "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
+ "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
+ "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
+ "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
+ "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
+ */
+ "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
+ "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
+ };
- if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
- tag &= ~0x100;
+ if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+ tag &= ~0x100;
- if(tag < 0 || tag > 30) return "(unknown)";
- return tag2str[tag];
+ if (tag < 0 || tag > 30)
+ return "(unknown)";
+ return tag2str[tag];
}
-
diff --git a/src/crypto/asn1/asn1_test.cc b/src/crypto/asn1/asn1_test.cc
new file mode 100644
index 00000000..8b024427
--- /dev/null
+++ b/src/crypto/asn1/asn1_test.cc
@@ -0,0 +1,81 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <openssl/asn1.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#include "../test/scoped_types.h"
+
+
+// kTag128 is an ASN.1 structure with a universal tag with number 128.
+static const uint8_t kTag128[] = {
+ 0x1f, 0x81, 0x00, 0x01, 0x00,
+};
+
+// kTag258 is an ASN.1 structure with a universal tag with number 258.
+static const uint8_t kTag258[] = {
+ 0x1f, 0x82, 0x02, 0x01, 0x00,
+};
+
+static_assert(V_ASN1_NEG_INTEGER == 258,
+ "V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it.");
+
+// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1,
+// which will not fit in an int.
+static const uint8_t kTagOverflow[] = {
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
+};
+
+static bool TestLargeTags() {
+ const uint8_t *p = kTag258;
+ ScopedASN1_TYPE obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
+ if (obj) {
+ fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
+ return false;
+ }
+ ERR_clear_error();
+
+ p = kTagOverflow;
+ obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
+ if (obj) {
+ fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
+ return false;
+ }
+ ERR_clear_error();
+
+ p = kTag128;
+ obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
+ if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
+ obj->value.asn1_string->data[0] != 0) {
+ fprintf(stderr, "Failed to parse value with tag 128.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ return true;
+}
+
+int main() {
+ CRYPTO_library_init();
+
+ if (!TestLargeTags()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/asn1/asn_pack.c b/src/crypto/asn1/asn_pack.c
index e842a10d..eff54e55 100644
--- a/src/crypto/asn1/asn_pack.c
+++ b/src/crypto/asn1/asn_pack.c
@@ -59,46 +59,47 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
/* ASN1_ITEM versions of the above */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
- ASN1_STRING *octmp;
+ ASN1_STRING *octmp;
+
+ if (!oct || !*oct) {
+ if (!(octmp = ASN1_STRING_new())) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (oct)
+ *oct = octmp;
+ } else
+ octmp = *oct;
- if (!oct || !*oct) {
- if (!(octmp = ASN1_STRING_new ())) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- if (oct) *oct = octmp;
- } else octmp = *oct;
+ if (octmp->data) {
+ OPENSSL_free(octmp->data);
+ octmp->data = NULL;
+ }
- if(octmp->data) {
- OPENSSL_free(octmp->data);
- octmp->data = NULL;
- }
-
- if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
- return NULL;
- }
- if (!octmp->data) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- return octmp;
+ if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
+ return NULL;
+ }
+ if (!octmp->data) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ return octmp;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
{
- const unsigned char *p;
- void *ret;
+ const unsigned char *p;
+ void *ret;
- p = oct->data;
- if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
- return ret;
+ p = oct->data;
+ if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
+ return ret;
}
diff --git a/src/crypto/asn1/bio_asn1.c b/src/crypto/asn1/bio_asn1.c
index 15f233be..03cc9a6e 100644
--- a/src/crypto/asn1/bio_asn1.c
+++ b/src/crypto/asn1/bio_asn1.c
@@ -62,53 +62,48 @@
#include <openssl/bio.h>
#include <openssl/mem.h>
-
/* Must be large enough for biggest tag+length */
#define DEFAULT_ASN1_BUF_SIZE 20
-typedef enum
- {
- ASN1_STATE_START,
- ASN1_STATE_PRE_COPY,
- ASN1_STATE_HEADER,
- ASN1_STATE_HEADER_COPY,
- ASN1_STATE_DATA_COPY,
- ASN1_STATE_POST_COPY,
- ASN1_STATE_DONE
- } asn1_bio_state_t;
-
-typedef struct BIO_ASN1_EX_FUNCS_st
- {
- asn1_ps_func *ex_func;
- asn1_ps_func *ex_free_func;
- } BIO_ASN1_EX_FUNCS;
-
-typedef struct BIO_ASN1_BUF_CTX_t
- {
- /* Internal state */
- asn1_bio_state_t state;
- /* Internal buffer */
- unsigned char *buf;
- /* Size of buffer */
- int bufsize;
- /* Current position in buffer */
- int bufpos;
- /* Current buffer length */
- int buflen;
- /* Amount of data to copy */
- int copylen;
- /* Class and tag to use */
- int asn1_class, asn1_tag;
- asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
- /* Extra buffer for prefix and suffix data */
- unsigned char *ex_buf;
- int ex_len;
- int ex_pos;
- void *ex_arg;
- } BIO_ASN1_BUF_CTX;
-
-
-static int asn1_bio_write(BIO *h, const char *buf,int num);
+typedef enum {
+ ASN1_STATE_START,
+ ASN1_STATE_PRE_COPY,
+ ASN1_STATE_HEADER,
+ ASN1_STATE_HEADER_COPY,
+ ASN1_STATE_DATA_COPY,
+ ASN1_STATE_POST_COPY,
+ ASN1_STATE_DONE
+} asn1_bio_state_t;
+
+typedef struct BIO_ASN1_EX_FUNCS_st {
+ asn1_ps_func *ex_func;
+ asn1_ps_func *ex_free_func;
+} BIO_ASN1_EX_FUNCS;
+
+typedef struct BIO_ASN1_BUF_CTX_t {
+ /* Internal state */
+ asn1_bio_state_t state;
+ /* Internal buffer */
+ unsigned char *buf;
+ /* Size of buffer */
+ int bufsize;
+ /* Current position in buffer */
+ int bufpos;
+ /* Current buffer length */
+ int buflen;
+ /* Amount of data to copy */
+ int copylen;
+ /* Class and tag to use */
+ int asn1_class, asn1_tag;
+ asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
+ /* Extra buffer for prefix and suffix data */
+ unsigned char *ex_buf;
+ int ex_len;
+ int ex_pos;
+ void *ex_arg;
+} BIO_ASN1_BUF_CTX;
+
+static int asn1_bio_write(BIO *h, const char *buf, int num);
static int asn1_bio_read(BIO *h, char *buf, int size);
static int asn1_bio_puts(BIO *h, const char *str);
static int asn1_bio_gets(BIO *h, char *str, int size);
@@ -119,378 +114,364 @@ static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *cleanup, asn1_bio_state_t next);
+ asn1_ps_func *cleanup, asn1_bio_state_t next);
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *setup,
- asn1_bio_state_t ex_state,
- asn1_bio_state_t other_state);
-
-static const BIO_METHOD methods_asn1=
- {
- BIO_TYPE_ASN1,
- "asn1",
- asn1_bio_write,
- asn1_bio_read,
- asn1_bio_puts,
- asn1_bio_gets,
- asn1_bio_ctrl,
- asn1_bio_new,
- asn1_bio_free,
- asn1_bio_callback_ctrl,
- };
+ asn1_ps_func *setup,
+ asn1_bio_state_t ex_state,
+ asn1_bio_state_t other_state);
+
+static const BIO_METHOD methods_asn1 = {
+ BIO_TYPE_ASN1,
+ "asn1",
+ asn1_bio_write,
+ asn1_bio_read,
+ asn1_bio_puts,
+ asn1_bio_gets,
+ asn1_bio_ctrl,
+ asn1_bio_new,
+ asn1_bio_free,
+ asn1_bio_callback_ctrl,
+};
const BIO_METHOD *BIO_f_asn1(void)
- {
- return(&methods_asn1);
- }
-
+{
+ return (&methods_asn1);
+}
static int asn1_bio_new(BIO *b)
- {
- BIO_ASN1_BUF_CTX *ctx;
- ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
- if (!ctx)
- return 0;
- if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
- {
- OPENSSL_free(ctx);
- return 0;
- }
- b->init = 1;
- b->ptr = (char *)ctx;
- b->flags = 0;
- return 1;
- }
+{
+ BIO_ASN1_BUF_CTX *ctx;
+ ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
+ if (!ctx)
+ return 0;
+ if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
+ OPENSSL_free(ctx);
+ return 0;
+ }
+ b->init = 1;
+ b->ptr = (char *)ctx;
+ b->flags = 0;
+ return 1;
+}
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
- {
- ctx->buf = OPENSSL_malloc(size);
- if (!ctx->buf)
- return 0;
- ctx->bufsize = size;
- ctx->bufpos = 0;
- ctx->buflen = 0;
- ctx->copylen = 0;
- ctx->asn1_class = V_ASN1_UNIVERSAL;
- ctx->asn1_tag = V_ASN1_OCTET_STRING;
- ctx->ex_buf = 0;
- ctx->ex_pos = 0;
- ctx->ex_len = 0;
- ctx->state = ASN1_STATE_START;
- return 1;
- }
+{
+ ctx->buf = OPENSSL_malloc(size);
+ if (!ctx->buf)
+ return 0;
+ ctx->bufsize = size;
+ ctx->bufpos = 0;
+ ctx->buflen = 0;
+ ctx->copylen = 0;
+ ctx->asn1_class = V_ASN1_UNIVERSAL;
+ ctx->asn1_tag = V_ASN1_OCTET_STRING;
+ ctx->ex_buf = 0;
+ ctx->ex_pos = 0;
+ ctx->ex_len = 0;
+ ctx->state = ASN1_STATE_START;
+ return 1;
+}
static int asn1_bio_free(BIO *b)
- {
- BIO_ASN1_BUF_CTX *ctx;
- ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
- if (ctx == NULL)
- return 0;
- if (ctx->buf)
- OPENSSL_free(ctx->buf);
- OPENSSL_free(ctx);
- b->init = 0;
- b->ptr = NULL;
- b->flags = 0;
- return 1;
- }
-
-static int asn1_bio_write(BIO *b, const char *in , int inl)
- {
- BIO_ASN1_BUF_CTX *ctx;
- int wrmax, wrlen, ret;
- unsigned char *p;
- if (!in || (inl < 0) || (b->next_bio == NULL))
- return 0;
- ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
- if (ctx == NULL)
- return 0;
-
- wrlen = 0;
- ret = -1;
-
- for(;;)
- {
- switch (ctx->state)
- {
-
- /* Setup prefix data, call it */
- case ASN1_STATE_START:
- if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
- ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
- return 0;
- break;
-
- /* Copy any pre data first */
- case ASN1_STATE_PRE_COPY:
-
- ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
- ASN1_STATE_HEADER);
-
- if (ret <= 0)
- goto done;
-
- break;
-
- case ASN1_STATE_HEADER:
- ctx->buflen =
- ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
- assert(ctx->buflen <= ctx->bufsize);
- p = ctx->buf;
- ASN1_put_object(&p, 0, inl,
- ctx->asn1_tag, ctx->asn1_class);
- ctx->copylen = inl;
- ctx->state = ASN1_STATE_HEADER_COPY;
-
- break;
-
- case ASN1_STATE_HEADER_COPY:
- ret = BIO_write(b->next_bio,
- ctx->buf + ctx->bufpos, ctx->buflen);
- if (ret <= 0)
- goto done;
-
- ctx->buflen -= ret;
- if (ctx->buflen)
- ctx->bufpos += ret;
- else
- {
- ctx->bufpos = 0;
- ctx->state = ASN1_STATE_DATA_COPY;
- }
-
- break;
-
- case ASN1_STATE_DATA_COPY:
-
- if (inl > ctx->copylen)
- wrmax = ctx->copylen;
- else
- wrmax = inl;
- ret = BIO_write(b->next_bio, in, wrmax);
- if (ret <= 0)
- break;
- wrlen += ret;
- ctx->copylen -= ret;
- in += ret;
- inl -= ret;
-
- if (ctx->copylen == 0)
- ctx->state = ASN1_STATE_HEADER;
-
- if (inl == 0)
- goto done;
-
- break;
-
- default:
- BIO_clear_retry_flags(b);
- return 0;
-
- }
-
- }
-
- done:
- BIO_clear_retry_flags(b);
- BIO_copy_next_retry(b);
-
- return (wrlen > 0) ? wrlen : ret;
-
- }
+{
+ BIO_ASN1_BUF_CTX *ctx;
+ ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
+ if (ctx == NULL)
+ return 0;
+ if (ctx->buf)
+ OPENSSL_free(ctx->buf);
+ OPENSSL_free(ctx);
+ b->init = 0;
+ b->ptr = NULL;
+ b->flags = 0;
+ return 1;
+}
+
+static int asn1_bio_write(BIO *b, const char *in, int inl)
+{
+ BIO_ASN1_BUF_CTX *ctx;
+ int wrmax, wrlen, ret;
+ unsigned char *p;
+ if (!in || (inl < 0) || (b->next_bio == NULL))
+ return 0;
+ ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
+ if (ctx == NULL)
+ return 0;
+
+ wrlen = 0;
+ ret = -1;
+
+ for (;;) {
+ switch (ctx->state) {
+
+ /* Setup prefix data, call it */
+ case ASN1_STATE_START:
+ if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
+ ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
+ return 0;
+ break;
+
+ /* Copy any pre data first */
+ case ASN1_STATE_PRE_COPY:
+
+ ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
+ ASN1_STATE_HEADER);
+
+ if (ret <= 0)
+ goto done;
+
+ break;
+
+ case ASN1_STATE_HEADER:
+ ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
+ assert(ctx->buflen <= ctx->bufsize);
+ p = ctx->buf;
+ ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
+ ctx->copylen = inl;
+ ctx->state = ASN1_STATE_HEADER_COPY;
+
+ break;
+
+ case ASN1_STATE_HEADER_COPY:
+ ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
+ if (ret <= 0)
+ goto done;
+
+ ctx->buflen -= ret;
+ if (ctx->buflen)
+ ctx->bufpos += ret;
+ else {
+ ctx->bufpos = 0;
+ ctx->state = ASN1_STATE_DATA_COPY;
+ }
+
+ break;
+
+ case ASN1_STATE_DATA_COPY:
+
+ if (inl > ctx->copylen)
+ wrmax = ctx->copylen;
+ else
+ wrmax = inl;
+ ret = BIO_write(b->next_bio, in, wrmax);
+ if (ret <= 0)
+ break;
+ wrlen += ret;
+ ctx->copylen -= ret;
+ in += ret;
+ inl -= ret;
+
+ if (ctx->copylen == 0)
+ ctx->state = ASN1_STATE_HEADER;
+
+ if (inl == 0)
+ goto done;
+
+ break;
+
+ default:
+ BIO_clear_retry_flags(b);
+ return 0;
+
+ }
+
+ }
+
+ done:
+ BIO_clear_retry_flags(b);
+ BIO_copy_next_retry(b);
+
+ return (wrlen > 0) ? wrlen : ret;
+
+}
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *cleanup, asn1_bio_state_t next)
- {
- int ret;
- if (ctx->ex_len <= 0)
- return 1;
- for(;;)
- {
- ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
- ctx->ex_len);
- if (ret <= 0)
- break;
- ctx->ex_len -= ret;
- if (ctx->ex_len > 0)
- ctx->ex_pos += ret;
- else
- {
- if(cleanup)
- cleanup(b, &ctx->ex_buf, &ctx->ex_len,
- &ctx->ex_arg);
- ctx->state = next;
- ctx->ex_pos = 0;
- break;
- }
- }
- return ret;
- }
+ asn1_ps_func *cleanup, asn1_bio_state_t next)
+{
+ int ret;
+ if (ctx->ex_len <= 0)
+ return 1;
+ for (;;) {
+ ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
+ if (ret <= 0)
+ break;
+ ctx->ex_len -= ret;
+ if (ctx->ex_len > 0)
+ ctx->ex_pos += ret;
+ else {
+ if (cleanup)
+ cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
+ ctx->state = next;
+ ctx->ex_pos = 0;
+ break;
+ }
+ }
+ return ret;
+}
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *setup,
- asn1_bio_state_t ex_state,
- asn1_bio_state_t other_state)
- {
- if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
- {
- BIO_clear_retry_flags(b);
- return 0;
- }
- if (ctx->ex_len > 0)
- ctx->state = ex_state;
- else
- ctx->state = other_state;
- return 1;
- }
-
-static int asn1_bio_read(BIO *b, char *in , int inl)
- {
- if (!b->next_bio)
- return 0;
- return BIO_read(b->next_bio, in , inl);
- }
+ asn1_ps_func *setup,
+ asn1_bio_state_t ex_state,
+ asn1_bio_state_t other_state)
+{
+ if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
+ BIO_clear_retry_flags(b);
+ return 0;
+ }
+ if (ctx->ex_len > 0)
+ ctx->state = ex_state;
+ else
+ ctx->state = other_state;
+ return 1;
+}
+
+static int asn1_bio_read(BIO *b, char *in, int inl)
+{
+ if (!b->next_bio)
+ return 0;
+ return BIO_read(b->next_bio, in, inl);
+}
static int asn1_bio_puts(BIO *b, const char *str)
- {
- return asn1_bio_write(b, str, strlen(str));
- }
+{
+ return asn1_bio_write(b, str, strlen(str));
+}
static int asn1_bio_gets(BIO *b, char *str, int size)
- {
- if (!b->next_bio)
- return 0;
- return BIO_gets(b->next_bio, str , size);
- }
+{
+ if (!b->next_bio)
+ return 0;
+ return BIO_gets(b->next_bio, str, size);
+}
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
- {
- if (b->next_bio == NULL) return(0);
- return BIO_callback_ctrl(b->next_bio,cmd,fp);
- }
+{
+ if (b->next_bio == NULL)
+ return (0);
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
+}
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
- {
- BIO_ASN1_BUF_CTX *ctx;
- BIO_ASN1_EX_FUNCS *ex_func;
- long ret = 1;
- ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
- if (ctx == NULL)
- return 0;
- switch(cmd)
- {
-
- case BIO_C_SET_PREFIX:
- ex_func = arg2;
- ctx->prefix = ex_func->ex_func;
- ctx->prefix_free = ex_func->ex_free_func;
- break;
-
- case BIO_C_GET_PREFIX:
- ex_func = arg2;
- ex_func->ex_func = ctx->prefix;
- ex_func->ex_free_func = ctx->prefix_free;
- break;
-
- case BIO_C_SET_SUFFIX:
- ex_func = arg2;
- ctx->suffix = ex_func->ex_func;
- ctx->suffix_free = ex_func->ex_free_func;
- break;
-
- case BIO_C_GET_SUFFIX:
- ex_func = arg2;
- ex_func->ex_func = ctx->suffix;
- ex_func->ex_free_func = ctx->suffix_free;
- break;
-
- case BIO_C_SET_EX_ARG:
- ctx->ex_arg = arg2;
- break;
-
- case BIO_C_GET_EX_ARG:
- *(void **)arg2 = ctx->ex_arg;
- break;
-
- case BIO_CTRL_FLUSH:
- if (!b->next_bio)
- return 0;
-
- /* Call post function if possible */
- if (ctx->state == ASN1_STATE_HEADER)
- {
- if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
- ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
- return 0;
- }
-
- if (ctx->state == ASN1_STATE_POST_COPY)
- {
- ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
- ASN1_STATE_DONE);
- if (ret <= 0)
- return ret;
- }
-
- if (ctx->state == ASN1_STATE_DONE)
- return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
- else
- {
- BIO_clear_retry_flags(b);
- return 0;
- }
- break;
-
-
- default:
- if (!b->next_bio)
- return 0;
- return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
-
- }
-
- return ret;
- }
+{
+ BIO_ASN1_BUF_CTX *ctx;
+ BIO_ASN1_EX_FUNCS *ex_func;
+ long ret = 1;
+ ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
+ if (ctx == NULL)
+ return 0;
+ switch (cmd) {
+
+ case BIO_C_SET_PREFIX:
+ ex_func = arg2;
+ ctx->prefix = ex_func->ex_func;
+ ctx->prefix_free = ex_func->ex_free_func;
+ break;
+
+ case BIO_C_GET_PREFIX:
+ ex_func = arg2;
+ ex_func->ex_func = ctx->prefix;
+ ex_func->ex_free_func = ctx->prefix_free;
+ break;
+
+ case BIO_C_SET_SUFFIX:
+ ex_func = arg2;
+ ctx->suffix = ex_func->ex_func;
+ ctx->suffix_free = ex_func->ex_free_func;
+ break;
+
+ case BIO_C_GET_SUFFIX:
+ ex_func = arg2;
+ ex_func->ex_func = ctx->suffix;
+ ex_func->ex_free_func = ctx->suffix_free;
+ break;
+
+ case BIO_C_SET_EX_ARG:
+ ctx->ex_arg = arg2;
+ break;
+
+ case BIO_C_GET_EX_ARG:
+ *(void **)arg2 = ctx->ex_arg;
+ break;
+
+ case BIO_CTRL_FLUSH:
+ if (!b->next_bio)
+ return 0;
+
+ /* Call post function if possible */
+ if (ctx->state == ASN1_STATE_HEADER) {
+ if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
+ ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
+ return 0;
+ }
+
+ if (ctx->state == ASN1_STATE_POST_COPY) {
+ ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
+ ASN1_STATE_DONE);
+ if (ret <= 0)
+ return ret;
+ }
+
+ if (ctx->state == ASN1_STATE_DONE)
+ return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
+ else {
+ BIO_clear_retry_flags(b);
+ return 0;
+ }
+ break;
+
+ default:
+ if (!b->next_bio)
+ return 0;
+ return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
+
+ }
+
+ return ret;
+}
static int asn1_bio_set_ex(BIO *b, int cmd,
- asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
- {
- BIO_ASN1_EX_FUNCS extmp;
- extmp.ex_func = ex_func;
- extmp.ex_free_func = ex_free_func;
- return BIO_ctrl(b, cmd, 0, &extmp);
- }
+ asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
+{
+ BIO_ASN1_EX_FUNCS extmp;
+ extmp.ex_func = ex_func;
+ extmp.ex_free_func = ex_free_func;
+ return BIO_ctrl(b, cmd, 0, &extmp);
+}
static int asn1_bio_get_ex(BIO *b, int cmd,
- asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
- {
- BIO_ASN1_EX_FUNCS extmp;
- int ret;
- ret = BIO_ctrl(b, cmd, 0, &extmp);
- if (ret > 0)
- {
- *ex_func = extmp.ex_func;
- *ex_free_func = extmp.ex_free_func;
- }
- return ret;
- }
-
-int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
- {
- return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
- }
-
-int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
- {
- return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
- }
-
-int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
- {
- return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
- }
-
-int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
- {
- return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
- }
+ asn1_ps_func **ex_func,
+ asn1_ps_func **ex_free_func)
+{
+ BIO_ASN1_EX_FUNCS extmp;
+ int ret;
+ ret = BIO_ctrl(b, cmd, 0, &extmp);
+ if (ret > 0) {
+ *ex_func = extmp.ex_func;
+ *ex_free_func = extmp.ex_free_func;
+ }
+ return ret;
+}
+
+int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
+ asn1_ps_func *prefix_free)
+{
+ return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
+}
+
+int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
+ asn1_ps_func **pprefix_free)
+{
+ return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
+}
+
+int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
+ asn1_ps_func *suffix_free)
+{
+ return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
+}
+
+int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
+ asn1_ps_func **psuffix_free)
+{
+ return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
+}
diff --git a/src/crypto/asn1/bio_ndef.c b/src/crypto/asn1/bio_ndef.c
index f07d3de7..81a8aa7c 100644
--- a/src/crypto/asn1/bio_ndef.c
+++ b/src/crypto/asn1/bio_ndef.c
@@ -63,192 +63,189 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
/* Experimental NDEF ASN1 BIO support routines */
-/* The usage is quite simple, initialize an ASN1 structure,
- * get a BIO from it then any data written through the BIO
- * will end up translated to approptiate format on the fly.
- * The data is streamed out and does *not* need to be
- * all held in memory at once.
- *
- * When the BIO is flushed the output is finalized and any
- * signatures etc written out.
- *
- * The BIO is a 'proper' BIO and can handle non blocking I/O
- * correctly.
- *
- * The usage is simple. The implementation is *not*...
+/*
+ * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
+ * then any data written through the BIO will end up translated to
+ * approptiate format on the fly. The data is streamed out and does *not*
+ * need to be all held in memory at once. When the BIO is flushed the output
+ * is finalized and any signatures etc written out. The BIO is a 'proper'
+ * BIO and can handle non blocking I/O correctly. The usage is simple. The
+ * implementation is *not*...
*/
/* BIO support data stored in the ASN1 BIO ex_arg */
-typedef struct ndef_aux_st
- {
- /* ASN1 structure this BIO refers to */
- ASN1_VALUE *val;
- const ASN1_ITEM *it;
- /* Top of the BIO chain */
- BIO *ndef_bio;
- /* Output BIO */
- BIO *out;
- /* Boundary where content is inserted */
- unsigned char **boundary;
- /* DER buffer start */
- unsigned char *derbuf;
- } NDEF_SUPPORT;
+typedef struct ndef_aux_st {
+ /* ASN1 structure this BIO refers to */
+ ASN1_VALUE *val;
+ const ASN1_ITEM *it;
+ /* Top of the BIO chain */
+ BIO *ndef_bio;
+ /* Output BIO */
+ BIO *out;
+ /* Boundary where content is inserted */
+ unsigned char **boundary;
+ /* DER buffer start */
+ unsigned char *derbuf;
+} NDEF_SUPPORT;
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
+ void *parg);
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
+ void *parg);
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
- {
- NDEF_SUPPORT *ndef_aux = NULL;
- BIO *asn_bio = NULL;
- const ASN1_AUX *aux = it->funcs;
- ASN1_STREAM_ARG sarg;
+{
+ NDEF_SUPPORT *ndef_aux = NULL;
+ BIO *asn_bio = NULL;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_STREAM_ARG sarg;
- if (!aux || !aux->asn1_cb)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
- return NULL;
- }
- ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
- asn_bio = BIO_new(BIO_f_asn1());
+ if (!aux || !aux->asn1_cb) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
+ return NULL;
+ }
+ ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
+ asn_bio = BIO_new(BIO_f_asn1());
- /* ASN1 bio needs to be next to output BIO */
+ /* ASN1 bio needs to be next to output BIO */
- out = BIO_push(asn_bio, out);
+ out = BIO_push(asn_bio, out);
- if (!ndef_aux || !asn_bio || !out)
- goto err;
+ if (!ndef_aux || !asn_bio || !out)
+ goto err;
- BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
- BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
+ BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
+ BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
- /* Now let callback prepend any digest, cipher etc BIOs
- * ASN1 structure needs.
- */
+ /*
+ * Now let callback prepend any digest, cipher etc BIOs ASN1 structure
+ * needs.
+ */
- sarg.out = out;
- sarg.ndef_bio = NULL;
- sarg.boundary = NULL;
+ sarg.out = out;
+ sarg.ndef_bio = NULL;
+ sarg.boundary = NULL;
- if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
- goto err;
+ if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
+ goto err;
- ndef_aux->val = val;
- ndef_aux->it = it;
- ndef_aux->ndef_bio = sarg.ndef_bio;
- ndef_aux->boundary = sarg.boundary;
- ndef_aux->out = out;
+ ndef_aux->val = val;
+ ndef_aux->it = it;
+ ndef_aux->ndef_bio = sarg.ndef_bio;
+ ndef_aux->boundary = sarg.boundary;
+ ndef_aux->out = out;
- BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
+ BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
- return sarg.ndef_bio;
+ return sarg.ndef_bio;
- err:
- if (asn_bio)
- BIO_free(asn_bio);
- if (ndef_aux)
- OPENSSL_free(ndef_aux);
- return NULL;
- }
+ err:
+ if (asn_bio)
+ BIO_free(asn_bio);
+ if (ndef_aux)
+ OPENSSL_free(ndef_aux);
+ return NULL;
+}
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
- {
- NDEF_SUPPORT *ndef_aux;
- unsigned char *p;
- int derlen;
+{
+ NDEF_SUPPORT *ndef_aux;
+ unsigned char *p;
+ int derlen;
- if (!parg)
- return 0;
+ if (!parg)
+ return 0;
- ndef_aux = *(NDEF_SUPPORT **)parg;
+ ndef_aux = *(NDEF_SUPPORT **)parg;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
- p = OPENSSL_malloc(derlen);
- if (p == NULL)
- return 0;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ if (p == NULL)
+ return 0;
- ndef_aux->derbuf = p;
- *pbuf = p;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
- if (!*ndef_aux->boundary)
- return 0;
+ if (!*ndef_aux->boundary)
+ return 0;
- *plen = *ndef_aux->boundary - *pbuf;
+ *plen = *ndef_aux->boundary - *pbuf;
- return 1;
- }
+ return 1;
+}
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
- {
- NDEF_SUPPORT *ndef_aux;
+static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
+ void *parg)
+{
+ NDEF_SUPPORT *ndef_aux;
- if (!parg)
- return 0;
+ if (!parg)
+ return 0;
- ndef_aux = *(NDEF_SUPPORT **)parg;
+ ndef_aux = *(NDEF_SUPPORT **)parg;
- if (ndef_aux->derbuf)
- OPENSSL_free(ndef_aux->derbuf);
+ if (ndef_aux->derbuf)
+ OPENSSL_free(ndef_aux->derbuf);
- ndef_aux->derbuf = NULL;
- *pbuf = NULL;
- *plen = 0;
- return 1;
- }
+ ndef_aux->derbuf = NULL;
+ *pbuf = NULL;
+ *plen = 0;
+ return 1;
+}
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
- {
- NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
- if (!ndef_prefix_free(b, pbuf, plen, parg))
- return 0;
- OPENSSL_free(*pndef_aux);
- *pndef_aux = NULL;
- return 1;
- }
+static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
+ void *parg)
+{
+ NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
+ if (!ndef_prefix_free(b, pbuf, plen, parg))
+ return 0;
+ OPENSSL_free(*pndef_aux);
+ *pndef_aux = NULL;
+ return 1;
+}
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
- {
- NDEF_SUPPORT *ndef_aux;
- unsigned char *p;
- int derlen;
- const ASN1_AUX *aux;
- ASN1_STREAM_ARG sarg;
-
- if (!parg)
- return 0;
-
- ndef_aux = *(NDEF_SUPPORT **)parg;
-
- aux = ndef_aux->it->funcs;
-
- /* Finalize structures */
- sarg.ndef_bio = ndef_aux->ndef_bio;
- sarg.out = ndef_aux->out;
- sarg.boundary = ndef_aux->boundary;
- if (aux->asn1_cb(ASN1_OP_STREAM_POST,
- &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
- return 0;
-
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
- p = OPENSSL_malloc(derlen);
- if (p == NULL)
- return 0;
-
- ndef_aux->derbuf = p;
- *pbuf = p;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
-
- if (!*ndef_aux->boundary)
- return 0;
- *pbuf = *ndef_aux->boundary;
- *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
-
- return 1;
- }
+{
+ NDEF_SUPPORT *ndef_aux;
+ unsigned char *p;
+ int derlen;
+ const ASN1_AUX *aux;
+ ASN1_STREAM_ARG sarg;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ aux = ndef_aux->it->funcs;
+
+ /* Finalize structures */
+ sarg.ndef_bio = ndef_aux->ndef_bio;
+ sarg.out = ndef_aux->out;
+ sarg.boundary = ndef_aux->boundary;
+ if (aux->asn1_cb(ASN1_OP_STREAM_POST,
+ &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
+ return 0;
+
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ if (p == NULL)
+ return 0;
+
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+
+ if (!*ndef_aux->boundary)
+ return 0;
+ *pbuf = *ndef_aux->boundary;
+ *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
+
+ return 1;
+}
diff --git a/src/crypto/asn1/f_enum.c b/src/crypto/asn1/f_enum.c
index bcdb7735..3af16f8a 100644
--- a/src/crypto/asn1/f_enum.c
+++ b/src/crypto/asn1/f_enum.c
@@ -62,145 +62,139 @@
/* Based on a_int.c: equivalent ENUMERATED functions */
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
- {
- int i,n=0;
- static const char *h="0123456789ABCDEF";
- char buf[2];
+{
+ int i, n = 0;
+ static const char *h = "0123456789ABCDEF";
+ char buf[2];
- if (a == NULL) return(0);
+ if (a == NULL)
+ return (0);
- if (a->length == 0)
- {
- if (BIO_write(bp,"00",2) != 2) goto err;
- n=2;
- }
- else
- {
- for (i=0; i<a->length; i++)
- {
- if ((i != 0) && (i%35 == 0))
- {
- if (BIO_write(bp,"\\\n",2) != 2) goto err;
- n+=2;
- }
- buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
- buf[1]=h[((unsigned char)a->data[i] )&0x0f];
- if (BIO_write(bp,buf,2) != 2) goto err;
- n+=2;
- }
- }
- return(n);
-err:
- return(-1);
- }
+ if (a->length == 0) {
+ if (BIO_write(bp, "00", 2) != 2)
+ goto err;
+ n = 2;
+ } else {
+ for (i = 0; i < a->length; i++) {
+ if ((i != 0) && (i % 35 == 0)) {
+ if (BIO_write(bp, "\\\n", 2) != 2)
+ goto err;
+ n += 2;
+ }
+ buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+ buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+ if (BIO_write(bp, buf, 2) != 2)
+ goto err;
+ n += 2;
+ }
+ }
+ return (n);
+ err:
+ return (-1);
+}
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
- {
- int ret=0;
- int i,j,k,m,n,again,bufsize;
- unsigned char *s=NULL,*sp;
- unsigned char *bufp;
- int num=0,slen=0,first=1;
+{
+ int ret = 0;
+ int i, j, k, m, n, again, bufsize;
+ unsigned char *s = NULL, *sp;
+ unsigned char *bufp;
+ int num = 0, slen = 0, first = 1;
- bs->type=V_ASN1_ENUMERATED;
+ bs->type = V_ASN1_ENUMERATED;
- bufsize=BIO_gets(bp,buf,size);
- for (;;)
- {
- if (bufsize < 1) goto err_sl;
- i=bufsize;
- if (buf[i-1] == '\n') buf[--i]='\0';
- if (i == 0) goto err_sl;
- if (buf[i-1] == '\r') buf[--i]='\0';
- if (i == 0) goto err_sl;
- again=(buf[i-1] == '\\');
+ bufsize = BIO_gets(bp, buf, size);
+ for (;;) {
+ if (bufsize < 1)
+ goto err_sl;
+ i = bufsize;
+ if (buf[i - 1] == '\n')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ if (buf[i - 1] == '\r')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ again = (buf[i - 1] == '\\');
- for (j=0; j<i; j++)
- {
- if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
- ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
- ((buf[j] >= 'A') && (buf[j] <= 'F'))))
- {
- i=j;
- break;
- }
- }
- buf[i]='\0';
- /* We have now cleared all the crap off the end of the
- * line */
- if (i < 2) goto err_sl;
-
- bufp=(unsigned char *)buf;
- if (first)
- {
- first=0;
- if ((bufp[0] == '0') && (buf[1] == '0'))
- {
- bufp+=2;
- i-=2;
- }
- }
- k=0;
- i-=again;
- if (i%2 != 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
- goto err;
- }
- i/=2;
- if (num+i > slen)
- {
- if (s == NULL)
- sp=(unsigned char *)OPENSSL_malloc(
- (unsigned int)num+i*2);
- else
- sp=(unsigned char *)OPENSSL_realloc(s,
- (unsigned int)num+i*2);
- if (sp == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- s=sp;
- slen=num+i*2;
- }
- for (j=0; j<i; j++,k+=2)
- {
- for (n=0; n<2; n++)
- {
- m=bufp[k+n];
- if ((m >= '0') && (m <= '9'))
- m-='0';
- else if ((m >= 'a') && (m <= 'f'))
- m=m-'a'+10;
- else if ((m >= 'A') && (m <= 'F'))
- m=m-'A'+10;
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
- goto err;
- }
- s[num+j]<<=4;
- s[num+j]|=m;
- }
- }
- num+=i;
- if (again)
- bufsize=BIO_gets(bp,buf,size);
- else
- break;
- }
- bs->length=num;
- bs->data=s;
- ret=1;
-err:
- if (0)
- {
-err_sl:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
- }
- if (s != NULL)
- OPENSSL_free(s);
- return(ret);
- }
+ for (j = 0; j < i; j++) {
+ if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F')))) {
+ i = j;
+ break;
+ }
+ }
+ buf[i] = '\0';
+ /*
+ * We have now cleared all the crap off the end of the line
+ */
+ if (i < 2)
+ goto err_sl;
+ bufp = (unsigned char *)buf;
+ if (first) {
+ first = 0;
+ if ((bufp[0] == '0') && (buf[1] == '0')) {
+ bufp += 2;
+ i -= 2;
+ }
+ }
+ k = 0;
+ i -= again;
+ if (i % 2 != 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i /= 2;
+ if (num + i > slen) {
+ if (s == NULL)
+ sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
+ i * 2);
+ else
+ sp = (unsigned char *)OPENSSL_realloc(s,
+ (unsigned int)num +
+ i * 2);
+ if (sp == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s = sp;
+ slen = num + i * 2;
+ }
+ for (j = 0; j < i; j++, k += 2) {
+ for (n = 0; n < 2; n++) {
+ m = bufp[k + n];
+ if ((m >= '0') && (m <= '9'))
+ m -= '0';
+ else if ((m >= 'a') && (m <= 'f'))
+ m = m - 'a' + 10;
+ else if ((m >= 'A') && (m <= 'F'))
+ m = m - 'A' + 10;
+ else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
+ goto err;
+ }
+ s[num + j] <<= 4;
+ s[num + j] |= m;
+ }
+ }
+ num += i;
+ if (again)
+ bufsize = BIO_gets(bp, buf, size);
+ else
+ break;
+ }
+ bs->length = num;
+ bs->data = s;
+ ret = 1;
+ err:
+ if (0) {
+ err_sl:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return (ret);
+}
diff --git a/src/crypto/asn1/f_int.c b/src/crypto/asn1/f_int.c
index 5186304b..60c0f2f2 100644
--- a/src/crypto/asn1/f_int.c
+++ b/src/crypto/asn1/f_int.c
@@ -59,152 +59,144 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
- {
- int i,n=0;
- static const char *h="0123456789ABCDEF";
- char buf[2];
+{
+ int i, n = 0;
+ static const char *h = "0123456789ABCDEF";
+ char buf[2];
- if (a == NULL) return(0);
+ if (a == NULL)
+ return (0);
- if (a->type & V_ASN1_NEG)
- {
- if (BIO_write(bp, "-", 1) != 1) goto err;
- n = 1;
- }
+ if (a->type & V_ASN1_NEG) {
+ if (BIO_write(bp, "-", 1) != 1)
+ goto err;
+ n = 1;
+ }
- if (a->length == 0)
- {
- if (BIO_write(bp,"00",2) != 2) goto err;
- n += 2;
- }
- else
- {
- for (i=0; i<a->length; i++)
- {
- if ((i != 0) && (i%35 == 0))
- {
- if (BIO_write(bp,"\\\n",2) != 2) goto err;
- n+=2;
- }
- buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
- buf[1]=h[((unsigned char)a->data[i] )&0x0f];
- if (BIO_write(bp,buf,2) != 2) goto err;
- n+=2;
- }
- }
- return(n);
-err:
- return(-1);
- }
+ if (a->length == 0) {
+ if (BIO_write(bp, "00", 2) != 2)
+ goto err;
+ n += 2;
+ } else {
+ for (i = 0; i < a->length; i++) {
+ if ((i != 0) && (i % 35 == 0)) {
+ if (BIO_write(bp, "\\\n", 2) != 2)
+ goto err;
+ n += 2;
+ }
+ buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+ buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+ if (BIO_write(bp, buf, 2) != 2)
+ goto err;
+ n += 2;
+ }
+ }
+ return (n);
+ err:
+ return (-1);
+}
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
- {
- int ret=0;
- int i,j,k,m,n,again,bufsize;
- unsigned char *s=NULL,*sp;
- unsigned char *bufp;
- int num=0,slen=0,first=1;
-
- bs->type=V_ASN1_INTEGER;
+{
+ int ret = 0;
+ int i, j, k, m, n, again, bufsize;
+ unsigned char *s = NULL, *sp;
+ unsigned char *bufp;
+ int num = 0, slen = 0, first = 1;
- bufsize=BIO_gets(bp,buf,size);
- for (;;)
- {
- if (bufsize < 1) goto err_sl;
- i=bufsize;
- if (buf[i-1] == '\n') buf[--i]='\0';
- if (i == 0) goto err_sl;
- if (buf[i-1] == '\r') buf[--i]='\0';
- if (i == 0) goto err_sl;
- again=(buf[i-1] == '\\');
+ bs->type = V_ASN1_INTEGER;
- for (j=0; j<i; j++)
- {
- if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
- ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
- ((buf[j] >= 'A') && (buf[j] <= 'F'))))
- {
- i=j;
- break;
- }
- }
- buf[i]='\0';
- /* We have now cleared all the crap off the end of the
- * line */
- if (i < 2) goto err_sl;
+ bufsize = BIO_gets(bp, buf, size);
+ for (;;) {
+ if (bufsize < 1)
+ goto err_sl;
+ i = bufsize;
+ if (buf[i - 1] == '\n')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ if (buf[i - 1] == '\r')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ again = (buf[i - 1] == '\\');
- bufp=(unsigned char *)buf;
- if (first)
- {
- first=0;
- if ((bufp[0] == '0') && (buf[1] == '0'))
- {
- bufp+=2;
- i-=2;
- }
- }
- k=0;
- i-=again;
- if (i%2 != 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
- goto err;
- }
- i/=2;
- if (num+i > slen)
- {
- if (s == NULL)
- sp=(unsigned char *)OPENSSL_malloc(
- (unsigned int)num+i*2);
- else
- sp=OPENSSL_realloc_clean(s,slen,num+i*2);
- if (sp == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- s=sp;
- slen=num+i*2;
- }
- for (j=0; j<i; j++,k+=2)
- {
- for (n=0; n<2; n++)
- {
- m=bufp[k+n];
- if ((m >= '0') && (m <= '9'))
- m-='0';
- else if ((m >= 'a') && (m <= 'f'))
- m=m-'a'+10;
- else if ((m >= 'A') && (m <= 'F'))
- m=m-'A'+10;
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
- goto err;
- }
- s[num+j]<<=4;
- s[num+j]|=m;
- }
- }
- num+=i;
- if (again)
- bufsize=BIO_gets(bp,buf,size);
- else
- break;
- }
- bs->length=num;
- bs->data=s;
- ret=1;
-err:
- if (0)
- {
-err_sl:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
- }
- if (s != NULL)
- OPENSSL_free(s);
- return(ret);
- }
+ for (j = 0; j < i; j++) {
+ if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F')))) {
+ i = j;
+ break;
+ }
+ }
+ buf[i] = '\0';
+ /*
+ * We have now cleared all the crap off the end of the line
+ */
+ if (i < 2)
+ goto err_sl;
+ bufp = (unsigned char *)buf;
+ if (first) {
+ first = 0;
+ if ((bufp[0] == '0') && (buf[1] == '0')) {
+ bufp += 2;
+ i -= 2;
+ }
+ }
+ k = 0;
+ i -= again;
+ if (i % 2 != 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i /= 2;
+ if (num + i > slen) {
+ if (s == NULL)
+ sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
+ i * 2);
+ else
+ sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
+ if (sp == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s = sp;
+ slen = num + i * 2;
+ }
+ for (j = 0; j < i; j++, k += 2) {
+ for (n = 0; n < 2; n++) {
+ m = bufp[k + n];
+ if ((m >= '0') && (m <= '9'))
+ m -= '0';
+ else if ((m >= 'a') && (m <= 'f'))
+ m = m - 'a' + 10;
+ else if ((m >= 'A') && (m <= 'F'))
+ m = m - 'A' + 10;
+ else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
+ goto err;
+ }
+ s[num + j] <<= 4;
+ s[num + j] |= m;
+ }
+ }
+ num += i;
+ if (again)
+ bufsize = BIO_gets(bp, buf, size);
+ else
+ break;
+ }
+ bs->length = num;
+ bs->data = s;
+ ret = 1;
+ err:
+ if (0) {
+ err_sl:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return (ret);
+}
diff --git a/src/crypto/asn1/f_string.c b/src/crypto/asn1/f_string.c
index 5a7fe36a..ec9cb83d 100644
--- a/src/crypto/asn1/f_string.c
+++ b/src/crypto/asn1/f_string.c
@@ -59,146 +59,138 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
-
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
- {
- int i,n=0;
- static const char *h="0123456789ABCDEF";
- char buf[2];
+{
+ int i, n = 0;
+ static const char *h = "0123456789ABCDEF";
+ char buf[2];
- if (a == NULL) return(0);
+ if (a == NULL)
+ return (0);
- if (a->length == 0)
- {
- if (BIO_write(bp,"0",1) != 1) goto err;
- n=1;
- }
- else
- {
- for (i=0; i<a->length; i++)
- {
- if ((i != 0) && (i%35 == 0))
- {
- if (BIO_write(bp,"\\\n",2) != 2) goto err;
- n+=2;
- }
- buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
- buf[1]=h[((unsigned char)a->data[i] )&0x0f];
- if (BIO_write(bp,buf,2) != 2) goto err;
- n+=2;
- }
- }
- return(n);
-err:
- return(-1);
- }
+ if (a->length == 0) {
+ if (BIO_write(bp, "0", 1) != 1)
+ goto err;
+ n = 1;
+ } else {
+ for (i = 0; i < a->length; i++) {
+ if ((i != 0) && (i % 35 == 0)) {
+ if (BIO_write(bp, "\\\n", 2) != 2)
+ goto err;
+ n += 2;
+ }
+ buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+ buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+ if (BIO_write(bp, buf, 2) != 2)
+ goto err;
+ n += 2;
+ }
+ }
+ return (n);
+ err:
+ return (-1);
+}
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
- {
- int ret=0;
- int i,j,k,m,n,again,bufsize;
- unsigned char *s=NULL,*sp;
- unsigned char *bufp;
- int num=0,slen=0,first=1;
-
- bufsize=BIO_gets(bp,buf,size);
- for (;;)
- {
- if (bufsize < 1)
- {
- if (first)
- break;
- else
- goto err_sl;
- }
- first=0;
+{
+ int ret = 0;
+ int i, j, k, m, n, again, bufsize;
+ unsigned char *s = NULL, *sp;
+ unsigned char *bufp;
+ int num = 0, slen = 0, first = 1;
- i=bufsize;
- if (buf[i-1] == '\n') buf[--i]='\0';
- if (i == 0) goto err_sl;
- if (buf[i-1] == '\r') buf[--i]='\0';
- if (i == 0) goto err_sl;
- again=(buf[i-1] == '\\');
+ bufsize = BIO_gets(bp, buf, size);
+ for (;;) {
+ if (bufsize < 1) {
+ if (first)
+ break;
+ else
+ goto err_sl;
+ }
+ first = 0;
- for (j=i-1; j>0; j--)
- {
- if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
- ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
- ((buf[j] >= 'A') && (buf[j] <= 'F'))))
- {
- i=j;
- break;
- }
- }
- buf[i]='\0';
- /* We have now cleared all the crap off the end of the
- * line */
- if (i < 2) goto err_sl;
+ i = bufsize;
+ if (buf[i - 1] == '\n')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ if (buf[i - 1] == '\r')
+ buf[--i] = '\0';
+ if (i == 0)
+ goto err_sl;
+ again = (buf[i - 1] == '\\');
- bufp=(unsigned char *)buf;
+ for (j = i - 1; j > 0; j--) {
+ if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F')))) {
+ i = j;
+ break;
+ }
+ }
+ buf[i] = '\0';
+ /*
+ * We have now cleared all the crap off the end of the line
+ */
+ if (i < 2)
+ goto err_sl;
- k=0;
- i-=again;
- if (i%2 != 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
- goto err;
- }
- i/=2;
- if (num+i > slen)
- {
- if (s == NULL)
- sp=(unsigned char *)OPENSSL_malloc(
- (unsigned int)num+i*2);
- else
- sp=(unsigned char *)OPENSSL_realloc(s,
- (unsigned int)num+i*2);
- if (sp == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- s=sp;
- slen=num+i*2;
- }
- for (j=0; j<i; j++,k+=2)
- {
- for (n=0; n<2; n++)
- {
- m=bufp[k+n];
- if ((m >= '0') && (m <= '9'))
- m-='0';
- else if ((m >= 'a') && (m <= 'f'))
- m=m-'a'+10;
- else if ((m >= 'A') && (m <= 'F'))
- m=m-'A'+10;
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
- goto err;
- }
- s[num+j]<<=4;
- s[num+j]|=m;
- }
- }
- num+=i;
- if (again)
- bufsize=BIO_gets(bp,buf,size);
- else
- break;
- }
- bs->length=num;
- bs->data=s;
- ret=1;
-err:
- if (0)
- {
-err_sl:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
- }
- if (s != NULL)
- OPENSSL_free(s);
- return(ret);
- }
+ bufp = (unsigned char *)buf;
+ k = 0;
+ i -= again;
+ if (i % 2 != 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i /= 2;
+ if (num + i > slen) {
+ if (s == NULL)
+ sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
+ i * 2);
+ else
+ sp = (unsigned char *)OPENSSL_realloc(s,
+ (unsigned int)num +
+ i * 2);
+ if (sp == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s = sp;
+ slen = num + i * 2;
+ }
+ for (j = 0; j < i; j++, k += 2) {
+ for (n = 0; n < 2; n++) {
+ m = bufp[k + n];
+ if ((m >= '0') && (m <= '9'))
+ m -= '0';
+ else if ((m >= 'a') && (m <= 'f'))
+ m = m - 'a' + 10;
+ else if ((m >= 'A') && (m <= 'F'))
+ m = m - 'A' + 10;
+ else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
+ goto err;
+ }
+ s[num + j] <<= 4;
+ s[num + j] |= m;
+ }
+ }
+ num += i;
+ if (again)
+ bufsize = BIO_gets(bp, buf, size);
+ else
+ break;
+ }
+ bs->length = num;
+ bs->data = s;
+ ret = 1;
+ err:
+ if (0) {
+ err_sl:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return (ret);
+}
diff --git a/src/crypto/asn1/t_bitst.c b/src/crypto/asn1/t_bitst.c
index 1ca6e089..e754ca73 100644
--- a/src/crypto/asn1/t_bitst.c
+++ b/src/crypto/asn1/t_bitst.c
@@ -60,43 +60,44 @@
#include <openssl/mem.h>
-
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
- BIT_STRING_BITNAME *tbl, int indent)
+ BIT_STRING_BITNAME *tbl, int indent)
{
- BIT_STRING_BITNAME *bnam;
- char first = 1;
- BIO_printf(out, "%*s", indent, "");
- for(bnam = tbl; bnam->lname; bnam++) {
- if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
- if(!first) BIO_puts(out, ", ");
- BIO_puts(out, bnam->lname);
- first = 0;
- }
- }
- BIO_puts(out, "\n");
- return 1;
+ BIT_STRING_BITNAME *bnam;
+ char first = 1;
+ BIO_printf(out, "%*s", indent, "");
+ for (bnam = tbl; bnam->lname; bnam++) {
+ if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
+ if (!first)
+ BIO_puts(out, ", ");
+ BIO_puts(out, bnam->lname);
+ first = 0;
+ }
+ }
+ BIO_puts(out, "\n");
+ return 1;
}
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
- BIT_STRING_BITNAME *tbl)
+ BIT_STRING_BITNAME *tbl)
{
- int bitnum;
- bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
- if(bitnum < 0) return 0;
- if(bs) {
- if(!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
- return 0;
- }
- return 1;
+ int bitnum;
+ bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
+ if (bitnum < 0)
+ return 0;
+ if (bs) {
+ if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
+ return 0;
+ }
+ return 1;
}
int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
{
- BIT_STRING_BITNAME *bnam;
- for(bnam = tbl; bnam->lname; bnam++) {
- if(!strcmp(bnam->sname, name) ||
- !strcmp(bnam->lname, name) ) return bnam->bitnum;
- }
- return -1;
+ BIT_STRING_BITNAME *bnam;
+ for (bnam = tbl; bnam->lname; bnam++) {
+ if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name))
+ return bnam->bitnum;
+ }
+ return -1;
}
diff --git a/src/crypto/asn1/t_pkey.c b/src/crypto/asn1/t_pkey.c
deleted file mode 100644
index 6ac9b3d6..00000000
--- a/src/crypto/asn1/t_pkey.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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 acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS 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 AUTHOR OR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <openssl/bio.h>
-#include <openssl/mem.h>
-
-
-int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
- unsigned char *buf, int off)
- {
- int n,i;
- const char *neg;
-
- if (num == NULL) return(1);
- neg = (BN_is_negative(num))?"-":"";
- if(!BIO_indent(bp,off,128))
- return 0;
- if (BN_is_zero(num))
- {
- if (BIO_printf(bp, "%s 0\n", number) <= 0)
- return 0;
- return 1;
- }
-
- if (BN_num_bytes(num) <= sizeof(long))
- {
- if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
- (unsigned long)num->d[0],neg,(unsigned long)num->d[0])
- <= 0) return(0);
- }
- else
- {
- buf[0]=0;
- if (BIO_printf(bp,"%s%s",number,
- (neg[0] == '-')?" (Negative)":"") <= 0)
- return(0);
- n=BN_bn2bin(num,&buf[1]);
-
- if (buf[1] & 0x80)
- n++;
- else buf++;
-
- for (i=0; i<n; i++)
- {
- if ((i%15) == 0)
- {
- if(BIO_puts(bp,"\n") <= 0
- || !BIO_indent(bp,off+4,128))
- return 0;
- }
- if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
- <= 0) return(0);
- }
- if (BIO_write(bp,"\n",1) <= 0) return(0);
- }
- return(1);
- }
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index 7c81753f..40d575d2 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -65,1278 +65,1157 @@
#include "../internal.h"
-
static int asn1_check_eoc(const unsigned char **in, long len);
static int asn1_find_end(const unsigned char **in, long len, char inf);
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
- char inf, int tag, int aclass, int depth);
+ char inf, int tag, int aclass, int depth);
static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
- char *inf, char *cst,
- const unsigned char **in, long len,
- int exptag, int expclass, char opt,
- ASN1_TLC *ctx);
+ char *inf, char *cst,
+ const unsigned char **in, long len,
+ int exptag, int expclass, char opt, ASN1_TLC *ctx);
static int asn1_template_ex_d2i(ASN1_VALUE **pval,
- const unsigned char **in, long len,
- const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx);
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx);
static int asn1_template_noexp_d2i(ASN1_VALUE **val,
- const unsigned char **in, long len,
- const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx);
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx);
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
- const unsigned char **in, long len,
- const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx);
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt,
+ ASN1_TLC *ctx);
/* Table to convert tags to bit values, used for MSTRING type */
static const unsigned long tag2bit[32] = {
-0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */
-B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */
-B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */
-B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
-B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
-B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */
-B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */
-B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */
-B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
- };
+ 0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */
+ B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, /* tags 4- 7 */
+ B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags
+ * 8-11 */
+ B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags
+ * 12-15
+ */
+ B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, /* tags
+ * 16-19
+ */
+ B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, /* tags 20-22 */
+ B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */
+ B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, /* tags
+ * 25-27 */
+ B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, /* tags
+ * 28-31
+ */
+};
unsigned long ASN1_tag2bit(int tag)
- {
- if ((tag < 0) || (tag > 30)) return 0;
- return tag2bit[tag];
- }
+{
+ if ((tag < 0) || (tag > 30))
+ return 0;
+ return tag2bit[tag];
+}
/* Macro to initialize and invalidate the cache */
-#define asn1_tlc_clear(c) if (c) (c)->valid = 0
+#define asn1_tlc_clear(c) if (c) (c)->valid = 0
/* Version to avoid compiler warning about 'c' always non-NULL */
-#define asn1_tlc_clear_nc(c) (c)->valid = 0
-
-/* Decode an ASN1 item, this currently behaves just
- * like a standard 'd2i' function. 'in' points to
- * a buffer to read the data from, in future we will
- * have more advanced versions that can input data
- * a piece at a time and this will simply be a special
- * case.
+#define asn1_tlc_clear_nc(c) (c)->valid = 0
+
+/*
+ * Decode an ASN1 item, this currently behaves just like a standard 'd2i'
+ * function. 'in' points to a buffer to read the data from, in future we
+ * will have more advanced versions that can input data a piece at a time and
+ * this will simply be a special case.
*/
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
- const unsigned char **in, long len, const ASN1_ITEM *it)
- {
- ASN1_TLC c;
- ASN1_VALUE *ptmpval = NULL;
- if (!pval)
- pval = &ptmpval;
- asn1_tlc_clear_nc(&c);
- if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
- return *pval;
- return NULL;
- }
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it)
+{
+ ASN1_TLC c;
+ ASN1_VALUE *ptmpval = NULL;
+ if (!pval)
+ pval = &ptmpval;
+ asn1_tlc_clear_nc(&c);
+ if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+ return *pval;
+ return NULL;
+}
int ASN1_template_d2i(ASN1_VALUE **pval,
- const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
- {
- ASN1_TLC c;
- asn1_tlc_clear_nc(&c);
- return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
- }
-
-
-/* Decode an item, taking care of IMPLICIT tagging, if any.
- * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt)
+{
+ ASN1_TLC c;
+ asn1_tlc_clear_nc(&c);
+ return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
+}
+
+/*
+ * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
+ * tag mismatch return -1 to handle OPTIONAL
*/
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
- const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx)
- {
- const ASN1_TEMPLATE *tt, *errtt = NULL;
- const ASN1_COMPAT_FUNCS *cf;
- const ASN1_EXTERN_FUNCS *ef;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
- const unsigned char *p = NULL, *q;
- unsigned char *wp=NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */
- unsigned char imphack = 0, oclass;
- char seq_eoc, seq_nolen, cst, isopt;
- long tmplen;
- int i;
- int otag;
- int ret = 0;
- ASN1_VALUE **pchptr, *ptmpval;
- int combine = aclass & ASN1_TFLG_COMBINE;
- if (!pval)
- return 0;
- if (aux && aux->asn1_cb)
- asn1_cb = aux->asn1_cb;
- else asn1_cb = 0;
-
- switch(it->itype)
- {
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates)
- {
- /* tagging or OPTIONAL is currently illegal on an item
- * template because the flags can't get passed down.
- * In practice this isn't a problem: we include the
- * relevant flags from the item template in the
- * template itself.
- */
- if ((tag != -1) || opt)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
- goto err;
- }
- return asn1_template_ex_d2i(pval, in, len,
- it->templates, opt, ctx);
- }
- return asn1_d2i_ex_primitive(pval, in, len, it,
- tag, aclass, opt, ctx);
- break;
-
- case ASN1_ITYPE_MSTRING:
- p = *in;
- /* Just read in tag and class */
- ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
- &p, len, -1, 0, 1, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
-
- /* Must be UNIVERSAL class */
- if (oclass != V_ASN1_UNIVERSAL)
- {
- /* If OPTIONAL, assume this is OK */
- if (opt) return -1;
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
- goto err;
- }
- /* Check tag matches bit map */
- if (!(ASN1_tag2bit(otag) & it->utype))
- {
- /* If OPTIONAL, assume this is OK */
- if (opt)
- return -1;
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG);
- goto err;
- }
- return asn1_d2i_ex_primitive(pval, in, len,
- it, otag, 0, 0, ctx);
-
- case ASN1_ITYPE_EXTERN:
- /* Use new style d2i */
- ef = it->funcs;
- return ef->asn1_ex_d2i(pval, in, len,
- it, tag, aclass, opt, ctx);
-
- case ASN1_ITYPE_COMPAT:
- /* we must resort to old style evil hackery */
- cf = it->funcs;
-
- /* If OPTIONAL see if it is there */
- if (opt)
- {
- int exptag;
- p = *in;
- if (tag == -1)
- exptag = it->utype;
- else exptag = tag;
- /* Don't care about anything other than presence
- * of expected tag */
-
- ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
- &p, len, exptag, aclass, 1, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- if (ret == -1)
- return -1;
- }
-
- /* This is the old style evil hack IMPLICIT handling:
- * since the underlying code is expecting a tag and
- * class other than the one present we change the
- * buffer temporarily then change it back afterwards.
- * This doesn't and never did work for tags > 30.
- *
- * Yes this is *horrible* but it is only needed for
- * old style d2i which will hopefully not be around
- * for much longer.
- * FIXME: should copy the buffer then modify it so
- * the input buffer can be const: we should *always*
- * copy because the old style d2i might modify the
- * buffer.
- */
-
- if (tag != -1)
- {
- wp = *(unsigned char **)in;
- imphack = *wp;
- if (p == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
- | it->utype);
- }
-
- ptmpval = cf->asn1_d2i(pval, in, len);
-
- if (tag != -1)
- *wp = imphack;
-
- if (ptmpval)
- return 1;
-
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
-
-
- case ASN1_ITYPE_CHOICE:
- if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
- goto auxerr;
-
- if (*pval)
- {
- /* Free up and zero CHOICE value if initialised */
- i = asn1_get_choice_selector(pval, it);
- if ((i >= 0) && (i < it->tcount))
- {
- tt = it->templates + i;
- pchptr = asn1_get_field_ptr(pval, tt);
- ASN1_template_free(pchptr, tt);
- asn1_set_choice_selector(pval, -1, it);
- }
- }
- else if (!ASN1_item_ex_new(pval, it))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- /* CHOICE type, try each possibility in turn */
- p = *in;
- for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
- {
- pchptr = asn1_get_field_ptr(pval, tt);
- /* We mark field as OPTIONAL so its absence
- * can be recognised.
- */
- ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
- /* If field not present, try the next one */
- if (ret == -1)
- continue;
- /* If positive return, read OK, break loop */
- if (ret > 0)
- break;
- /* Otherwise must be an ASN1 parsing error */
- errtt = tt;
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
-
- /* Did we fall off the end without reading anything? */
- if (i == it->tcount)
- {
- /* If OPTIONAL, this is OK */
- if (opt)
- {
- /* Free and zero it */
- ASN1_item_ex_free(pval, it);
- return -1;
- }
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
- goto err;
- }
-
- asn1_set_choice_selector(pval, i, it);
- if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
- goto auxerr;
- *in = p;
- return 1;
-
- case ASN1_ITYPE_NDEF_SEQUENCE:
- case ASN1_ITYPE_SEQUENCE:
- p = *in;
- tmplen = len;
-
- /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
- if (tag == -1)
- {
- tag = V_ASN1_SEQUENCE;
- aclass = V_ASN1_UNIVERSAL;
- }
- /* Get SEQUENCE length and update len, p */
- ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
- &p, len, tag, aclass, opt, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- else if (ret == -1)
- return -1;
- if (aux && (aux->flags & ASN1_AFLG_BROKEN))
- {
- len = tmplen - (p - *in);
- seq_nolen = 1;
- }
- /* If indefinite we don't do a length check */
- else seq_nolen = seq_eoc;
- if (!cst)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
- goto err;
- }
-
- if (!*pval && !ASN1_item_ex_new(pval, it))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
-
- if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
- goto auxerr;
-
- /* Free up and zero any ADB found */
- for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
- {
- if (tt->flags & ASN1_TFLG_ADB_MASK)
- {
- const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
- pseqval = asn1_get_field_ptr(pval, seqtt);
- ASN1_template_free(pseqval, seqtt);
- }
- }
-
- /* Get each field entry */
- for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
- {
- const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
- if (!seqtt)
- goto err;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- /* Have we ran out of data? */
- if (!len)
- break;
- q = p;
- if (asn1_check_eoc(&p, len))
- {
- if (!seq_eoc)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
- goto err;
- }
- len -= p - q;
- seq_eoc = 0;
- q = p;
- break;
- }
- /* This determines the OPTIONAL flag value. The field
- * cannot be omitted if it is the last of a SEQUENCE
- * and there is still data to be read. This isn't
- * strictly necessary but it increases efficiency in
- * some cases.
- */
- if (i == (it->tcount - 1))
- isopt = 0;
- else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
- /* attempt to read in field, allowing each to be
- * OPTIONAL */
-
- ret = asn1_template_ex_d2i(pseqval, &p, len,
- seqtt, isopt, ctx);
- if (!ret)
- {
- errtt = seqtt;
- goto err;
- }
- else if (ret == -1)
- {
- /* OPTIONAL component absent.
- * Free and zero the field.
- */
- ASN1_template_free(pseqval, seqtt);
- continue;
- }
- /* Update length */
- len -= p - q;
- }
-
- /* Check for EOC if expecting one */
- if (seq_eoc && !asn1_check_eoc(&p, len))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
- goto err;
- }
- /* Check all data read */
- if (!seq_nolen && len)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
- goto err;
- }
-
- /* If we get here we've got no more data in the SEQUENCE,
- * however we may not have read all fields so check all
- * remaining are OPTIONAL and clear any that are.
- */
- for (; i < it->tcount; tt++, i++)
- {
- const ASN1_TEMPLATE *seqtt;
- seqtt = asn1_do_adb(pval, tt, 1);
- if (!seqtt)
- goto err;
- if (seqtt->flags & ASN1_TFLG_OPTIONAL)
- {
- ASN1_VALUE **pseqval;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- ASN1_template_free(pseqval, seqtt);
- }
- else
- {
- errtt = seqtt;
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING);
- goto err;
- }
- }
- /* Save encoding */
- if (!asn1_enc_save(pval, *in, p - *in, it))
- goto auxerr;
- if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
- goto auxerr;
- *in = p;
- return 1;
-
- default:
- return 0;
- }
- auxerr:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
- err:
- if (combine == 0)
- ASN1_item_ex_free(pval, it);
- if (errtt)
- ERR_add_error_data(4, "Field=", errtt->field_name,
- ", Type=", it->sname);
- else
- ERR_add_error_data(2, "Type=", it->sname);
- return 0;
- }
-
-/* Templates are handled with two separate functions.
- * One handles any EXPLICIT tag and the other handles the rest.
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+ const ASN1_TEMPLATE *tt, *errtt = NULL;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ const unsigned char *p = NULL, *q;
+ unsigned char *wp = NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */
+ unsigned char imphack = 0, oclass;
+ char seq_eoc, seq_nolen, cst, isopt;
+ long tmplen;
+ int i;
+ int otag;
+ int ret = 0;
+ ASN1_VALUE **pchptr, *ptmpval;
+ int combine = aclass & ASN1_TFLG_COMBINE;
+ if (!pval)
+ return 0;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else
+ asn1_cb = 0;
+
+ switch (it->itype) {
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates) {
+ /*
+ * tagging or OPTIONAL is currently illegal on an item template
+ * because the flags can't get passed down. In practice this
+ * isn't a problem: we include the relevant flags from the item
+ * template in the template itself.
+ */
+ if ((tag != -1) || opt) {
+ OPENSSL_PUT_ERROR(ASN1,
+ ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+ goto err;
+ }
+ return asn1_template_ex_d2i(pval, in, len,
+ it->templates, opt, ctx);
+ }
+ return asn1_d2i_ex_primitive(pval, in, len, it,
+ tag, aclass, opt, ctx);
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ p = *in;
+ /* Just read in tag and class */
+ ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
+ &p, len, -1, 0, 1, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ /* Must be UNIVERSAL class */
+ if (oclass != V_ASN1_UNIVERSAL) {
+ /* If OPTIONAL, assume this is OK */
+ if (opt)
+ return -1;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
+ goto err;
+ }
+ /* Check tag matches bit map */
+ if (!(ASN1_tag2bit(otag) & it->utype)) {
+ /* If OPTIONAL, assume this is OK */
+ if (opt)
+ return -1;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG);
+ goto err;
+ }
+ return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx);
+
+ case ASN1_ITYPE_EXTERN:
+ /* Use new style d2i */
+ ef = it->funcs;
+ return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
+
+ case ASN1_ITYPE_COMPAT:
+ /* we must resort to old style evil hackery */
+ cf = it->funcs;
+
+ /* If OPTIONAL see if it is there */
+ if (opt) {
+ int exptag;
+ p = *in;
+ if (tag == -1)
+ exptag = it->utype;
+ else
+ exptag = tag;
+ /*
+ * Don't care about anything other than presence of expected tag
+ */
+
+ ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
+ &p, len, exptag, aclass, 1, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ if (ret == -1)
+ return -1;
+ }
+
+ /*
+ * This is the old style evil hack IMPLICIT handling: since the
+ * underlying code is expecting a tag and class other than the one
+ * present we change the buffer temporarily then change it back
+ * afterwards. This doesn't and never did work for tags > 30. Yes
+ * this is *horrible* but it is only needed for old style d2i which
+ * will hopefully not be around for much longer. FIXME: should copy
+ * the buffer then modify it so the input buffer can be const: we
+ * should *always* copy because the old style d2i might modify the
+ * buffer.
+ */
+
+ if (tag != -1) {
+ wp = *(unsigned char **)in;
+ imphack = *wp;
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
+ | it->utype);
+ }
+
+ ptmpval = cf->asn1_d2i(pval, in, len);
+
+ if (tag != -1)
+ *wp = imphack;
+
+ if (ptmpval)
+ return 1;
+
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+
+ case ASN1_ITYPE_CHOICE:
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+ goto auxerr;
+
+ if (*pval) {
+ /* Free up and zero CHOICE value if initialised */
+ i = asn1_get_choice_selector(pval, it);
+ if ((i >= 0) && (i < it->tcount)) {
+ tt = it->templates + i;
+ pchptr = asn1_get_field_ptr(pval, tt);
+ ASN1_template_free(pchptr, tt);
+ asn1_set_choice_selector(pval, -1, it);
+ }
+ } else if (!ASN1_item_ex_new(pval, it)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ /* CHOICE type, try each possibility in turn */
+ p = *in;
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+ pchptr = asn1_get_field_ptr(pval, tt);
+ /*
+ * We mark field as OPTIONAL so its absence can be recognised.
+ */
+ ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
+ /* If field not present, try the next one */
+ if (ret == -1)
+ continue;
+ /* If positive return, read OK, break loop */
+ if (ret > 0)
+ break;
+ /* Otherwise must be an ASN1 parsing error */
+ errtt = tt;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ /* Did we fall off the end without reading anything? */
+ if (i == it->tcount) {
+ /* If OPTIONAL, this is OK */
+ if (opt) {
+ /* Free and zero it */
+ ASN1_item_ex_free(pval, it);
+ return -1;
+ }
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
+ goto err;
+ }
+
+ asn1_set_choice_selector(pval, i, it);
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+ goto auxerr;
+ *in = p;
+ return 1;
+
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ case ASN1_ITYPE_SEQUENCE:
+ p = *in;
+ tmplen = len;
+
+ /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+ if (tag == -1) {
+ tag = V_ASN1_SEQUENCE;
+ aclass = V_ASN1_UNIVERSAL;
+ }
+ /* Get SEQUENCE length and update len, p */
+ ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
+ &p, len, tag, aclass, opt, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ } else if (ret == -1)
+ return -1;
+ if (aux && (aux->flags & ASN1_AFLG_BROKEN)) {
+ len = tmplen - (p - *in);
+ seq_nolen = 1;
+ }
+ /* If indefinite we don't do a length check */
+ else
+ seq_nolen = seq_eoc;
+ if (!cst) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+ goto err;
+ }
+
+ if (!*pval && !ASN1_item_ex_new(pval, it)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+ goto auxerr;
+
+ /* Free up and zero any ADB found */
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+ if (tt->flags & ASN1_TFLG_ADB_MASK) {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ ASN1_template_free(pseqval, seqtt);
+ }
+ }
+
+ /* Get each field entry */
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ goto err;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ /* Have we ran out of data? */
+ if (!len)
+ break;
+ q = p;
+ if (asn1_check_eoc(&p, len)) {
+ if (!seq_eoc) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+ goto err;
+ }
+ len -= p - q;
+ seq_eoc = 0;
+ q = p;
+ break;
+ }
+ /*
+ * This determines the OPTIONAL flag value. The field cannot be
+ * omitted if it is the last of a SEQUENCE and there is still
+ * data to be read. This isn't strictly necessary but it
+ * increases efficiency in some cases.
+ */
+ if (i == (it->tcount - 1))
+ isopt = 0;
+ else
+ isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
+ /*
+ * attempt to read in field, allowing each to be OPTIONAL
+ */
+
+ ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx);
+ if (!ret) {
+ errtt = seqtt;
+ goto err;
+ } else if (ret == -1) {
+ /*
+ * OPTIONAL component absent. Free and zero the field.
+ */
+ ASN1_template_free(pseqval, seqtt);
+ continue;
+ }
+ /* Update length */
+ len -= p - q;
+ }
+
+ /* Check for EOC if expecting one */
+ if (seq_eoc && !asn1_check_eoc(&p, len)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ /* Check all data read */
+ if (!seq_nolen && len) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /*
+ * If we get here we've got no more data in the SEQUENCE, however we
+ * may not have read all fields so check all remaining are OPTIONAL
+ * and clear any that are.
+ */
+ for (; i < it->tcount; tt++, i++) {
+ const ASN1_TEMPLATE *seqtt;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ goto err;
+ if (seqtt->flags & ASN1_TFLG_OPTIONAL) {
+ ASN1_VALUE **pseqval;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ ASN1_template_free(pseqval, seqtt);
+ } else {
+ errtt = seqtt;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING);
+ goto err;
+ }
+ }
+ /* Save encoding */
+ if (!asn1_enc_save(pval, *in, p - *in, it))
+ goto auxerr;
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+ goto auxerr;
+ *in = p;
+ return 1;
+
+ default:
+ return 0;
+ }
+ auxerr:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
+ err:
+ if (combine == 0)
+ ASN1_item_ex_free(pval, it);
+ if (errtt)
+ ERR_add_error_data(4, "Field=", errtt->field_name,
+ ", Type=", it->sname);
+ else
+ ERR_add_error_data(2, "Type=", it->sname);
+ return 0;
+}
+
+/*
+ * Templates are handled with two separate functions. One handles any
+ * EXPLICIT tag and the other handles the rest.
*/
static int asn1_template_ex_d2i(ASN1_VALUE **val,
- const unsigned char **in, long inlen,
- const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx)
- {
- int flags, aclass;
- int ret;
- long len;
- const unsigned char *p, *q;
- char exp_eoc;
- if (!val)
- return 0;
- flags = tt->flags;
- aclass = flags & ASN1_TFLG_TAG_CLASS;
-
- p = *in;
-
- /* Check if EXPLICIT tag expected */
- if (flags & ASN1_TFLG_EXPTAG)
- {
- char cst;
- /* Need to work out amount of data available to the inner
- * content and where it starts: so read in EXPLICIT header to
- * get the info.
- */
- ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
- &p, inlen, tt->tag, aclass, opt, ctx);
- q = p;
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- else if (ret == -1)
- return -1;
- if (!cst)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
- return 0;
- }
- /* We've found the field so it can't be OPTIONAL now */
- ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- /* We read the field in OK so update length */
- len -= p - q;
- if (exp_eoc)
- {
- /* If NDEF we must have an EOC here */
- if (!asn1_check_eoc(&p, len))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
- goto err;
- }
- }
- else
- {
- /* Otherwise we must hit the EXPLICIT tag end or its
- * an error */
- if (len)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
- goto err;
- }
- }
- }
- else
- return asn1_template_noexp_d2i(val, in, inlen,
- tt, opt, ctx);
-
- *in = p;
- return 1;
-
- err:
- ASN1_template_free(val, tt);
- return 0;
- }
+ const unsigned char **in, long inlen,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx)
+{
+ int flags, aclass;
+ int ret;
+ long len;
+ const unsigned char *p, *q;
+ char exp_eoc;
+ if (!val)
+ return 0;
+ flags = tt->flags;
+ aclass = flags & ASN1_TFLG_TAG_CLASS;
+
+ p = *in;
+
+ /* Check if EXPLICIT tag expected */
+ if (flags & ASN1_TFLG_EXPTAG) {
+ char cst;
+ /*
+ * Need to work out amount of data available to the inner content and
+ * where it starts: so read in EXPLICIT header to get the info.
+ */
+ ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
+ &p, inlen, tt->tag, aclass, opt, ctx);
+ q = p;
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ } else if (ret == -1)
+ return -1;
+ if (!cst) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+ return 0;
+ }
+ /* We've found the field so it can't be OPTIONAL now */
+ ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ /* We read the field in OK so update length */
+ len -= p - q;
+ if (exp_eoc) {
+ /* If NDEF we must have an EOC here */
+ if (!asn1_check_eoc(&p, len)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ } else {
+ /*
+ * Otherwise we must hit the EXPLICIT tag end or its an error
+ */
+ if (len) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
+ goto err;
+ }
+ }
+ } else
+ return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx);
+
+ *in = p;
+ return 1;
+
+ err:
+ ASN1_template_free(val, tt);
+ return 0;
+}
static int asn1_template_noexp_d2i(ASN1_VALUE **val,
- const unsigned char **in, long len,
- const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx)
- {
- int flags, aclass;
- int ret;
- const unsigned char *p;
- if (!val)
- return 0;
- flags = tt->flags;
- aclass = flags & ASN1_TFLG_TAG_CLASS;
-
- p = *in;
-
- if (flags & ASN1_TFLG_SK_MASK)
- {
- /* SET OF, SEQUENCE OF */
- int sktag, skaclass;
- char sk_eoc;
- /* First work out expected inner tag value */
- if (flags & ASN1_TFLG_IMPTAG)
- {
- sktag = tt->tag;
- skaclass = aclass;
- }
- else
- {
- skaclass = V_ASN1_UNIVERSAL;
- if (flags & ASN1_TFLG_SET_OF)
- sktag = V_ASN1_SET;
- else
- sktag = V_ASN1_SEQUENCE;
- }
- /* Get the tag */
- ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
- &p, len, sktag, skaclass, opt, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- else if (ret == -1)
- return -1;
- if (!*val)
- *val = (ASN1_VALUE *)sk_new_null();
- else
- {
- /* We've got a valid STACK: free up any items present */
- STACK_OF(ASN1_VALUE) *sktmp
- = (STACK_OF(ASN1_VALUE) *)*val;
- ASN1_VALUE *vtmp;
- while(sk_ASN1_VALUE_num(sktmp) > 0)
- {
- vtmp = sk_ASN1_VALUE_pop(sktmp);
- ASN1_item_ex_free(&vtmp,
- ASN1_ITEM_ptr(tt->item));
- }
- }
-
- if (!*val)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Read as many items as we can */
- while(len > 0)
- {
- ASN1_VALUE *skfield;
- const unsigned char *q = p;
- /* See if EOC found */
- if (asn1_check_eoc(&p, len))
- {
- if (!sk_eoc)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
- goto err;
- }
- len -= p - q;
- sk_eoc = 0;
- break;
- }
- skfield = NULL;
- if (!ASN1_item_ex_d2i(&skfield, &p, len,
- ASN1_ITEM_ptr(tt->item),
- -1, 0, 0, ctx))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- len -= p - q;
- if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
- skfield))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- if (sk_eoc)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
- goto err;
- }
- }
- else if (flags & ASN1_TFLG_IMPTAG)
- {
- /* IMPLICIT tagging */
- ret = ASN1_item_ex_d2i(val, &p, len,
- ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- else if (ret == -1)
- return -1;
- }
- else
- {
- /* Nothing special */
- ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
- -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- goto err;
- }
- else if (ret == -1)
- return -1;
- }
-
- *in = p;
- return 1;
-
- err:
- ASN1_template_free(val, tt);
- return 0;
- }
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx)
+{
+ int flags, aclass;
+ int ret;
+ const unsigned char *p;
+ if (!val)
+ return 0;
+ flags = tt->flags;
+ aclass = flags & ASN1_TFLG_TAG_CLASS;
+
+ p = *in;
+
+ if (flags & ASN1_TFLG_SK_MASK) {
+ /* SET OF, SEQUENCE OF */
+ int sktag, skaclass;
+ char sk_eoc;
+ /* First work out expected inner tag value */
+ if (flags & ASN1_TFLG_IMPTAG) {
+ sktag = tt->tag;
+ skaclass = aclass;
+ } else {
+ skaclass = V_ASN1_UNIVERSAL;
+ if (flags & ASN1_TFLG_SET_OF)
+ sktag = V_ASN1_SET;
+ else
+ sktag = V_ASN1_SEQUENCE;
+ }
+ /* Get the tag */
+ ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
+ &p, len, sktag, skaclass, opt, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ } else if (ret == -1)
+ return -1;
+ if (!*val)
+ *val = (ASN1_VALUE *)sk_new_null();
+ else {
+ /*
+ * We've got a valid STACK: free up any items present
+ */
+ STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val;
+ ASN1_VALUE *vtmp;
+ while (sk_ASN1_VALUE_num(sktmp) > 0) {
+ vtmp = sk_ASN1_VALUE_pop(sktmp);
+ ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item));
+ }
+ }
+
+ if (!*val) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Read as many items as we can */
+ while (len > 0) {
+ ASN1_VALUE *skfield;
+ const unsigned char *q = p;
+ /* See if EOC found */
+ if (asn1_check_eoc(&p, len)) {
+ if (!sk_eoc) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+ goto err;
+ }
+ len -= p - q;
+ sk_eoc = 0;
+ break;
+ }
+ skfield = NULL;
+ if (!ASN1_item_ex_d2i(&skfield, &p, len,
+ ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ len -= p - q;
+ if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if (sk_eoc) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ } else if (flags & ASN1_TFLG_IMPTAG) {
+ /* IMPLICIT tagging */
+ ret = ASN1_item_ex_d2i(val, &p, len,
+ ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt,
+ ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ } else if (ret == -1)
+ return -1;
+ } else {
+ /* Nothing special */
+ ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
+ -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ } else if (ret == -1)
+ return -1;
+ }
+
+ *in = p;
+ return 1;
+
+ err:
+ ASN1_template_free(val, tt);
+ return 0;
+}
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
- const unsigned char **in, long inlen,
- const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
- {
- int ret = 0, utype;
- long plen;
- char cst, inf, free_cont = 0;
- const unsigned char *p;
- BUF_MEM buf;
- const unsigned char *cont = NULL;
- long len;
- if (!pval)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL);
- return 0; /* Should never happen */
- }
-
- if (it->itype == ASN1_ITYPE_MSTRING)
- {
- utype = tag;
- tag = -1;
- }
- else
- utype = it->utype;
-
- if (utype == V_ASN1_ANY)
- {
- /* If type is ANY need to figure out type from tag */
- unsigned char oclass;
- if (tag >= 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
- return 0;
- }
- if (opt)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
- return 0;
- }
- p = *in;
- ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
- &p, inlen, -1, 0, 0, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- if (oclass != V_ASN1_UNIVERSAL)
- utype = V_ASN1_OTHER;
- }
- if (tag == -1)
- {
- tag = utype;
- aclass = V_ASN1_UNIVERSAL;
- }
- p = *in;
- /* Check header */
- ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
- &p, inlen, tag, aclass, opt, ctx);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- else if (ret == -1)
- return -1;
- ret = 0;
- /* SEQUENCE, SET and "OTHER" are left in encoded form */
- if ((utype == V_ASN1_SEQUENCE)
- || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
- {
- /* Clear context cache for type OTHER because the auto clear
- * when we have a exact match wont work
- */
- if (utype == V_ASN1_OTHER)
- {
- asn1_tlc_clear(ctx);
- }
- /* SEQUENCE and SET must be constructed */
- else if (!cst)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
- return 0;
- }
-
- cont = *in;
- /* If indefinite length constructed find the real end */
- if (inf)
- {
- if (!asn1_find_end(&p, plen, inf))
- goto err;
- len = p - cont;
- }
- else
- {
- len = p - cont + plen;
- p += plen;
- buf.data = NULL;
- }
- }
- else if (cst)
- {
- if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
- || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
- || utype == V_ASN1_ENUMERATED)
- {
- /* These types only have primitive encodings. */
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
- return 0;
- }
-
- buf.length = 0;
- buf.max = 0;
- buf.data = NULL;
- /* Should really check the internal tags are correct but
- * some things may get this wrong. The relevant specs
- * say that constructed string types should be OCTET STRINGs
- * internally irrespective of the type. So instead just check
- * for UNIVERSAL class and ignore the tag.
- */
- if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
- {
- free_cont = 1;
- goto err;
- }
- len = buf.length;
- /* Append a final null to string */
- if (!BUF_MEM_grow_clean(&buf, len + 1))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- buf.data[len] = 0;
- cont = (const unsigned char *)buf.data;
- free_cont = 1;
- }
- else
- {
- cont = p;
- len = plen;
- p += plen;
- }
-
- /* We now have content length and type: translate into a structure */
- if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
- goto err;
-
- *in = p;
- ret = 1;
- err:
- if (free_cont && buf.data) OPENSSL_free(buf.data);
- return ret;
- }
+ const unsigned char **in, long inlen,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+ int ret = 0, utype;
+ long plen;
+ char cst, inf, free_cont = 0;
+ const unsigned char *p;
+ BUF_MEM buf = {0, NULL, 0 };
+ const unsigned char *cont = NULL;
+ long len;
+ if (!pval) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL);
+ return 0; /* Should never happen */
+ }
+
+ if (it->itype == ASN1_ITYPE_MSTRING) {
+ utype = tag;
+ tag = -1;
+ } else
+ utype = it->utype;
+
+ if (utype == V_ASN1_ANY) {
+ /* If type is ANY need to figure out type from tag */
+ unsigned char oclass;
+ if (tag >= 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
+ return 0;
+ }
+ if (opt) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
+ return 0;
+ }
+ p = *in;
+ ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
+ &p, inlen, -1, 0, 0, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ if (oclass != V_ASN1_UNIVERSAL)
+ utype = V_ASN1_OTHER;
+ }
+ if (tag == -1) {
+ tag = utype;
+ aclass = V_ASN1_UNIVERSAL;
+ }
+ p = *in;
+ /* Check header */
+ ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
+ &p, inlen, tag, aclass, opt, ctx);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ } else if (ret == -1)
+ return -1;
+ ret = 0;
+ /* SEQUENCE, SET and "OTHER" are left in encoded form */
+ if ((utype == V_ASN1_SEQUENCE)
+ || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) {
+ /*
+ * Clear context cache for type OTHER because the auto clear when we
+ * have a exact match wont work
+ */
+ if (utype == V_ASN1_OTHER) {
+ asn1_tlc_clear(ctx);
+ }
+ /* SEQUENCE and SET must be constructed */
+ else if (!cst) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
+ return 0;
+ }
+
+ cont = *in;
+ /* If indefinite length constructed find the real end */
+ if (inf) {
+ if (!asn1_find_end(&p, plen, inf))
+ goto err;
+ len = p - cont;
+ } else {
+ len = p - cont + plen;
+ p += plen;
+ }
+ } else if (cst) {
+ if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
+ || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
+ || utype == V_ASN1_ENUMERATED) {
+ /* These types only have primitive encodings. */
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
+ return 0;
+ }
+
+ /* Free any returned 'buf' content */
+ free_cont = 1;
+ /*
+ * Should really check the internal tags are correct but some things
+ * may get this wrong. The relevant specs say that constructed string
+ * types should be OCTET STRINGs internally irrespective of the type.
+ * So instead just check for UNIVERSAL class and ignore the tag.
+ */
+ if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) {
+ goto err;
+ }
+ len = buf.length;
+ /* Append a final null to string */
+ if (!BUF_MEM_grow_clean(&buf, len + 1)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ buf.data[len] = 0;
+ cont = (const unsigned char *)buf.data;
+ } else {
+ cont = p;
+ len = plen;
+ p += plen;
+ }
+
+ /* We now have content length and type: translate into a structure */
+ /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */
+ if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
+ goto err;
+
+ *in = p;
+ ret = 1;
+ err:
+ if (free_cont && buf.data)
+ OPENSSL_free(buf.data);
+ return ret;
+}
/* Translate ASN1 content octets into a structure */
int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
- int utype, char *free_cont, const ASN1_ITEM *it)
- {
- ASN1_VALUE **opval = NULL;
- ASN1_STRING *stmp;
- ASN1_TYPE *typ = NULL;
- int ret = 0;
- const ASN1_PRIMITIVE_FUNCS *pf;
- ASN1_INTEGER **tint;
- pf = it->funcs;
-
- if (pf && pf->prim_c2i)
- return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
- /* If ANY type clear type and set pointer to internal value */
- if (it->utype == V_ASN1_ANY)
- {
- if (!*pval)
- {
- typ = ASN1_TYPE_new();
- if (typ == NULL)
- goto err;
- *pval = (ASN1_VALUE *)typ;
- }
- else
- typ = (ASN1_TYPE *)*pval;
-
- if (utype != typ->type)
- ASN1_TYPE_set(typ, utype, NULL);
- opval = pval;
- pval = &typ->value.asn1_value;
- }
- switch(utype)
- {
- case V_ASN1_OBJECT:
- if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
- goto err;
- break;
-
- case V_ASN1_NULL:
- if (len)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
- goto err;
- }
- *pval = (ASN1_VALUE *)1;
- break;
-
- case V_ASN1_BOOLEAN:
- if (len != 1)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
- goto err;
- }
- else
- {
- ASN1_BOOLEAN *tbool;
- tbool = (ASN1_BOOLEAN *)pval;
- *tbool = *cont;
- }
- break;
-
- case V_ASN1_BIT_STRING:
- if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
- goto err;
- break;
-
- case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
- case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
- tint = (ASN1_INTEGER **)pval;
- if (!c2i_ASN1_INTEGER(tint, &cont, len))
- goto err;
- /* Fixup type to match the expected form */
- (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
- break;
-
- case V_ASN1_OCTET_STRING:
- case V_ASN1_NUMERICSTRING:
- case V_ASN1_PRINTABLESTRING:
- case V_ASN1_T61STRING:
- case V_ASN1_VIDEOTEXSTRING:
- case V_ASN1_IA5STRING:
- case V_ASN1_UTCTIME:
- case V_ASN1_GENERALIZEDTIME:
- case V_ASN1_GRAPHICSTRING:
- case V_ASN1_VISIBLESTRING:
- case V_ASN1_GENERALSTRING:
- case V_ASN1_UNIVERSALSTRING:
- case V_ASN1_BMPSTRING:
- case V_ASN1_UTF8STRING:
- case V_ASN1_OTHER:
- case V_ASN1_SET:
- case V_ASN1_SEQUENCE:
- default:
- if (utype == V_ASN1_BMPSTRING && (len & 1))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
- goto err;
- }
- if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
- goto err;
- }
- /* All based on ASN1_STRING and handled the same */
- if (!*pval)
- {
- stmp = ASN1_STRING_type_new(utype);
- if (!stmp)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- *pval = (ASN1_VALUE *)stmp;
- }
- else
- {
- stmp = (ASN1_STRING *)*pval;
- stmp->type = utype;
- }
- /* If we've already allocated a buffer use it */
- if (*free_cont)
- {
- if (stmp->data)
- OPENSSL_free(stmp->data);
- stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
- stmp->length = len;
- *free_cont = 0;
- }
- else
- {
- if (!ASN1_STRING_set(stmp, cont, len))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- ASN1_STRING_free(stmp);
- *pval = NULL;
- goto err;
- }
- }
- break;
- }
- /* If ASN1_ANY and NULL type fix up value */
- if (typ && (utype == V_ASN1_NULL))
- typ->value.ptr = NULL;
-
- ret = 1;
- err:
- if (!ret)
- {
- ASN1_TYPE_free(typ);
- if (opval)
- *opval = NULL;
- }
- return ret;
- }
-
-
-/* This function finds the end of an ASN1 structure when passed its maximum
- * length, whether it is indefinite length and a pointer to the content.
- * This is more efficient than calling asn1_collect because it does not
- * recurse on each indefinite length header.
+ int utype, char *free_cont, const ASN1_ITEM *it)
+{
+ ASN1_VALUE **opval = NULL;
+ ASN1_STRING *stmp;
+ ASN1_TYPE *typ = NULL;
+ int ret = 0;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ ASN1_INTEGER **tint;
+ pf = it->funcs;
+
+ if (pf && pf->prim_c2i)
+ return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
+ /* If ANY type clear type and set pointer to internal value */
+ if (it->utype == V_ASN1_ANY) {
+ if (!*pval) {
+ typ = ASN1_TYPE_new();
+ if (typ == NULL)
+ goto err;
+ *pval = (ASN1_VALUE *)typ;
+ } else
+ typ = (ASN1_TYPE *)*pval;
+
+ if (utype != typ->type)
+ ASN1_TYPE_set(typ, utype, NULL);
+ opval = pval;
+ pval = &typ->value.asn1_value;
+ }
+ switch (utype) {
+ case V_ASN1_OBJECT:
+ if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
+ goto err;
+ break;
+
+ case V_ASN1_NULL:
+ if (len) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
+ goto err;
+ }
+ *pval = (ASN1_VALUE *)1;
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (len != 1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+ goto err;
+ } else {
+ ASN1_BOOLEAN *tbool;
+ tbool = (ASN1_BOOLEAN *)pval;
+ *tbool = *cont;
+ }
+ break;
+
+ case V_ASN1_BIT_STRING:
+ if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
+ goto err;
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_ENUMERATED:
+ tint = (ASN1_INTEGER **)pval;
+ if (!c2i_ASN1_INTEGER(tint, &cont, len))
+ goto err;
+ /* Fixup type to match the expected form */
+ (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
+ break;
+
+ case V_ASN1_OCTET_STRING:
+ case V_ASN1_NUMERICSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_VIDEOTEXSTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ case V_ASN1_GRAPHICSTRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_OTHER:
+ case V_ASN1_SET:
+ case V_ASN1_SEQUENCE:
+ default:
+ if (utype == V_ASN1_BMPSTRING && (len & 1)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+ goto err;
+ }
+ if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+ goto err;
+ }
+ /* All based on ASN1_STRING and handled the same */
+ if (!*pval) {
+ stmp = ASN1_STRING_type_new(utype);
+ if (!stmp) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ *pval = (ASN1_VALUE *)stmp;
+ } else {
+ stmp = (ASN1_STRING *)*pval;
+ stmp->type = utype;
+ }
+ /* If we've already allocated a buffer use it */
+ if (*free_cont) {
+ if (stmp->data)
+ OPENSSL_free(stmp->data);
+ stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
+ stmp->length = len;
+ *free_cont = 0;
+ } else {
+ if (!ASN1_STRING_set(stmp, cont, len)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(stmp);
+ *pval = NULL;
+ goto err;
+ }
+ }
+ break;
+ }
+ /* If ASN1_ANY and NULL type fix up value */
+ if (typ && (utype == V_ASN1_NULL))
+ typ->value.ptr = NULL;
+
+ ret = 1;
+ err:
+ if (!ret) {
+ ASN1_TYPE_free(typ);
+ if (opval)
+ *opval = NULL;
+ }
+ return ret;
+}
+
+/*
+ * This function finds the end of an ASN1 structure when passed its maximum
+ * length, whether it is indefinite length and a pointer to the content. This
+ * is more efficient than calling asn1_collect because it does not recurse on
+ * each indefinite length header.
*/
static int asn1_find_end(const unsigned char **in, long len, char inf)
- {
- int expected_eoc;
- long plen;
- const unsigned char *p = *in, *q;
- /* If not indefinite length constructed just add length */
- if (inf == 0)
- {
- *in += len;
- return 1;
- }
- expected_eoc = 1;
- /* Indefinite length constructed form. Find the end when enough EOCs
- * are found. If more indefinite length constructed headers
- * are encountered increment the expected eoc count otherwise just
- * skip to the end of the data.
- */
- while (len > 0)
- {
- if(asn1_check_eoc(&p, len))
- {
- expected_eoc--;
- if (expected_eoc == 0)
- break;
- len -= 2;
- continue;
- }
- q = p;
- /* Just read in a header: only care about the length */
- if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
- -1, 0, 0, NULL))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
- if (inf)
- expected_eoc++;
- else
- p += plen;
- len -= p - q;
- }
- if (expected_eoc)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
- return 0;
- }
- *in = p;
- return 1;
- }
-/* This function collects the asn1 data from a constructred string
- * type into a buffer. The values of 'in' and 'len' should refer
- * to the contents of the constructed type and 'inf' should be set
- * if it is indefinite length.
+{
+ int expected_eoc;
+ long plen;
+ const unsigned char *p = *in, *q;
+ /* If not indefinite length constructed just add length */
+ if (inf == 0) {
+ *in += len;
+ return 1;
+ }
+ expected_eoc = 1;
+ /*
+ * Indefinite length constructed form. Find the end when enough EOCs are
+ * found. If more indefinite length constructed headers are encountered
+ * increment the expected eoc count otherwise just skip to the end of the
+ * data.
+ */
+ while (len > 0) {
+ if (asn1_check_eoc(&p, len)) {
+ expected_eoc--;
+ if (expected_eoc == 0)
+ break;
+ len -= 2;
+ continue;
+ }
+ q = p;
+ /* Just read in a header: only care about the length */
+ if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
+ -1, 0, 0, NULL)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ if (inf)
+ expected_eoc++;
+ else
+ p += plen;
+ len -= p - q;
+ }
+ if (expected_eoc) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+ return 0;
+ }
+ *in = p;
+ return 1;
+}
+
+/*
+ * This function collects the asn1 data from a constructred string type into
+ * a buffer. The values of 'in' and 'len' should refer to the contents of the
+ * constructed type and 'inf' should be set if it is indefinite length.
*/
#ifndef ASN1_MAX_STRING_NEST
-/* This determines how many levels of recursion are permitted in ASN1
- * string types. If it is not limited stack overflows can occur. If set
- * to zero no recursion is allowed at all. Although zero should be adequate
- * examples exist that require a value of 1. So 5 should be more than enough.
+/*
+ * This determines how many levels of recursion are permitted in ASN1 string
+ * types. If it is not limited stack overflows can occur. If set to zero no
+ * recursion is allowed at all. Although zero should be adequate examples
+ * exist that require a value of 1. So 5 should be more than enough.
*/
-#define ASN1_MAX_STRING_NEST 5
+# define ASN1_MAX_STRING_NEST 5
#endif
-
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
- char inf, int tag, int aclass, int depth)
- {
- const unsigned char *p, *q;
- long plen;
- char cst, ininf;
- p = *in;
- inf &= 1;
- /* If no buffer and not indefinite length constructed just pass over
- * the encoded data */
- if (!buf && !inf)
- {
- *in += len;
- return 1;
- }
- while(len > 0)
- {
- q = p;
- /* Check for EOC */
- if (asn1_check_eoc(&p, len))
- {
- /* EOC is illegal outside indefinite length
- * constructed form */
- if (!inf)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
- return 0;
- }
- inf = 0;
- break;
- }
-
- if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
- len, tag, aclass, 0, NULL))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
- return 0;
- }
-
- /* If indefinite length constructed update max length */
- if (cst)
- {
- if (depth >= ASN1_MAX_STRING_NEST)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING);
- return 0;
- }
- if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
- depth + 1))
- return 0;
- }
- else if (plen && !collect_data(buf, &p, plen))
- return 0;
- len -= p - q;
- }
- if (inf)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
- return 0;
- }
- *in = p;
- return 1;
- }
+ char inf, int tag, int aclass, int depth)
+{
+ const unsigned char *p, *q;
+ long plen;
+ char cst, ininf;
+ p = *in;
+ inf &= 1;
+ /*
+ * If no buffer and not indefinite length constructed just pass over the
+ * encoded data
+ */
+ if (!buf && !inf) {
+ *in += len;
+ return 1;
+ }
+ while (len > 0) {
+ q = p;
+ /* Check for EOC */
+ if (asn1_check_eoc(&p, len)) {
+ /*
+ * EOC is illegal outside indefinite length constructed form
+ */
+ if (!inf) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+ return 0;
+ }
+ inf = 0;
+ break;
+ }
+
+ if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
+ len, tag, aclass, 0, NULL)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+
+ /* If indefinite length constructed update max length */
+ if (cst) {
+ if (depth >= ASN1_MAX_STRING_NEST) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING);
+ return 0;
+ }
+ if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1))
+ return 0;
+ } else if (plen && !collect_data(buf, &p, plen))
+ return 0;
+ len -= p - q;
+ }
+ if (inf) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+ return 0;
+ }
+ *in = p;
+ return 1;
+}
static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
- {
- int len;
- if (buf)
- {
- len = buf->length;
- if (!BUF_MEM_grow_clean(buf, len + plen))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- memcpy(buf->data + len, *p, plen);
- }
- *p += plen;
- return 1;
- }
+{
+ int len;
+ if (buf) {
+ len = buf->length;
+ if (!BUF_MEM_grow_clean(buf, len + plen)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(buf->data + len, *p, plen);
+ }
+ *p += plen;
+ return 1;
+}
/* Check for ASN1 EOC and swallow it if found */
static int asn1_check_eoc(const unsigned char **in, long len)
- {
- const unsigned char *p;
- if (len < 2) return 0;
- p = *in;
- if (!p[0] && !p[1])
- {
- *in += 2;
- return 1;
- }
- return 0;
- }
-
-/* Check an ASN1 tag and length: a bit like ASN1_get_object
- * but it sets the length for indefinite length constructed
- * form, we don't know the exact length but we can set an
- * upper bound to the amount of data available minus the
- * header length just read.
+{
+ const unsigned char *p;
+ if (len < 2)
+ return 0;
+ p = *in;
+ if (!p[0] && !p[1]) {
+ *in += 2;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the
+ * length for indefinite length constructed form, we don't know the exact
+ * length but we can set an upper bound to the amount of data available minus
+ * the header length just read.
*/
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
- char *inf, char *cst,
- const unsigned char **in, long len,
- int exptag, int expclass, char opt,
- ASN1_TLC *ctx)
- {
- int i;
- int ptag, pclass;
- long plen;
- const unsigned char *p, *q;
- p = *in;
- q = p;
-
- if (ctx && ctx->valid)
- {
- i = ctx->ret;
- plen = ctx->plen;
- pclass = ctx->pclass;
- ptag = ctx->ptag;
- p += ctx->hdrlen;
- }
- else
- {
- i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
- if (ctx)
- {
- ctx->ret = i;
- ctx->plen = plen;
- ctx->pclass = pclass;
- ctx->ptag = ptag;
- ctx->hdrlen = p - q;
- ctx->valid = 1;
- /* If definite length, and no error, length +
- * header can't exceed total amount of data available.
- */
- if (!(i & 0x81) && ((plen + ctx->hdrlen) > len))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- asn1_tlc_clear(ctx);
- return 0;
- }
- }
- }
-
- if (i & 0x80)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER);
- asn1_tlc_clear(ctx);
- return 0;
- }
- if (exptag >= 0)
- {
- if ((exptag != ptag) || (expclass != pclass))
- {
- /* If type is OPTIONAL, not an error:
- * indicate missing type.
- */
- if (opt) return -1;
- asn1_tlc_clear(ctx);
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG);
- return 0;
- }
- /* We have a tag and class match:
- * assume we are going to do something with it */
- asn1_tlc_clear(ctx);
- }
-
- if (i & 1)
- plen = len - (p - q);
-
- if (inf)
- *inf = i & 1;
-
- if (cst)
- *cst = i & V_ASN1_CONSTRUCTED;
-
- if (olen)
- *olen = plen;
-
- if (oclass)
- *oclass = pclass;
-
- if (otag)
- *otag = ptag;
-
- *in = p;
- return 1;
- }
+ char *inf, char *cst,
+ const unsigned char **in, long len,
+ int exptag, int expclass, char opt, ASN1_TLC *ctx)
+{
+ int i;
+ int ptag, pclass;
+ long plen;
+ const unsigned char *p, *q;
+ p = *in;
+ q = p;
+
+ if (ctx && ctx->valid) {
+ i = ctx->ret;
+ plen = ctx->plen;
+ pclass = ctx->pclass;
+ ptag = ctx->ptag;
+ p += ctx->hdrlen;
+ } else {
+ i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
+ if (ctx) {
+ ctx->ret = i;
+ ctx->plen = plen;
+ ctx->pclass = pclass;
+ ctx->ptag = ptag;
+ ctx->hdrlen = p - q;
+ ctx->valid = 1;
+ /*
+ * If definite length, and no error, length + header can't exceed
+ * total amount of data available.
+ */
+ if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+ asn1_tlc_clear(ctx);
+ return 0;
+ }
+ }
+ }
+
+ if (i & 0x80) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER);
+ asn1_tlc_clear(ctx);
+ return 0;
+ }
+ if (exptag >= 0) {
+ if ((exptag != ptag) || (expclass != pclass)) {
+ /*
+ * If type is OPTIONAL, not an error: indicate missing type.
+ */
+ if (opt)
+ return -1;
+ asn1_tlc_clear(ctx);
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG);
+ return 0;
+ }
+ /*
+ * We have a tag and class match: assume we are going to do something
+ * with it
+ */
+ asn1_tlc_clear(ctx);
+ }
+
+ if (i & 1)
+ plen = len - (p - q);
+
+ if (inf)
+ *inf = i & 1;
+
+ if (cst)
+ *cst = i & V_ASN1_CONSTRUCTED;
+
+ if (olen)
+ *olen = plen;
+
+ if (oclass)
+ *oclass = pclass;
+
+ if (otag)
+ *otag = ptag;
+
+ *in = p;
+ return 1;
+}
diff --git a/src/crypto/asn1/tasn_enc.c b/src/crypto/asn1/tasn_enc.c
index 38e14d2a..a56d08ed 100644
--- a/src/crypto/asn1/tasn_enc.c
+++ b/src/crypto/asn1/tasn_enc.c
@@ -61,635 +61,599 @@
#include <openssl/asn1t.h>
#include <openssl/mem.h>
-
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_ITEM *it,
- int tag, int aclass);
+ const ASN1_ITEM *it, int tag, int aclass);
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
- int skcontlen, const ASN1_ITEM *item,
- int do_sort, int iclass);
+ int skcontlen, const ASN1_ITEM *item,
+ int do_sort, int iclass);
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_TEMPLATE *tt,
- int tag, int aclass);
+ const ASN1_TEMPLATE *tt, int tag, int aclass);
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
- const ASN1_ITEM *it, int flags);
+ const ASN1_ITEM *it, int flags);
-/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
- * to use indefinite length constructed encoding, where appropriate
+/*
+ * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
+ * indefinite length constructed encoding, where appropriate
*/
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
- const ASN1_ITEM *it)
- {
- return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
- }
+ const ASN1_ITEM *it)
+{
+ return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
+}
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
- {
- return asn1_item_flags_i2d(val, out, it, 0);
- }
+{
+ return asn1_item_flags_i2d(val, out, it, 0);
+}
-/* Encode an ASN1 item, this is use by the
- * standard 'i2d' function. 'out' points to
- * a buffer to output the data to.
- *
- * The new i2d has one additional feature. If the output
- * buffer is NULL (i.e. *out == NULL) then a buffer is
+/*
+ * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
+ * points to a buffer to output the data to. The new i2d has one additional
+ * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
- const ASN1_ITEM *it, int flags)
- {
- if (out && !*out)
- {
- unsigned char *p, *buf;
- int len;
- len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
- if (len <= 0)
- return len;
- buf = OPENSSL_malloc(len);
- if (!buf)
- return -1;
- p = buf;
- ASN1_item_ex_i2d(&val, &p, it, -1, flags);
- *out = buf;
- return len;
- }
-
- return ASN1_item_ex_i2d(&val, out, it, -1, flags);
- }
-
-/* Encode an item, taking care of IMPLICIT tagging (if any).
- * This function performs the normal item handling: it can be
- * used in external types.
+ const ASN1_ITEM *it, int flags)
+{
+ if (out && !*out) {
+ unsigned char *p, *buf;
+ int len;
+ len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
+ if (len <= 0)
+ return len;
+ buf = OPENSSL_malloc(len);
+ if (!buf)
+ return -1;
+ p = buf;
+ ASN1_item_ex_i2d(&val, &p, it, -1, flags);
+ *out = buf;
+ return len;
+ }
+
+ return ASN1_item_ex_i2d(&val, out, it, -1, flags);
+}
+
+/*
+ * Encode an item, taking care of IMPLICIT tagging (if any). This function
+ * performs the normal item handling: it can be used in external types.
*/
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_ITEM *it, int tag, int aclass)
- {
- const ASN1_TEMPLATE *tt = NULL;
- unsigned char *p = NULL;
- int i, seqcontlen, seqlen, ndef = 1;
- const ASN1_COMPAT_FUNCS *cf;
- const ASN1_EXTERN_FUNCS *ef;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb = 0;
-
- if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
- return 0;
-
- if (aux && aux->asn1_cb)
- asn1_cb = aux->asn1_cb;
-
- switch(it->itype)
- {
-
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates)
- return asn1_template_ex_i2d(pval, out, it->templates,
- tag, aclass);
- return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
- break;
-
- case ASN1_ITYPE_MSTRING:
- return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
-
- case ASN1_ITYPE_CHOICE:
- if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
- return 0;
- i = asn1_get_choice_selector(pval, it);
- if ((i >= 0) && (i < it->tcount))
- {
- ASN1_VALUE **pchval;
- const ASN1_TEMPLATE *chtt;
- chtt = it->templates + i;
- pchval = asn1_get_field_ptr(pval, chtt);
- return asn1_template_ex_i2d(pchval, out, chtt,
- -1, aclass);
- }
- /* Fixme: error condition if selector out of range */
- if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
- return 0;
- break;
-
- case ASN1_ITYPE_EXTERN:
- /* If new style i2d it does all the work */
- ef = it->funcs;
- return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
-
- case ASN1_ITYPE_COMPAT:
- /* old style hackery... */
- cf = it->funcs;
- if (out)
- p = *out;
- i = cf->asn1_i2d(*pval, out);
- /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
- * but so did the old code. Tags > 30 are very rare anyway.
- */
- if (out && (tag != -1))
- *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
- return i;
-
- case ASN1_ITYPE_NDEF_SEQUENCE:
- /* Use indefinite length constructed if requested */
- if (aclass & ASN1_TFLG_NDEF) ndef = 2;
- /* fall through */
-
- case ASN1_ITYPE_SEQUENCE:
- i = asn1_enc_restore(&seqcontlen, out, pval, it);
- /* An error occurred */
- if (i < 0)
- return 0;
- /* We have a valid cached encoding... */
- if (i > 0)
- return seqcontlen;
- /* Otherwise carry on */
- seqcontlen = 0;
- /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
- if (tag == -1)
- {
- tag = V_ASN1_SEQUENCE;
- /* Retain any other flags in aclass */
- aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
- | V_ASN1_UNIVERSAL;
- }
- if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
- return 0;
- /* First work out sequence content length */
- for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
- {
- const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
- if (!seqtt)
- return 0;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- /* FIXME: check for errors in enhanced version */
- seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
- -1, aclass);
- }
-
- seqlen = ASN1_object_size(ndef, seqcontlen, tag);
- if (!out)
- return seqlen;
- /* Output SEQUENCE header */
- ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
- for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
- {
- const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
- if (!seqtt)
- return 0;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- /* FIXME: check for errors in enhanced version */
- asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
- }
- if (ndef == 2)
- ASN1_put_eoc(out);
- if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
- return 0;
- return seqlen;
-
- default:
- return 0;
-
- }
- return 0;
- }
+ const ASN1_ITEM *it, int tag, int aclass)
+{
+ const ASN1_TEMPLATE *tt = NULL;
+ unsigned char *p = NULL;
+ int i, seqcontlen, seqlen, ndef = 1;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb = 0;
+
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+ return 0;
+
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+
+ switch (it->itype) {
+
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates)
+ return asn1_template_ex_i2d(pval, out, it->templates,
+ tag, aclass);
+ return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
+
+ case ASN1_ITYPE_CHOICE:
+ if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+ return 0;
+ i = asn1_get_choice_selector(pval, it);
+ if ((i >= 0) && (i < it->tcount)) {
+ ASN1_VALUE **pchval;
+ const ASN1_TEMPLATE *chtt;
+ chtt = it->templates + i;
+ pchval = asn1_get_field_ptr(pval, chtt);
+ return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
+ }
+ /* Fixme: error condition if selector out of range */
+ if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+ return 0;
+ break;
+
+ case ASN1_ITYPE_EXTERN:
+ /* If new style i2d it does all the work */
+ ef = it->funcs;
+ return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
+
+ case ASN1_ITYPE_COMPAT:
+ /* old style hackery... */
+ cf = it->funcs;
+ if (out)
+ p = *out;
+ i = cf->asn1_i2d(*pval, out);
+ /*
+ * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
+ * did the old code. Tags > 30 are very rare anyway.
+ */
+ if (out && (tag != -1))
+ *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
+ return i;
+
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ /* Use indefinite length constructed if requested */
+ if (aclass & ASN1_TFLG_NDEF)
+ ndef = 2;
+ /* fall through */
+
+ case ASN1_ITYPE_SEQUENCE:
+ i = asn1_enc_restore(&seqcontlen, out, pval, it);
+ /* An error occurred */
+ if (i < 0)
+ return 0;
+ /* We have a valid cached encoding... */
+ if (i > 0)
+ return seqcontlen;
+ /* Otherwise carry on */
+ seqcontlen = 0;
+ /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+ if (tag == -1) {
+ tag = V_ASN1_SEQUENCE;
+ /* Retain any other flags in aclass */
+ aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
+ | V_ASN1_UNIVERSAL;
+ }
+ if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+ return 0;
+ /* First work out sequence content length */
+ for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ return 0;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ /* FIXME: check for errors in enhanced version */
+ seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
+ -1, aclass);
+ }
+
+ seqlen = ASN1_object_size(ndef, seqcontlen, tag);
+ if (!out)
+ return seqlen;
+ /* Output SEQUENCE header */
+ ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
+ for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ return 0;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ /* FIXME: check for errors in enhanced version */
+ asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
+ }
+ if (ndef == 2)
+ ASN1_put_eoc(out);
+ if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+ return 0;
+ return seqlen;
+
+ default:
+ return 0;
+
+ }
+ return 0;
+}
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_TEMPLATE *tt)
- {
- return asn1_template_ex_i2d(pval, out, tt, -1, 0);
- }
+ const ASN1_TEMPLATE *tt)
+{
+ return asn1_template_ex_i2d(pval, out, tt, -1, 0);
+}
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_TEMPLATE *tt, int tag, int iclass)
- {
- int i, ret, flags, ttag, tclass, ndef;
- size_t j;
- flags = tt->flags;
- /* Work out tag and class to use: tagging may come
- * either from the template or the arguments, not both
- * because this would create ambiguity. Additionally
- * the iclass argument may contain some additional flags
- * which should be noted and passed down to other levels.
- */
- if (flags & ASN1_TFLG_TAG_MASK)
- {
- /* Error if argument and template tagging */
- if (tag != -1)
- /* FIXME: error code here */
- return -1;
- /* Get tagging from template */
- ttag = tt->tag;
- tclass = flags & ASN1_TFLG_TAG_CLASS;
- }
- else if (tag != -1)
- {
- /* No template tagging, get from arguments */
- ttag = tag;
- tclass = iclass & ASN1_TFLG_TAG_CLASS;
- }
- else
- {
- ttag = -1;
- tclass = 0;
- }
- /*
- * Remove any class mask from iflag.
- */
- iclass &= ~ASN1_TFLG_TAG_CLASS;
-
- /* At this point 'ttag' contains the outer tag to use,
- * 'tclass' is the class and iclass is any flags passed
- * to this function.
- */
-
- /* if template and arguments require ndef, use it */
- if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
- ndef = 2;
- else ndef = 1;
-
- if (flags & ASN1_TFLG_SK_MASK)
- {
- /* SET OF, SEQUENCE OF */
- STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
- int isset, sktag, skaclass;
- int skcontlen, sklen;
- ASN1_VALUE *skitem;
-
- if (!*pval)
- return 0;
-
- if (flags & ASN1_TFLG_SET_OF)
- {
- isset = 1;
- /* 2 means we reorder */
- if (flags & ASN1_TFLG_SEQUENCE_OF)
- isset = 2;
- }
- else isset = 0;
-
- /* Work out inner tag value: if EXPLICIT
- * or no tagging use underlying type.
- */
- if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
- {
- sktag = ttag;
- skaclass = tclass;
- }
- else
- {
- skaclass = V_ASN1_UNIVERSAL;
- if (isset)
- sktag = V_ASN1_SET;
- else sktag = V_ASN1_SEQUENCE;
- }
-
- /* Determine total length of items */
- skcontlen = 0;
- for (j = 0; j < sk_ASN1_VALUE_num(sk); j++)
- {
- skitem = sk_ASN1_VALUE_value(sk, j);
- skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
- ASN1_ITEM_ptr(tt->item),
- -1, iclass);
- }
- sklen = ASN1_object_size(ndef, skcontlen, sktag);
- /* If EXPLICIT need length of surrounding tag */
- if (flags & ASN1_TFLG_EXPTAG)
- ret = ASN1_object_size(ndef, sklen, ttag);
- else ret = sklen;
-
- if (!out)
- return ret;
-
- /* Now encode this lot... */
- /* EXPLICIT tag */
- if (flags & ASN1_TFLG_EXPTAG)
- ASN1_put_object(out, ndef, sklen, ttag, tclass);
- /* SET or SEQUENCE and IMPLICIT tag */
- ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
- /* And the stuff itself */
- asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
- isset, iclass);
- if (ndef == 2)
- {
- ASN1_put_eoc(out);
- if (flags & ASN1_TFLG_EXPTAG)
- ASN1_put_eoc(out);
- }
-
- return ret;
- }
-
- if (flags & ASN1_TFLG_EXPTAG)
- {
- /* EXPLICIT tagging */
- /* Find length of tagged item */
- i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
- -1, iclass);
- if (!i)
- return 0;
- /* Find length of EXPLICIT tag */
- ret = ASN1_object_size(ndef, i, ttag);
- if (out)
- {
- /* Output tag and item */
- ASN1_put_object(out, ndef, i, ttag, tclass);
- ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
- -1, iclass);
- if (ndef == 2)
- ASN1_put_eoc(out);
- }
- return ret;
- }
-
- /* Either normal or IMPLICIT tagging: combine class and flags */
- return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
- ttag, tclass | iclass);
+ const ASN1_TEMPLATE *tt, int tag, int iclass)
+{
+ int i, ret, flags, ttag, tclass, ndef;
+ size_t j;
+ flags = tt->flags;
+ /*
+ * Work out tag and class to use: tagging may come either from the
+ * template or the arguments, not both because this would create
+ * ambiguity. Additionally the iclass argument may contain some
+ * additional flags which should be noted and passed down to other
+ * levels.
+ */
+ if (flags & ASN1_TFLG_TAG_MASK) {
+ /* Error if argument and template tagging */
+ if (tag != -1)
+ /* FIXME: error code here */
+ return -1;
+ /* Get tagging from template */
+ ttag = tt->tag;
+ tclass = flags & ASN1_TFLG_TAG_CLASS;
+ } else if (tag != -1) {
+ /* No template tagging, get from arguments */
+ ttag = tag;
+ tclass = iclass & ASN1_TFLG_TAG_CLASS;
+ } else {
+ ttag = -1;
+ tclass = 0;
+ }
+ /*
+ * Remove any class mask from iflag.
+ */
+ iclass &= ~ASN1_TFLG_TAG_CLASS;
+
+ /*
+ * At this point 'ttag' contains the outer tag to use, 'tclass' is the
+ * class and iclass is any flags passed to this function.
+ */
+
+ /* if template and arguments require ndef, use it */
+ if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
+ ndef = 2;
+ else
+ ndef = 1;
+
+ if (flags & ASN1_TFLG_SK_MASK) {
+ /* SET OF, SEQUENCE OF */
+ STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+ int isset, sktag, skaclass;
+ int skcontlen, sklen;
+ ASN1_VALUE *skitem;
+
+ if (!*pval)
+ return 0;
+
+ if (flags & ASN1_TFLG_SET_OF) {
+ isset = 1;
+ /* 2 means we reorder */
+ if (flags & ASN1_TFLG_SEQUENCE_OF)
+ isset = 2;
+ } else
+ isset = 0;
+
+ /*
+ * Work out inner tag value: if EXPLICIT or no tagging use underlying
+ * type.
+ */
+ if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
+ sktag = ttag;
+ skaclass = tclass;
+ } else {
+ skaclass = V_ASN1_UNIVERSAL;
+ if (isset)
+ sktag = V_ASN1_SET;
+ else
+ sktag = V_ASN1_SEQUENCE;
+ }
+
+ /* Determine total length of items */
+ skcontlen = 0;
+ for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
+ skitem = sk_ASN1_VALUE_value(sk, j);
+ skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
+ ASN1_ITEM_ptr(tt->item),
+ -1, iclass);
+ }
+ sklen = ASN1_object_size(ndef, skcontlen, sktag);
+ /* If EXPLICIT need length of surrounding tag */
+ if (flags & ASN1_TFLG_EXPTAG)
+ ret = ASN1_object_size(ndef, sklen, ttag);
+ else
+ ret = sklen;
+
+ if (!out)
+ return ret;
+
+ /* Now encode this lot... */
+ /* EXPLICIT tag */
+ if (flags & ASN1_TFLG_EXPTAG)
+ ASN1_put_object(out, ndef, sklen, ttag, tclass);
+ /* SET or SEQUENCE and IMPLICIT tag */
+ ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
+ /* And the stuff itself */
+ asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
+ isset, iclass);
+ if (ndef == 2) {
+ ASN1_put_eoc(out);
+ if (flags & ASN1_TFLG_EXPTAG)
+ ASN1_put_eoc(out);
+ }
+
+ return ret;
+ }
+
+ if (flags & ASN1_TFLG_EXPTAG) {
+ /* EXPLICIT tagging */
+ /* Find length of tagged item */
+ i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
+ if (!i)
+ return 0;
+ /* Find length of EXPLICIT tag */
+ ret = ASN1_object_size(ndef, i, ttag);
+ if (out) {
+ /* Output tag and item */
+ ASN1_put_object(out, ndef, i, ttag, tclass);
+ ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
+ if (ndef == 2)
+ ASN1_put_eoc(out);
+ }
+ return ret;
+ }
+
+ /* Either normal or IMPLICIT tagging: combine class and flags */
+ return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
+ ttag, tclass | iclass);
}
/* Temporary structure used to hold DER encoding of items for SET OF */
-typedef struct {
- unsigned char *data;
- int length;
- ASN1_VALUE *field;
+typedef struct {
+ unsigned char *data;
+ int length;
+ ASN1_VALUE *field;
} DER_ENC;
static int der_cmp(const void *a, const void *b)
- {
- const DER_ENC *d1 = a, *d2 = b;
- int cmplen, i;
- cmplen = (d1->length < d2->length) ? d1->length : d2->length;
- i = memcmp(d1->data, d2->data, cmplen);
- if (i)
- return i;
- return d1->length - d2->length;
- }
+{
+ const DER_ENC *d1 = a, *d2 = b;
+ int cmplen, i;
+ cmplen = (d1->length < d2->length) ? d1->length : d2->length;
+ i = memcmp(d1->data, d2->data, cmplen);
+ if (i)
+ return i;
+ return d1->length - d2->length;
+}
/* Output the content octets of SET OF or SEQUENCE OF */
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
- int skcontlen, const ASN1_ITEM *item,
- int do_sort, int iclass)
- {
- size_t i;
- ASN1_VALUE *skitem;
- unsigned char *tmpdat = NULL, *p = NULL;
- DER_ENC *derlst = NULL, *tder;
- if (do_sort)
- {
- /* Don't need to sort less than 2 items */
- if (sk_ASN1_VALUE_num(sk) < 2)
- do_sort = 0;
- else
- {
- derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
- * sizeof(*derlst));
- if (!derlst)
- return 0;
- tmpdat = OPENSSL_malloc(skcontlen);
- if (!tmpdat)
- {
- OPENSSL_free(derlst);
- return 0;
- }
- }
- }
- /* If not sorting just output each item */
- if (!do_sort)
- {
- for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
- {
- skitem = sk_ASN1_VALUE_value(sk, i);
- ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
- }
- return 1;
- }
- p = tmpdat;
-
- /* Doing sort: build up a list of each member's DER encoding */
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
- {
- skitem = sk_ASN1_VALUE_value(sk, i);
- tder->data = p;
- tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
- tder->field = skitem;
- }
-
- /* Now sort them */
- qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
- /* Output sorted DER encoding */
- p = *out;
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
- {
- memcpy(p, tder->data, tder->length);
- p += tder->length;
- }
- *out = p;
- /* If do_sort is 2 then reorder the STACK */
- if (do_sort == 2)
- {
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
- i++, tder++)
- (void)sk_ASN1_VALUE_set(sk, i, tder->field);
- }
- OPENSSL_free(derlst);
- OPENSSL_free(tmpdat);
- return 1;
- }
+ int skcontlen, const ASN1_ITEM *item,
+ int do_sort, int iclass)
+{
+ size_t i;
+ ASN1_VALUE *skitem;
+ unsigned char *tmpdat = NULL, *p = NULL;
+ DER_ENC *derlst = NULL, *tder;
+ if (do_sort) {
+ /* Don't need to sort less than 2 items */
+ if (sk_ASN1_VALUE_num(sk) < 2)
+ do_sort = 0;
+ else {
+ derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+ * sizeof(*derlst));
+ if (!derlst)
+ return 0;
+ tmpdat = OPENSSL_malloc(skcontlen);
+ if (!tmpdat) {
+ OPENSSL_free(derlst);
+ return 0;
+ }
+ }
+ }
+ /* If not sorting just output each item */
+ if (!do_sort) {
+ for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+ skitem = sk_ASN1_VALUE_value(sk, i);
+ ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
+ }
+ return 1;
+ }
+ p = tmpdat;
+
+ /* Doing sort: build up a list of each member's DER encoding */
+ for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+ skitem = sk_ASN1_VALUE_value(sk, i);
+ tder->data = p;
+ tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
+ tder->field = skitem;
+ }
+
+ /* Now sort them */
+ qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
+ /* Output sorted DER encoding */
+ p = *out;
+ for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+ memcpy(p, tder->data, tder->length);
+ p += tder->length;
+ }
+ *out = p;
+ /* If do_sort is 2 then reorder the STACK */
+ if (do_sort == 2) {
+ for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
+ (void)sk_ASN1_VALUE_set(sk, i, tder->field);
+ }
+ OPENSSL_free(derlst);
+ OPENSSL_free(tmpdat);
+ return 1;
+}
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_ITEM *it, int tag, int aclass)
- {
- int len;
- int utype;
- int usetag;
- int ndef = 0;
-
- utype = it->utype;
-
- /* Get length of content octets and maybe find
- * out the underlying type.
- */
-
- len = asn1_ex_i2c(pval, NULL, &utype, it);
-
- /* If SEQUENCE, SET or OTHER then header is
- * included in pseudo content octets so don't
- * include tag+length. We need to check here
- * because the call to asn1_ex_i2c() could change
- * utype.
- */
- if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
- (utype == V_ASN1_OTHER))
- usetag = 0;
- else usetag = 1;
-
- /* -1 means omit type */
-
- if (len == -1)
- return 0;
-
- /* -2 return is special meaning use ndef */
- if (len == -2)
- {
- ndef = 2;
- len = 0;
- }
-
- /* If not implicitly tagged get tag from underlying type */
- if (tag == -1) tag = utype;
-
- /* Output tag+length followed by content octets */
- if (out)
- {
- if (usetag)
- ASN1_put_object(out, ndef, len, tag, aclass);
- asn1_ex_i2c(pval, *out, &utype, it);
- if (ndef)
- ASN1_put_eoc(out);
- else
- *out += len;
- }
-
- if (usetag)
- return ASN1_object_size(ndef, len, tag);
- return len;
- }
+ const ASN1_ITEM *it, int tag, int aclass)
+{
+ int len;
+ int utype;
+ int usetag;
+ int ndef = 0;
+
+ utype = it->utype;
+
+ /*
+ * Get length of content octets and maybe find out the underlying type.
+ */
+
+ len = asn1_ex_i2c(pval, NULL, &utype, it);
+
+ /*
+ * If SEQUENCE, SET or OTHER then header is included in pseudo content
+ * octets so don't include tag+length. We need to check here because the
+ * call to asn1_ex_i2c() could change utype.
+ */
+ if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
+ (utype == V_ASN1_OTHER))
+ usetag = 0;
+ else
+ usetag = 1;
+
+ /* -1 means omit type */
+
+ if (len == -1)
+ return 0;
+
+ /* -2 return is special meaning use ndef */
+ if (len == -2) {
+ ndef = 2;
+ len = 0;
+ }
+
+ /* If not implicitly tagged get tag from underlying type */
+ if (tag == -1)
+ tag = utype;
+
+ /* Output tag+length followed by content octets */
+ if (out) {
+ if (usetag)
+ ASN1_put_object(out, ndef, len, tag, aclass);
+ asn1_ex_i2c(pval, *out, &utype, it);
+ if (ndef)
+ ASN1_put_eoc(out);
+ else
+ *out += len;
+ }
+
+ if (usetag)
+ return ASN1_object_size(ndef, len, tag);
+ return len;
+}
/* Produce content octets from a structure */
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
- const ASN1_ITEM *it)
- {
- ASN1_BOOLEAN *tbool = NULL;
- ASN1_STRING *strtmp;
- ASN1_OBJECT *otmp;
- int utype;
- const unsigned char *cont;
- unsigned char c;
- int len;
- const ASN1_PRIMITIVE_FUNCS *pf;
- pf = it->funcs;
- if (pf && pf->prim_i2c)
- return pf->prim_i2c(pval, cout, putype, it);
-
- /* Should type be omitted? */
- if ((it->itype != ASN1_ITYPE_PRIMITIVE)
- || (it->utype != V_ASN1_BOOLEAN))
- {
- if (!*pval) return -1;
- }
-
- if (it->itype == ASN1_ITYPE_MSTRING)
- {
- /* If MSTRING type set the underlying type */
- strtmp = (ASN1_STRING *)*pval;
- utype = strtmp->type;
- *putype = utype;
- }
- else if (it->utype == V_ASN1_ANY)
- {
- /* If ANY set type and pointer to value */
- ASN1_TYPE *typ;
- typ = (ASN1_TYPE *)*pval;
- utype = typ->type;
- *putype = utype;
- pval = &typ->value.asn1_value;
- }
- else utype = *putype;
-
- switch(utype)
- {
- case V_ASN1_OBJECT:
- otmp = (ASN1_OBJECT *)*pval;
- cont = otmp->data;
- len = otmp->length;
- break;
-
- case V_ASN1_NULL:
- cont = NULL;
- len = 0;
- break;
-
- case V_ASN1_BOOLEAN:
- tbool = (ASN1_BOOLEAN *)pval;
- if (*tbool == -1)
- return -1;
- if (it->utype != V_ASN1_ANY)
- {
- /* Default handling if value == size field then omit */
- if (*tbool && (it->size > 0))
- return -1;
- if (!*tbool && !it->size)
- return -1;
- }
- c = (unsigned char)*tbool;
- cont = &c;
- len = 1;
- break;
-
- case V_ASN1_BIT_STRING:
- return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
- cout ? &cout : NULL);
- break;
-
- case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
- case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
- /* These are all have the same content format
- * as ASN1_INTEGER
- */
- return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
- cout ? &cout : NULL);
- break;
-
- case V_ASN1_OCTET_STRING:
- case V_ASN1_NUMERICSTRING:
- case V_ASN1_PRINTABLESTRING:
- case V_ASN1_T61STRING:
- case V_ASN1_VIDEOTEXSTRING:
- case V_ASN1_IA5STRING:
- case V_ASN1_UTCTIME:
- case V_ASN1_GENERALIZEDTIME:
- case V_ASN1_GRAPHICSTRING:
- case V_ASN1_VISIBLESTRING:
- case V_ASN1_GENERALSTRING:
- case V_ASN1_UNIVERSALSTRING:
- case V_ASN1_BMPSTRING:
- case V_ASN1_UTF8STRING:
- case V_ASN1_SEQUENCE:
- case V_ASN1_SET:
- default:
- /* All based on ASN1_STRING and handled the same */
- strtmp = (ASN1_STRING *)*pval;
- /* Special handling for NDEF */
- if ((it->size == ASN1_TFLG_NDEF)
- && (strtmp->flags & ASN1_STRING_FLAG_NDEF))
- {
- if (cout)
- {
- strtmp->data = cout;
- strtmp->length = 0;
- }
- /* Special return code */
- return -2;
- }
- cont = strtmp->data;
- len = strtmp->length;
-
- break;
-
- }
- if (cout && len)
- memcpy(cout, cont, len);
- return len;
- }
+ const ASN1_ITEM *it)
+{
+ ASN1_BOOLEAN *tbool = NULL;
+ ASN1_STRING *strtmp;
+ ASN1_OBJECT *otmp;
+ int utype;
+ const unsigned char *cont;
+ unsigned char c;
+ int len;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (pf && pf->prim_i2c)
+ return pf->prim_i2c(pval, cout, putype, it);
+
+ /* Should type be omitted? */
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE)
+ || (it->utype != V_ASN1_BOOLEAN)) {
+ if (!*pval)
+ return -1;
+ }
+
+ if (it->itype == ASN1_ITYPE_MSTRING) {
+ /* If MSTRING type set the underlying type */
+ strtmp = (ASN1_STRING *)*pval;
+ utype = strtmp->type;
+ *putype = utype;
+ } else if (it->utype == V_ASN1_ANY) {
+ /* If ANY set type and pointer to value */
+ ASN1_TYPE *typ;
+ typ = (ASN1_TYPE *)*pval;
+ utype = typ->type;
+ *putype = utype;
+ pval = &typ->value.asn1_value;
+ } else
+ utype = *putype;
+
+ switch (utype) {
+ case V_ASN1_OBJECT:
+ otmp = (ASN1_OBJECT *)*pval;
+ cont = otmp->data;
+ len = otmp->length;
+ break;
+
+ case V_ASN1_NULL:
+ cont = NULL;
+ len = 0;
+ break;
+
+ case V_ASN1_BOOLEAN:
+ tbool = (ASN1_BOOLEAN *)pval;
+ if (*tbool == -1)
+ return -1;
+ if (it->utype != V_ASN1_ANY) {
+ /*
+ * Default handling if value == size field then omit
+ */
+ if (*tbool && (it->size > 0))
+ return -1;
+ if (!*tbool && !it->size)
+ return -1;
+ }
+ c = (unsigned char)*tbool;
+ cont = &c;
+ len = 1;
+ break;
+
+ case V_ASN1_BIT_STRING:
+ return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+ cout ? &cout : NULL);
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_ENUMERATED:
+ /*
+ * These are all have the same content format as ASN1_INTEGER
+ */
+ return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
+ break;
+
+ case V_ASN1_OCTET_STRING:
+ case V_ASN1_NUMERICSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_VIDEOTEXSTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ case V_ASN1_GRAPHICSTRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_SEQUENCE:
+ case V_ASN1_SET:
+ default:
+ /* All based on ASN1_STRING and handled the same */
+ strtmp = (ASN1_STRING *)*pval;
+ /* Special handling for NDEF */
+ if ((it->size == ASN1_TFLG_NDEF)
+ && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
+ if (cout) {
+ strtmp->data = cout;
+ strtmp->length = 0;
+ }
+ /* Special return code */
+ return -2;
+ }
+ cont = strtmp->data;
+ len = strtmp->length;
+
+ break;
+
+ }
+ if (cout && len)
+ memcpy(cout, cont, len);
+ return len;
+}
diff --git a/src/crypto/asn1/tasn_fre.c b/src/crypto/asn1/tasn_fre.c
index d1317ae4..609cb9f9 100644
--- a/src/crypto/asn1/tasn_fre.c
+++ b/src/crypto/asn1/tasn_fre.c
@@ -59,206 +59,188 @@
#include <openssl/asn1t.h>
#include <openssl/mem.h>
-
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int combine);
/* Free up an ASN1 structure */
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
- {
- asn1_item_combine_free(&val, it, 0);
- }
+{
+ asn1_item_combine_free(&val, it, 0);
+}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- asn1_item_combine_free(pval, it, 0);
- }
-
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
- {
- const ASN1_TEMPLATE *tt = NULL, *seqtt;
- const ASN1_EXTERN_FUNCS *ef;
- const ASN1_COMPAT_FUNCS *cf;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
- int i;
- if (!pval)
- return;
- if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
- return;
- if (aux && aux->asn1_cb)
- asn1_cb = aux->asn1_cb;
- else
- asn1_cb = 0;
-
- switch(it->itype)
- {
-
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates)
- ASN1_template_free(pval, it->templates);
- else
- ASN1_primitive_free(pval, it);
- break;
-
- case ASN1_ITYPE_MSTRING:
- ASN1_primitive_free(pval, it);
- break;
-
- case ASN1_ITYPE_CHOICE:
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
- if (i == 2)
- return;
- }
- i = asn1_get_choice_selector(pval, it);
- if ((i >= 0) && (i < it->tcount))
- {
- ASN1_VALUE **pchval;
- tt = it->templates + i;
- pchval = asn1_get_field_ptr(pval, tt);
- ASN1_template_free(pchval, tt);
- }
- if (asn1_cb)
- asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
- if (!combine)
- {
- OPENSSL_free(*pval);
- *pval = NULL;
- }
- break;
-
- case ASN1_ITYPE_COMPAT:
- cf = it->funcs;
- if (cf && cf->asn1_free)
- cf->asn1_free(*pval);
- break;
-
- case ASN1_ITYPE_EXTERN:
- ef = it->funcs;
- if (ef && ef->asn1_ex_free)
- ef->asn1_ex_free(pval, it);
- break;
-
- case ASN1_ITYPE_NDEF_SEQUENCE:
- case ASN1_ITYPE_SEQUENCE:
- if (!asn1_refcount_dec_and_test_zero(pval, it))
- return;
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
- if (i == 2)
- return;
- }
- asn1_enc_free(pval, it);
- /* If we free up as normal we will invalidate any
- * ANY DEFINED BY field and we wont be able to
- * determine the type of the field it defines. So
- * free up in reverse order.
- */
- tt = it->templates + it->tcount - 1;
- for (i = 0; i < it->tcount; tt--, i++)
- {
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 0);
- if (!seqtt)
- continue;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- ASN1_template_free(pseqval, seqtt);
- }
- if (asn1_cb)
- asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
- if (!combine)
- {
- OPENSSL_free(*pval);
- *pval = NULL;
- }
- break;
- }
- }
+{
+ asn1_item_combine_free(pval, it, 0);
+}
+
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int combine)
+{
+ const ASN1_TEMPLATE *tt = NULL, *seqtt;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ int i;
+ if (!pval)
+ return;
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+ return;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else
+ asn1_cb = 0;
+
+ switch (it->itype) {
+
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates)
+ ASN1_template_free(pval, it->templates);
+ else
+ ASN1_primitive_free(pval, it);
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ ASN1_primitive_free(pval, it);
+ break;
+
+ case ASN1_ITYPE_CHOICE:
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+ if (i == 2)
+ return;
+ }
+ i = asn1_get_choice_selector(pval, it);
+ if ((i >= 0) && (i < it->tcount)) {
+ ASN1_VALUE **pchval;
+ tt = it->templates + i;
+ pchval = asn1_get_field_ptr(pval, tt);
+ ASN1_template_free(pchval, tt);
+ }
+ if (asn1_cb)
+ asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+ if (!combine) {
+ OPENSSL_free(*pval);
+ *pval = NULL;
+ }
+ break;
+
+ case ASN1_ITYPE_COMPAT:
+ cf = it->funcs;
+ if (cf && cf->asn1_free)
+ cf->asn1_free(*pval);
+ break;
+
+ case ASN1_ITYPE_EXTERN:
+ ef = it->funcs;
+ if (ef && ef->asn1_ex_free)
+ ef->asn1_ex_free(pval, it);
+ break;
+
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ case ASN1_ITYPE_SEQUENCE:
+ if (!asn1_refcount_dec_and_test_zero(pval, it))
+ return;
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+ if (i == 2)
+ return;
+ }
+ asn1_enc_free(pval, it);
+ /*
+ * If we free up as normal we will invalidate any ANY DEFINED BY
+ * field and we wont be able to determine the type of the field it
+ * defines. So free up in reverse order.
+ */
+ tt = it->templates + it->tcount - 1;
+ for (i = 0; i < it->tcount; tt--, i++) {
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 0);
+ if (!seqtt)
+ continue;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ ASN1_template_free(pseqval, seqtt);
+ }
+ if (asn1_cb)
+ asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+ if (!combine) {
+ OPENSSL_free(*pval);
+ *pval = NULL;
+ }
+ break;
+ }
+}
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
- {
- size_t i;
- if (tt->flags & ASN1_TFLG_SK_MASK)
- {
- STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
- for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
- {
- ASN1_VALUE *vtmp;
- vtmp = sk_ASN1_VALUE_value(sk, i);
- asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
- 0);
- }
- sk_ASN1_VALUE_free(sk);
- *pval = NULL;
- }
- else
- asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
- tt->flags & ASN1_TFLG_COMBINE);
- }
+{
+ size_t i;
+ if (tt->flags & ASN1_TFLG_SK_MASK) {
+ STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+ for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+ ASN1_VALUE *vtmp;
+ vtmp = sk_ASN1_VALUE_value(sk, i);
+ asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
+ }
+ sk_ASN1_VALUE_free(sk);
+ *pval = NULL;
+ } else
+ asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
+ tt->flags & ASN1_TFLG_COMBINE);
+}
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- int utype;
- if (it)
- {
- const ASN1_PRIMITIVE_FUNCS *pf;
- pf = it->funcs;
- if (pf && pf->prim_free)
- {
- pf->prim_free(pval, it);
- return;
- }
- }
- /* Special case: if 'it' is NULL free contents of ASN1_TYPE */
- if (!it)
- {
- ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
- utype = typ->type;
- pval = &typ->value.asn1_value;
- if (!*pval)
- return;
- }
- else if (it->itype == ASN1_ITYPE_MSTRING)
- {
- utype = -1;
- if (!*pval)
- return;
- }
- else
- {
- utype = it->utype;
- if ((utype != V_ASN1_BOOLEAN) && !*pval)
- return;
- }
-
- switch(utype)
- {
- case V_ASN1_OBJECT:
- ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
- break;
-
- case V_ASN1_BOOLEAN:
- if (it)
- *(ASN1_BOOLEAN *)pval = it->size;
- else
- *(ASN1_BOOLEAN *)pval = -1;
- return;
-
- case V_ASN1_NULL:
- break;
-
- case V_ASN1_ANY:
- ASN1_primitive_free(pval, NULL);
- OPENSSL_free(*pval);
- break;
-
- default:
- ASN1_STRING_free((ASN1_STRING *)*pval);
- *pval = NULL;
- break;
- }
- *pval = NULL;
- }
+{
+ int utype;
+ if (it) {
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (pf && pf->prim_free) {
+ pf->prim_free(pval, it);
+ return;
+ }
+ }
+ /* Special case: if 'it' is NULL free contents of ASN1_TYPE */
+ if (!it) {
+ ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
+ utype = typ->type;
+ pval = &typ->value.asn1_value;
+ if (!*pval)
+ return;
+ } else if (it->itype == ASN1_ITYPE_MSTRING) {
+ utype = -1;
+ if (!*pval)
+ return;
+ } else {
+ utype = it->utype;
+ if ((utype != V_ASN1_BOOLEAN) && !*pval)
+ return;
+ }
+
+ switch (utype) {
+ case V_ASN1_OBJECT:
+ ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (it)
+ *(ASN1_BOOLEAN *)pval = it->size;
+ else
+ *(ASN1_BOOLEAN *)pval = -1;
+ return;
+
+ case V_ASN1_NULL:
+ break;
+
+ case V_ASN1_ANY:
+ ASN1_primitive_free(pval, NULL);
+ OPENSSL_free(*pval);
+ break;
+
+ default:
+ ASN1_STRING_free((ASN1_STRING *)*pval);
+ *pval = NULL;
+ break;
+ }
+ *pval = NULL;
+}
diff --git a/src/crypto/asn1/tasn_new.c b/src/crypto/asn1/tasn_new.c
index c68fe066..232fe46a 100644
--- a/src/crypto/asn1/tasn_new.c
+++ b/src/crypto/asn1/tasn_new.c
@@ -63,336 +63,319 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
-
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
- int combine);
+ int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
- {
- ASN1_VALUE *ret = NULL;
- if (ASN1_item_ex_new(&ret, it) > 0)
- return ret;
- return NULL;
- }
+{
+ ASN1_VALUE *ret = NULL;
+ if (ASN1_item_ex_new(&ret, it) > 0)
+ return ret;
+ return NULL;
+}
/* Allocate an ASN1 structure */
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- return asn1_item_ex_combine_new(pval, it, 0);
- }
+{
+ return asn1_item_ex_combine_new(pval, it, 0);
+}
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
- int combine)
- {
- const ASN1_TEMPLATE *tt = NULL;
- const ASN1_COMPAT_FUNCS *cf;
- const ASN1_EXTERN_FUNCS *ef;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
- ASN1_VALUE **pseqval;
- int i;
- if (aux && aux->asn1_cb)
- asn1_cb = aux->asn1_cb;
- else
- asn1_cb = 0;
+ int combine)
+{
+ const ASN1_TEMPLATE *tt = NULL;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ ASN1_VALUE **pseqval;
+ int i;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else
+ asn1_cb = 0;
#ifdef CRYPTO_MDEBUG
- if (it->sname)
- CRYPTO_push_info(it->sname);
+ if (it->sname)
+ CRYPTO_push_info(it->sname);
#endif
- switch(it->itype)
- {
-
- case ASN1_ITYPE_EXTERN:
- ef = it->funcs;
- if (ef && ef->asn1_ex_new)
- {
- if (!ef->asn1_ex_new(pval, it))
- goto memerr;
- }
- break;
-
- case ASN1_ITYPE_COMPAT:
- cf = it->funcs;
- if (cf && cf->asn1_new) {
- *pval = cf->asn1_new();
- if (!*pval)
- goto memerr;
- }
- break;
-
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates)
- {
- if (!ASN1_template_new(pval, it->templates))
- goto memerr;
- }
- else if (!ASN1_primitive_new(pval, it))
- goto memerr;
- break;
-
- case ASN1_ITYPE_MSTRING:
- if (!ASN1_primitive_new(pval, it))
- goto memerr;
- break;
-
- case ASN1_ITYPE_CHOICE:
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
- if (!i)
- goto auxerr;
- if (i==2)
- {
+ switch (it->itype) {
+
+ case ASN1_ITYPE_EXTERN:
+ ef = it->funcs;
+ if (ef && ef->asn1_ex_new) {
+ if (!ef->asn1_ex_new(pval, it))
+ goto memerr;
+ }
+ break;
+
+ case ASN1_ITYPE_COMPAT:
+ cf = it->funcs;
+ if (cf && cf->asn1_new) {
+ *pval = cf->asn1_new();
+ if (!*pval)
+ goto memerr;
+ }
+ break;
+
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates) {
+ if (!ASN1_template_new(pval, it->templates))
+ goto memerr;
+ } else if (!ASN1_primitive_new(pval, it))
+ goto memerr;
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ if (!ASN1_primitive_new(pval, it))
+ goto memerr;
+ break;
+
+ case ASN1_ITYPE_CHOICE:
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+ if (!i)
+ goto auxerr;
+ if (i == 2) {
#ifdef CRYPTO_MDEBUG
- if (it->sname)
- CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return 1;
- }
- }
- if (!combine)
- {
- *pval = OPENSSL_malloc(it->size);
- if (!*pval)
- goto memerr;
- memset(*pval, 0, it->size);
- }
- asn1_set_choice_selector(pval, -1, it);
- if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
- goto auxerr;
- break;
-
- case ASN1_ITYPE_NDEF_SEQUENCE:
- case ASN1_ITYPE_SEQUENCE:
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
- if (!i)
- goto auxerr;
- if (i==2)
- {
+ return 1;
+ }
+ }
+ if (!combine) {
+ *pval = OPENSSL_malloc(it->size);
+ if (!*pval)
+ goto memerr;
+ memset(*pval, 0, it->size);
+ }
+ asn1_set_choice_selector(pval, -1, it);
+ if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+ goto auxerr;
+ break;
+
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ case ASN1_ITYPE_SEQUENCE:
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+ if (!i)
+ goto auxerr;
+ if (i == 2) {
#ifdef CRYPTO_MDEBUG
- if (it->sname)
- CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return 1;
- }
- }
- if (!combine)
- {
- *pval = OPENSSL_malloc(it->size);
- if (!*pval)
- goto memerr;
- memset(*pval, 0, it->size);
- asn1_refcount_set_one(pval, it);
- asn1_enc_init(pval, it);
- }
- for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
- {
- pseqval = asn1_get_field_ptr(pval, tt);
- if (!ASN1_template_new(pseqval, tt))
- goto memerr;
- }
- if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
- goto auxerr;
- break;
- }
+ return 1;
+ }
+ }
+ if (!combine) {
+ *pval = OPENSSL_malloc(it->size);
+ if (!*pval)
+ goto memerr;
+ memset(*pval, 0, it->size);
+ asn1_refcount_set_one(pval, it);
+ asn1_enc_init(pval, it);
+ }
+ for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+ pseqval = asn1_get_field_ptr(pval, tt);
+ if (!ASN1_template_new(pseqval, tt))
+ goto memerr;
+ }
+ if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+ goto auxerr;
+ break;
+ }
#ifdef CRYPTO_MDEBUG
- if (it->sname) CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return 1;
+ return 1;
- memerr:
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- ASN1_item_ex_free(pval, it);
+ memerr:
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
- if (it->sname) CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return 0;
+ return 0;
- auxerr:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
- ASN1_item_ex_free(pval, it);
+ auxerr:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
+ ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
- if (it->sname) CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return 0;
+ return 0;
- }
+}
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- const ASN1_EXTERN_FUNCS *ef;
-
- switch(it->itype)
- {
-
- case ASN1_ITYPE_EXTERN:
- ef = it->funcs;
- if (ef && ef->asn1_ex_clear)
- ef->asn1_ex_clear(pval, it);
- else *pval = NULL;
- break;
-
-
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates)
- asn1_template_clear(pval, it->templates);
- else
- asn1_primitive_clear(pval, it);
- break;
-
- case ASN1_ITYPE_MSTRING:
- asn1_primitive_clear(pval, it);
- break;
-
- case ASN1_ITYPE_COMPAT:
- case ASN1_ITYPE_CHOICE:
- case ASN1_ITYPE_SEQUENCE:
- case ASN1_ITYPE_NDEF_SEQUENCE:
- *pval = NULL;
- break;
- }
- }
-
+{
+ const ASN1_EXTERN_FUNCS *ef;
+
+ switch (it->itype) {
+
+ case ASN1_ITYPE_EXTERN:
+ ef = it->funcs;
+ if (ef && ef->asn1_ex_clear)
+ ef->asn1_ex_clear(pval, it);
+ else
+ *pval = NULL;
+ break;
+
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates)
+ asn1_template_clear(pval, it->templates);
+ else
+ asn1_primitive_clear(pval, it);
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ asn1_primitive_clear(pval, it);
+ break;
+
+ case ASN1_ITYPE_COMPAT:
+ case ASN1_ITYPE_CHOICE:
+ case ASN1_ITYPE_SEQUENCE:
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ *pval = NULL;
+ break;
+ }
+}
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
- {
- const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
- int ret;
- if (tt->flags & ASN1_TFLG_OPTIONAL)
- {
- asn1_template_clear(pval, tt);
- return 1;
- }
- /* If ANY DEFINED BY nothing to do */
-
- if (tt->flags & ASN1_TFLG_ADB_MASK)
- {
- *pval = NULL;
- return 1;
- }
+{
+ const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
+ int ret;
+ if (tt->flags & ASN1_TFLG_OPTIONAL) {
+ asn1_template_clear(pval, tt);
+ return 1;
+ }
+ /* If ANY DEFINED BY nothing to do */
+
+ if (tt->flags & ASN1_TFLG_ADB_MASK) {
+ *pval = NULL;
+ return 1;
+ }
#ifdef CRYPTO_MDEBUG
- if (tt->field_name)
- CRYPTO_push_info(tt->field_name);
+ if (tt->field_name)
+ CRYPTO_push_info(tt->field_name);
#endif
- /* If SET OF or SEQUENCE OF, its a STACK */
- if (tt->flags & ASN1_TFLG_SK_MASK)
- {
- STACK_OF(ASN1_VALUE) *skval;
- skval = sk_ASN1_VALUE_new_null();
- if (!skval)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- ret = 0;
- goto done;
- }
- *pval = (ASN1_VALUE *)skval;
- ret = 1;
- goto done;
- }
- /* Otherwise pass it back to the item routine */
- ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
- done:
+ /* If SET OF or SEQUENCE OF, its a STACK */
+ if (tt->flags & ASN1_TFLG_SK_MASK) {
+ STACK_OF(ASN1_VALUE) *skval;
+ skval = sk_ASN1_VALUE_new_null();
+ if (!skval) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ ret = 0;
+ goto done;
+ }
+ *pval = (ASN1_VALUE *)skval;
+ ret = 1;
+ goto done;
+ }
+ /* Otherwise pass it back to the item routine */
+ ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
+ done:
#ifdef CRYPTO_MDEBUG
- if (it->sname)
- CRYPTO_pop_info();
+ if (it->sname)
+ CRYPTO_pop_info();
#endif
- return ret;
- }
+ return ret;
+}
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
- {
- /* If ADB or STACK just NULL the field */
- if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
- *pval = NULL;
- else
- asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
- }
-
-
-/* NB: could probably combine most of the real XXX_new() behaviour and junk
+{
+ /* If ADB or STACK just NULL the field */
+ if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
+ *pval = NULL;
+ else
+ asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
+}
+
+/*
+ * NB: could probably combine most of the real XXX_new() behaviour and junk
* all the old functions.
*/
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- ASN1_TYPE *typ;
- ASN1_STRING *str;
- int utype;
-
- if (!it)
- return 0;
-
- if (it->funcs)
- {
- const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
- if (pf->prim_new)
- return pf->prim_new(pval, it);
- }
-
- if (it->itype == ASN1_ITYPE_MSTRING)
- utype = -1;
- else
- utype = it->utype;
- switch(utype)
- {
- case V_ASN1_OBJECT:
- *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
- return 1;
-
- case V_ASN1_BOOLEAN:
- *(ASN1_BOOLEAN *)pval = it->size;
- return 1;
-
- case V_ASN1_NULL:
- *pval = (ASN1_VALUE *)1;
- return 1;
-
- case V_ASN1_ANY:
- typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
- if (!typ)
- return 0;
- typ->value.ptr = NULL;
- typ->type = -1;
- *pval = (ASN1_VALUE *)typ;
- break;
-
- default:
- str = ASN1_STRING_type_new(utype);
- if (it->itype == ASN1_ITYPE_MSTRING && str)
- str->flags |= ASN1_STRING_FLAG_MSTRING;
- *pval = (ASN1_VALUE *)str;
- break;
- }
- if (*pval)
- return 1;
- return 0;
- }
+{
+ ASN1_TYPE *typ;
+ ASN1_STRING *str;
+ int utype;
+
+ if (!it)
+ return 0;
+
+ if (it->funcs) {
+ const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+ if (pf->prim_new)
+ return pf->prim_new(pval, it);
+ }
+
+ if (it->itype == ASN1_ITYPE_MSTRING)
+ utype = -1;
+ else
+ utype = it->utype;
+ switch (utype) {
+ case V_ASN1_OBJECT:
+ *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
+ return 1;
+
+ case V_ASN1_BOOLEAN:
+ *(ASN1_BOOLEAN *)pval = it->size;
+ return 1;
+
+ case V_ASN1_NULL:
+ *pval = (ASN1_VALUE *)1;
+ return 1;
+
+ case V_ASN1_ANY:
+ typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
+ if (!typ)
+ return 0;
+ typ->value.ptr = NULL;
+ typ->type = -1;
+ *pval = (ASN1_VALUE *)typ;
+ break;
+
+ default:
+ str = ASN1_STRING_type_new(utype);
+ if (it->itype == ASN1_ITYPE_MSTRING && str)
+ str->flags |= ASN1_STRING_FLAG_MSTRING;
+ *pval = (ASN1_VALUE *)str;
+ break;
+ }
+ if (*pval)
+ return 1;
+ return 0;
+}
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
- {
- int utype;
- if (it && it->funcs)
- {
- const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
- if (pf->prim_clear)
- pf->prim_clear(pval, it);
- else
- *pval = NULL;
- return;
- }
- if (!it || (it->itype == ASN1_ITYPE_MSTRING))
- utype = -1;
- else
- utype = it->utype;
- if (utype == V_ASN1_BOOLEAN)
- *(ASN1_BOOLEAN *)pval = it->size;
- else *pval = NULL;
- }
+{
+ int utype;
+ if (it && it->funcs) {
+ const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+ if (pf->prim_clear)
+ pf->prim_clear(pval, it);
+ else
+ *pval = NULL;
+ return;
+ }
+ if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+ utype = -1;
+ else
+ utype = it->utype;
+ if (utype == V_ASN1_BOOLEAN)
+ *(ASN1_BOOLEAN *)pval = it->size;
+ else
+ *pval = NULL;
+}
diff --git a/src/crypto/asn1/tasn_prn.c b/src/crypto/asn1/tasn_prn.c
index a5740554..dd20cb4d 100644
--- a/src/crypto/asn1/tasn_prn.c
+++ b/src/crypto/asn1/tasn_prn.c
@@ -65,578 +65,532 @@
#include "asn1_locl.h"
-
-
-/* Print routines.
+/*
+ * Print routines.
*/
/* ASN1_PCTX routines */
-static ASN1_PCTX default_pctx =
- {
- ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
- 0, /* nm_flags */
- 0, /* cert_flags */
- 0, /* oid_flags */
- 0 /* str_flags */
- };
-
+static ASN1_PCTX default_pctx = {
+ ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
+ 0, /* nm_flags */
+ 0, /* cert_flags */
+ 0, /* oid_flags */
+ 0 /* str_flags */
+};
ASN1_PCTX *ASN1_PCTX_new(void)
- {
- ASN1_PCTX *ret;
- ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ret->flags = 0;
- ret->nm_flags = 0;
- ret->cert_flags = 0;
- ret->oid_flags = 0;
- ret->str_flags = 0;
- return ret;
- }
+{
+ ASN1_PCTX *ret;
+ ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret->flags = 0;
+ ret->nm_flags = 0;
+ ret->cert_flags = 0;
+ ret->oid_flags = 0;
+ ret->str_flags = 0;
+ return ret;
+}
void ASN1_PCTX_free(ASN1_PCTX *p)
- {
- OPENSSL_free(p);
- }
+{
+ OPENSSL_free(p);
+}
unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
- {
- return p->flags;
- }
+{
+ return p->flags;
+}
void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
- {
- p->flags = flags;
- }
+{
+ p->flags = flags;
+}
unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
- {
- return p->nm_flags;
- }
+{
+ return p->nm_flags;
+}
void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
- {
- p->nm_flags = flags;
- }
+{
+ p->nm_flags = flags;
+}
unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
- {
- return p->cert_flags;
- }
+{
+ return p->cert_flags;
+}
void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
- {
- p->cert_flags = flags;
- }
+{
+ p->cert_flags = flags;
+}
unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
- {
- return p->oid_flags;
- }
+{
+ return p->oid_flags;
+}
void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
- {
- p->oid_flags = flags;
- }
+{
+ p->oid_flags = flags;
+}
unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
- {
- return p->str_flags;
- }
+{
+ return p->str_flags;
+}
void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
- {
- p->str_flags = flags;
- }
+{
+ p->str_flags = flags;
+}
/* Main print routines */
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_ITEM *it,
- const char *fname, const char *sname,
- int nohdr, const ASN1_PCTX *pctx);
+ const ASN1_ITEM *it,
+ const char *fname, const char *sname,
+ int nohdr, const ASN1_PCTX *pctx);
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
+ const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
- const ASN1_ITEM *it, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx);
+ const ASN1_ITEM *it, int indent,
+ const char *fname, const char *sname,
+ const ASN1_PCTX *pctx);
static int asn1_print_fsname(BIO *out, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx);
+ const char *fname, const char *sname,
+ const ASN1_PCTX *pctx);
int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
- const ASN1_ITEM *it, const ASN1_PCTX *pctx)
- {
- const char *sname;
- if (pctx == NULL)
- pctx = &default_pctx;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
- sname = NULL;
- else
- sname = it->sname;
- return asn1_item_print_ctx(out, &ifld, indent, it,
- NULL, sname, 0, pctx);
- }
+ const ASN1_ITEM *it, const ASN1_PCTX *pctx)
+{
+ const char *sname;
+ if (pctx == NULL)
+ pctx = &default_pctx;
+ if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
+ sname = NULL;
+ else
+ sname = it->sname;
+ return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
+}
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_ITEM *it,
- const char *fname, const char *sname,
- int nohdr, const ASN1_PCTX *pctx)
- {
- const ASN1_TEMPLATE *tt;
- const ASN1_EXTERN_FUNCS *ef;
- ASN1_VALUE **tmpfld;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
- ASN1_PRINT_ARG parg;
- int i;
- if (aux && aux->asn1_cb)
- {
- parg.out = out;
- parg.indent = indent;
- parg.pctx = pctx;
- asn1_cb = aux->asn1_cb;
- }
- else asn1_cb = 0;
-
- if(*fld == NULL)
- {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT)
- {
- if (!nohdr && !asn1_print_fsname(out, indent,
- fname, sname, pctx))
- return 0;
- if (BIO_puts(out, "<ABSENT>\n") <= 0)
- return 0;
- }
- return 1;
- }
-
- switch(it->itype)
- {
- case ASN1_ITYPE_PRIMITIVE:
- if(it->templates)
- {
- if (!asn1_template_print_ctx(out, fld, indent,
- it->templates, pctx))
- return 0;
- break;
- }
- /* fall thru */
- case ASN1_ITYPE_MSTRING:
- if (!asn1_primitive_print(out, fld, it,
- indent, fname, sname,pctx))
- return 0;
- break;
-
- case ASN1_ITYPE_EXTERN:
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- /* Use new style print routine if possible */
- ef = it->funcs;
- if (ef && ef->asn1_ex_print)
- {
- i = ef->asn1_ex_print(out, fld, indent, "", pctx);
- if (!i)
- return 0;
- if ((i == 2) && (BIO_puts(out, "\n") <= 0))
- return 0;
- return 1;
- }
- else if (sname &&
- BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
- return 0;
- break;
-
- case ASN1_ITYPE_CHOICE:
+ const ASN1_ITEM *it,
+ const char *fname, const char *sname,
+ int nohdr, const ASN1_PCTX *pctx)
+{
+ const ASN1_TEMPLATE *tt;
+ const ASN1_EXTERN_FUNCS *ef;
+ ASN1_VALUE **tmpfld;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ ASN1_PRINT_ARG parg;
+ int i;
+ if (aux && aux->asn1_cb) {
+ parg.out = out;
+ parg.indent = indent;
+ parg.pctx = pctx;
+ asn1_cb = aux->asn1_cb;
+ } else
+ asn1_cb = 0;
+
+ if (*fld == NULL) {
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
+ if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+ if (BIO_puts(out, "<ABSENT>\n") <= 0)
+ return 0;
+ }
+ return 1;
+ }
+
+ switch (it->itype) {
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates) {
+ if (!asn1_template_print_ctx(out, fld, indent,
+ it->templates, pctx))
+ return 0;
+ break;
+ }
+ /* fall thru */
+ case ASN1_ITYPE_MSTRING:
+ if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx))
+ return 0;
+ break;
+
+ case ASN1_ITYPE_EXTERN:
+ if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+ /* Use new style print routine if possible */
+ ef = it->funcs;
+ if (ef && ef->asn1_ex_print) {
+ i = ef->asn1_ex_print(out, fld, indent, "", pctx);
+ if (!i)
+ return 0;
+ if ((i == 2) && (BIO_puts(out, "\n") <= 0))
+ return 0;
+ return 1;
+ } else if (sname &&
+ BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
+ return 0;
+ break;
+
+ case ASN1_ITYPE_CHOICE:
#if 0
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
+ if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
#endif
- /* CHOICE type, get selector */
- i = asn1_get_choice_selector(fld, it);
- /* This should never happen... */
- if((i < 0) || (i >= it->tcount))
- {
- if (BIO_printf(out,
- "ERROR: selector [%d] invalid\n", i) <= 0)
- return 0;
- return 1;
- }
- tt = it->templates + i;
- tmpfld = asn1_get_field_ptr(fld, tt);
- if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
- return 0;
- break;
-
- case ASN1_ITYPE_SEQUENCE:
- case ASN1_ITYPE_NDEF_SEQUENCE:
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- if (fname || sname)
- {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
- {
- if (BIO_puts(out, " {\n") <= 0)
- return 0;
- }
- else
- {
- if (BIO_puts(out, "\n") <= 0)
- return 0;
- }
- }
-
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
- if (i == 0)
- return 0;
- if (i == 2)
- return 1;
- }
-
- /* Print each field entry */
- for(i = 0, tt = it->templates; i < it->tcount; i++, tt++)
- {
- const ASN1_TEMPLATE *seqtt;
- seqtt = asn1_do_adb(fld, tt, 1);
- if (!seqtt)
- return 0;
- tmpfld = asn1_get_field_ptr(fld, seqtt);
- if (!asn1_template_print_ctx(out, tmpfld,
- indent + 2, seqtt, pctx))
- return 0;
- }
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
- {
- if (BIO_printf(out, "%*s}\n", indent, "") < 0)
- return 0;
- }
-
- if (asn1_cb)
- {
- i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
- if (i == 0)
- return 0;
- }
- break;
-
- default:
- BIO_printf(out, "Unprocessed type %d\n", it->itype);
- return 0;
- }
-
- return 1;
- }
+ /* CHOICE type, get selector */
+ i = asn1_get_choice_selector(fld, it);
+ /* This should never happen... */
+ if ((i < 0) || (i >= it->tcount)) {
+ if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
+ return 0;
+ return 1;
+ }
+ tt = it->templates + i;
+ tmpfld = asn1_get_field_ptr(fld, tt);
+ if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
+ return 0;
+ break;
+
+ case ASN1_ITYPE_SEQUENCE:
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+ if (fname || sname) {
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+ if (BIO_puts(out, " {\n") <= 0)
+ return 0;
+ } else {
+ if (BIO_puts(out, "\n") <= 0)
+ return 0;
+ }
+ }
+
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
+ if (i == 0)
+ return 0;
+ if (i == 2)
+ return 1;
+ }
+
+ /* Print each field entry */
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+ const ASN1_TEMPLATE *seqtt;
+ seqtt = asn1_do_adb(fld, tt, 1);
+ if (!seqtt)
+ return 0;
+ tmpfld = asn1_get_field_ptr(fld, seqtt);
+ if (!asn1_template_print_ctx(out, tmpfld,
+ indent + 2, seqtt, pctx))
+ return 0;
+ }
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+ if (BIO_printf(out, "%*s}\n", indent, "") < 0)
+ return 0;
+ }
+
+ if (asn1_cb) {
+ i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
+ if (i == 0)
+ return 0;
+ }
+ break;
+
+ default:
+ BIO_printf(out, "Unprocessed type %d\n", it->itype);
+ return 0;
+ }
+
+ return 1;
+}
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
- {
- int flags;
- size_t i;
- const char *sname, *fname;
- flags = tt->flags;
- if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
- sname = ASN1_ITEM_ptr(tt->item)->sname;
- else
- sname = NULL;
- if(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
- fname = NULL;
- else
- fname = tt->field_name;
- if(flags & ASN1_TFLG_SK_MASK)
- {
- const char *tname;
- ASN1_VALUE *skitem;
- STACK_OF(ASN1_VALUE) *stack;
-
- /* SET OF, SEQUENCE OF */
- if (fname)
- {
- if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF)
- {
- if(flags & ASN1_TFLG_SET_OF)
- tname = "SET";
- else
- tname = "SEQUENCE";
- if (BIO_printf(out, "%*s%s OF %s {\n",
- indent, "", tname, tt->field_name) <= 0)
- return 0;
- }
- else if (BIO_printf(out, "%*s%s:\n", indent, "",
- fname) <= 0)
- return 0;
- }
- stack = (STACK_OF(ASN1_VALUE) *)*fld;
- for(i = 0; i < sk_ASN1_VALUE_num(stack); i++)
- {
- if ((i > 0) && (BIO_puts(out, "\n") <= 0))
- return 0;
-
- skitem = sk_ASN1_VALUE_value(stack, i);
- if (!asn1_item_print_ctx(out, &skitem, indent + 2,
- ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
- return 0;
- }
- if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
- return 0;
- if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
- {
- if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
- return 0;
- }
- return 1;
- }
- return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
- fname, sname, 0, pctx);
- }
+ const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
+{
+ int flags;
+ size_t i;
+ const char *sname, *fname;
+ flags = tt->flags;
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
+ sname = ASN1_ITEM_ptr(tt->item)->sname;
+ else
+ sname = NULL;
+ if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
+ fname = NULL;
+ else
+ fname = tt->field_name;
+ if (flags & ASN1_TFLG_SK_MASK) {
+ const char *tname;
+ ASN1_VALUE *skitem;
+ STACK_OF(ASN1_VALUE) *stack;
+
+ /* SET OF, SEQUENCE OF */
+ if (fname) {
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
+ if (flags & ASN1_TFLG_SET_OF)
+ tname = "SET";
+ else
+ tname = "SEQUENCE";
+ if (BIO_printf(out, "%*s%s OF %s {\n",
+ indent, "", tname, tt->field_name) <= 0)
+ return 0;
+ } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
+ return 0;
+ }
+ stack = (STACK_OF(ASN1_VALUE) *)*fld;
+ for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
+ if ((i > 0) && (BIO_puts(out, "\n") <= 0))
+ return 0;
+
+ skitem = sk_ASN1_VALUE_value(stack, i);
+ if (!asn1_item_print_ctx(out, &skitem, indent + 2,
+ ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
+ pctx))
+ return 0;
+ }
+ if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
+ return 0;
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+ if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
+ return 0;
+ }
+ return 1;
+ }
+ return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
+ fname, sname, 0, pctx);
+}
static int asn1_print_fsname(BIO *out, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx)
- {
- static char spaces[] = " ";
- const int nspaces = sizeof(spaces) - 1;
+ const char *fname, const char *sname,
+ const ASN1_PCTX *pctx)
+{
+ static char spaces[] = " ";
+ const int nspaces = sizeof(spaces) - 1;
#if 0
- if (!sname && !fname)
- return 1;
+ if (!sname && !fname)
+ return 1;
#endif
- while (indent > nspaces)
- {
- if (BIO_write(out, spaces, nspaces) != nspaces)
- return 0;
- indent -= nspaces;
- }
- if (BIO_write(out, spaces, indent) != indent)
- return 0;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
- sname = NULL;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
- fname = NULL;
- if (!sname && !fname)
- return 1;
- if (fname)
- {
- if (BIO_puts(out, fname) <= 0)
- return 0;
- }
- if (sname)
- {
- if (fname)
- {
- if (BIO_printf(out, " (%s)", sname) <= 0)
- return 0;
- }
- else
- {
- if (BIO_puts(out, sname) <= 0)
- return 0;
- }
- }
- if (BIO_write(out, ": ", 2) != 2)
- return 0;
- return 1;
- }
+ while (indent > nspaces) {
+ if (BIO_write(out, spaces, nspaces) != nspaces)
+ return 0;
+ indent -= nspaces;
+ }
+ if (BIO_write(out, spaces, indent) != indent)
+ return 0;
+ if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
+ sname = NULL;
+ if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
+ fname = NULL;
+ if (!sname && !fname)
+ return 1;
+ if (fname) {
+ if (BIO_puts(out, fname) <= 0)
+ return 0;
+ }
+ if (sname) {
+ if (fname) {
+ if (BIO_printf(out, " (%s)", sname) <= 0)
+ return 0;
+ } else {
+ if (BIO_puts(out, sname) <= 0)
+ return 0;
+ }
+ }
+ if (BIO_write(out, ": ", 2) != 2)
+ return 0;
+ return 1;
+}
static int asn1_print_boolean_ctx(BIO *out, int boolval,
- const ASN1_PCTX *pctx)
- {
- const char *str;
- switch (boolval)
- {
- case -1:
- str = "BOOL ABSENT";
- break;
+ const ASN1_PCTX *pctx)
+{
+ const char *str;
+ switch (boolval) {
+ case -1:
+ str = "BOOL ABSENT";
+ break;
- case 0:
- str = "FALSE";
- break;
+ case 0:
+ str = "FALSE";
+ break;
- default:
- str = "TRUE";
- break;
+ default:
+ str = "TRUE";
+ break;
- }
+ }
- if (BIO_puts(out, str) <= 0)
- return 0;
- return 1;
+ if (BIO_puts(out, str) <= 0)
+ return 0;
+ return 1;
- }
+}
static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
- const ASN1_PCTX *pctx)
- {
- BIGNUM *bn = NULL;
- char *s = NULL;
- int ret = 1;
-
- bn = ASN1_INTEGER_to_BN(str, NULL);
- if (bn == NULL) {
- return 0;
- }
- s = BN_bn2dec(bn);
- BN_free(bn);
- if (s == NULL) {
- return 0;
- }
-
- if (BIO_puts(out, s) <= 0) {
- ret = 0;
- }
- OPENSSL_free(s);
- return ret;
- }
+ const ASN1_PCTX *pctx)
+{
+ BIGNUM *bn = NULL;
+ char *s = NULL;
+ int ret = 1;
+
+ bn = ASN1_INTEGER_to_BN(str, NULL);
+ if (bn == NULL) {
+ return 0;
+ }
+ s = BN_bn2dec(bn);
+ BN_free(bn);
+ if (s == NULL) {
+ return 0;
+ }
+
+ if (BIO_puts(out, s) <= 0) {
+ ret = 0;
+ }
+ OPENSSL_free(s);
+ return ret;
+}
static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
- const ASN1_PCTX *pctx)
- {
- char objbuf[80];
- const char *ln;
- ln = OBJ_nid2ln(OBJ_obj2nid(oid));
- if(!ln)
- ln = "";
- OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
- if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
- return 0;
- return 1;
- }
+ const ASN1_PCTX *pctx)
+{
+ char objbuf[80];
+ const char *ln;
+ ln = OBJ_nid2ln(OBJ_obj2nid(oid));
+ if (!ln)
+ ln = "";
+ OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
+ if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
+ return 0;
+ return 1;
+}
static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
- const ASN1_PCTX *pctx)
- {
- if (str->type == V_ASN1_BIT_STRING)
- {
- if (BIO_printf(out, " (%ld unused bits)\n",
- str->flags & 0x7) <= 0)
- return 0;
- }
- else if (BIO_puts(out, "\n") <= 0)
- return 0;
- if (str->length > 0 && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
- return 0;
- }
- return 1;
- }
+ const ASN1_PCTX *pctx)
+{
+ if (str->type == V_ASN1_BIT_STRING) {
+ if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0)
+ return 0;
+ } else if (BIO_puts(out, "\n") <= 0)
+ return 0;
+ if (str->length > 0
+ && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
+ return 0;
+ }
+ return 1;
+}
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
- const ASN1_ITEM *it, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx)
- {
- long utype;
- ASN1_STRING *str;
- int ret = 1, needlf = 1;
- const char *pname;
- const ASN1_PRIMITIVE_FUNCS *pf;
- pf = it->funcs;
- if (!asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- if (pf && pf->prim_print)
- return pf->prim_print(out, fld, it, indent, pctx);
- str = (ASN1_STRING *)*fld;
- if (it->itype == ASN1_ITYPE_MSTRING)
- utype = str->type & ~V_ASN1_NEG;
- else
- utype = it->utype;
- if (utype == V_ASN1_ANY)
- {
- ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
- utype = atype->type;
- fld = &atype->value.asn1_value;
- str = (ASN1_STRING *)*fld;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
- pname = NULL;
- else
- pname = ASN1_tag2str(utype);
- }
- else
- {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
- pname = ASN1_tag2str(utype);
- else
- pname = NULL;
- }
-
- if (utype == V_ASN1_NULL)
- {
- if (BIO_puts(out, "NULL\n") <= 0)
- return 0;
- return 1;
- }
-
- if (pname)
- {
- if (BIO_puts(out, pname) <= 0)
- return 0;
- if (BIO_puts(out, ":") <= 0)
- return 0;
- }
-
- switch (utype)
- {
- case V_ASN1_BOOLEAN:
- {
- int boolval = *(int *)fld;
- if (boolval == -1)
- boolval = it->size;
- ret = asn1_print_boolean_ctx(out, boolval, pctx);
- }
- break;
-
- case V_ASN1_INTEGER:
- case V_ASN1_ENUMERATED:
- ret = asn1_print_integer_ctx(out, str, pctx);
- break;
-
- case V_ASN1_UTCTIME:
- ret = ASN1_UTCTIME_print(out, str);
- break;
-
- case V_ASN1_GENERALIZEDTIME:
- ret = ASN1_GENERALIZEDTIME_print(out, str);
- break;
-
- case V_ASN1_OBJECT:
- ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
- break;
-
- case V_ASN1_OCTET_STRING:
- case V_ASN1_BIT_STRING:
- ret = asn1_print_obstring_ctx(out, str, indent, pctx);
- needlf = 0;
- break;
-
- case V_ASN1_SEQUENCE:
- case V_ASN1_SET:
- case V_ASN1_OTHER:
- if (BIO_puts(out, "\n") <= 0)
- return 0;
- if (ASN1_parse_dump(out, str->data, str->length,
- indent, 0) <= 0)
- ret = 0;
- needlf = 0;
- break;
-
- default:
- ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
-
- }
- if (!ret)
- return 0;
- if (needlf && BIO_puts(out, "\n") <= 0)
- return 0;
- return 1;
- }
+ const ASN1_ITEM *it, int indent,
+ const char *fname, const char *sname,
+ const ASN1_PCTX *pctx)
+{
+ long utype;
+ ASN1_STRING *str;
+ int ret = 1, needlf = 1;
+ const char *pname;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (!asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+ if (pf && pf->prim_print)
+ return pf->prim_print(out, fld, it, indent, pctx);
+ str = (ASN1_STRING *)*fld;
+ if (it->itype == ASN1_ITYPE_MSTRING)
+ utype = str->type & ~V_ASN1_NEG;
+ else
+ utype = it->utype;
+ if (utype == V_ASN1_ANY) {
+ ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
+ utype = atype->type;
+ fld = &atype->value.asn1_value;
+ str = (ASN1_STRING *)*fld;
+ if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
+ pname = NULL;
+ else
+ pname = ASN1_tag2str(utype);
+ } else {
+ if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
+ pname = ASN1_tag2str(utype);
+ else
+ pname = NULL;
+ }
+
+ if (utype == V_ASN1_NULL) {
+ if (BIO_puts(out, "NULL\n") <= 0)
+ return 0;
+ return 1;
+ }
+
+ if (pname) {
+ if (BIO_puts(out, pname) <= 0)
+ return 0;
+ if (BIO_puts(out, ":") <= 0)
+ return 0;
+ }
+
+ switch (utype) {
+ case V_ASN1_BOOLEAN:
+ {
+ int boolval = *(int *)fld;
+ if (boolval == -1)
+ boolval = it->size;
+ ret = asn1_print_boolean_ctx(out, boolval, pctx);
+ }
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_ENUMERATED:
+ ret = asn1_print_integer_ctx(out, str, pctx);
+ break;
+
+ case V_ASN1_UTCTIME:
+ ret = ASN1_UTCTIME_print(out, str);
+ break;
+
+ case V_ASN1_GENERALIZEDTIME:
+ ret = ASN1_GENERALIZEDTIME_print(out, str);
+ break;
+
+ case V_ASN1_OBJECT:
+ ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
+ break;
+
+ case V_ASN1_OCTET_STRING:
+ case V_ASN1_BIT_STRING:
+ ret = asn1_print_obstring_ctx(out, str, indent, pctx);
+ needlf = 0;
+ break;
+
+ case V_ASN1_SEQUENCE:
+ case V_ASN1_SET:
+ case V_ASN1_OTHER:
+ if (BIO_puts(out, "\n") <= 0)
+ return 0;
+ if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0)
+ ret = 0;
+ needlf = 0;
+ break;
+
+ default:
+ ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
+
+ }
+ if (!ret)
+ return 0;
+ if (needlf && BIO_puts(out, "\n") <= 0)
+ return 0;
+ return 1;
+}
diff --git a/src/crypto/asn1/tasn_typ.c b/src/crypto/asn1/tasn_typ.c
index f004b0dc..daf02eae 100644
--- a/src/crypto/asn1/tasn_typ.c
+++ b/src/crypto/asn1/tasn_typ.c
@@ -58,20 +58,19 @@
#include <openssl/asn1t.h>
-
/* Declarations for string types */
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
- IMPLEMENT_ASN1_TYPE(sname) \
- IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
- sname *sname##_new(void) \
- { \
- return ASN1_STRING_type_new(V_##sname); \
- } \
- void sname##_free(sname *x) \
- { \
- ASN1_STRING_free(x); \
- }
+ IMPLEMENT_ASN1_TYPE(sname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
+ sname *sname##_new(void) \
+ { \
+ return ASN1_STRING_type_new(V_##sname); \
+ } \
+ void sname##_free(sname *x) \
+ { \
+ ASN1_STRING_free(x); \
+ }
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
@@ -95,12 +94,16 @@ IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
IMPLEMENT_ASN1_TYPE(ASN1_ANY);
-/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
+/*
+ * Just swallow an ASN1_SEQUENCE in an ASN1_STRING
+ */ ;
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
-/* Multistring types */;
+/*
+ * Multistring types
+ */ ;
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
@@ -111,18 +114,23 @@ IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT);
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING);
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING);
-/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */;
+/*
+ * Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE
+ */ ;
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1);
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1);
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0);
-/* Special, OCTET STRING with indefinite length constructed support */;
+/*
+ * Special, OCTET STRING with indefinite length constructed support
+ */ ;
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING,
- ASN1_TFLG_NDEF);
+ASN1_TFLG_NDEF);
-ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = ASN1_EX_TEMPLATE_TYPE(
- ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY);
+ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY,
+ ASN1_ANY);
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY);
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
@@ -131,7 +139,6 @@ ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY);
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY,
- ASN1_SEQUENCE_ANY,
- ASN1_SEQUENCE_ANY);
+ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY);
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY,
- ASN1_SET_ANY);
+ASN1_SET_ANY);
diff --git a/src/crypto/asn1/x_bignum.c b/src/crypto/asn1/x_bignum.c
index 5867c4ff..585d9d4a 100644
--- a/src/crypto/asn1/x_bignum.c
+++ b/src/crypto/asn1/x_bignum.c
@@ -59,85 +59,95 @@
#include <openssl/asn1t.h>
#include <openssl/bn.h>
-
-/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a
- * BIGNUM directly. Currently it ignores the sign which isn't a problem since all
- * BIGNUMs used are non negative and anything that looks negative is normally due
- * to an encoding error.
+/*
+ * Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
+ * as a BIGNUM directly. Currently it ignores the sign which isn't a problem
+ * since all BIGNUMs used are non negative and anything that looks negative
+ * is normally due to an encoding error.
*/
-#define BN_SENSITIVE 1
+#define BN_SENSITIVE 1
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
-static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it);
+static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+ int utype, char *free_cont, const ASN1_ITEM *it);
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
- NULL, 0,
- bn_new,
- bn_free,
- 0,
- bn_c2i,
- bn_i2c,
- NULL /* prim_print */,
+ NULL, 0,
+ bn_new,
+ bn_free,
+ 0,
+ bn_c2i,
+ bn_i2c,
+ NULL /* prim_print */ ,
};
ASN1_ITEM_start(BIGNUM)
- ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)
ASN1_ITEM_start(CBIGNUM)
- ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
ASN1_ITEM_end(CBIGNUM)
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- *pval = (ASN1_VALUE *)BN_new();
- if(*pval) return 1;
- else return 0;
+ *pval = (ASN1_VALUE *)BN_new();
+ if (*pval)
+ return 1;
+ else
+ return 0;
}
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- if(!*pval) return;
- if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval);
- else BN_free((BIGNUM *)*pval);
- *pval = NULL;
+ if (!*pval)
+ return;
+ if (it->size & BN_SENSITIVE)
+ BN_clear_free((BIGNUM *)*pval);
+ else
+ BN_free((BIGNUM *)*pval);
+ *pval = NULL;
}
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
+static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it)
{
- BIGNUM *bn;
- int pad;
- if(!*pval) return -1;
- bn = (BIGNUM *)*pval;
- /* If MSB set in an octet we need a padding byte */
- if(BN_num_bits(bn) & 0x7) pad = 0;
- else pad = 1;
- if(cont) {
- if(pad) *cont++ = 0;
- BN_bn2bin(bn, cont);
- }
- return pad + BN_num_bytes(bn);
+ BIGNUM *bn;
+ int pad;
+ if (!*pval)
+ return -1;
+ bn = (BIGNUM *)*pval;
+ /* If MSB set in an octet we need a padding byte */
+ if (BN_num_bits(bn) & 0x7)
+ pad = 0;
+ else
+ pad = 1;
+ if (cont) {
+ if (pad)
+ *cont++ = 0;
+ BN_bn2bin(bn, cont);
+ }
+ return pad + BN_num_bytes(bn);
}
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
- int utype, char *free_cont, const ASN1_ITEM *it)
+ int utype, char *free_cont, const ASN1_ITEM *it)
{
- BIGNUM *bn;
- if(!*pval)
- {
- if (!bn_new(pval, it))
- {
- return 0;
- }
- }
- bn = (BIGNUM *)*pval;
- if(!BN_bin2bn(cont, len, bn)) {
- bn_free(pval, it);
- return 0;
- }
- return 1;
+ BIGNUM *bn;
+ if (!*pval) {
+ if (!bn_new(pval, it)) {
+ return 0;
+ }
+ }
+ bn = (BIGNUM *)*pval;
+ if (!BN_bin2bn(cont, len, bn)) {
+ bn_free(pval, it);
+ return 0;
+ }
+ return 1;
}
diff --git a/src/crypto/asn1/x_long.c b/src/crypto/asn1/x_long.c
index 7b1a6fe8..bc4d2751 100644
--- a/src/crypto/asn1/x_long.c
+++ b/src/crypto/asn1/x_long.c
@@ -63,120 +63,135 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
-/* Custom primitive type for long handling. This converts between an ASN1_INTEGER
- * and a long directly.
+/*
+ * Custom primitive type for long handling. This converts between an
+ * ASN1_INTEGER and a long directly.
*/
-
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
-static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx);
+static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it);
+static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+ int utype, char *free_cont, const ASN1_ITEM *it);
+static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int indent, const ASN1_PCTX *pctx);
static const ASN1_PRIMITIVE_FUNCS long_pf = {
- NULL, 0,
- long_new,
- long_free,
- long_free, /* Clear should set to initial value */
- long_c2i,
- long_i2c,
- long_print
+ NULL, 0,
+ long_new,
+ long_free,
+ long_free, /* Clear should set to initial value */
+ long_c2i,
+ long_i2c,
+ long_print
};
ASN1_ITEM_start(LONG)
- ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
ASN1_ITEM_end(LONG)
ASN1_ITEM_start(ZLONG)
- ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
ASN1_ITEM_end(ZLONG)
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- *(long *)pval = it->size;
- return 1;
+ *(long *)pval = it->size;
+ return 1;
}
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- *(long *)pval = it->size;
+ *(long *)pval = it->size;
}
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
+static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it)
{
- long ltmp;
- unsigned long utmp;
- int clen, pad, i;
- /* this exists to bypass broken gcc optimization */
- char *cp = (char *)pval;
-
- /* use memcpy, because we may not be long aligned */
- memcpy(&ltmp, cp, sizeof(long));
-
- if(ltmp == it->size) return -1;
- /* Convert the long to positive: we subtract one if negative so
- * we can cleanly handle the padding if only the MSB of the leading
- * octet is set.
- */
- if(ltmp < 0) utmp = -ltmp - 1;
- else utmp = ltmp;
- clen = BN_num_bits_word(utmp);
- /* If MSB of leading octet set we need to pad */
- if(!(clen & 0x7)) pad = 1;
- else pad = 0;
-
- /* Convert number of bits to number of octets */
- clen = (clen + 7) >> 3;
-
- if(cont) {
- if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
- for(i = clen - 1; i >= 0; i--) {
- cont[i] = (unsigned char)(utmp & 0xff);
- if(ltmp < 0) cont[i] ^= 0xff;
- utmp >>= 8;
- }
- }
- return clen + pad;
+ long ltmp;
+ unsigned long utmp;
+ int clen, pad, i;
+ /* this exists to bypass broken gcc optimization */
+ char *cp = (char *)pval;
+
+ /* use memcpy, because we may not be long aligned */
+ memcpy(&ltmp, cp, sizeof(long));
+
+ if (ltmp == it->size)
+ return -1;
+ /*
+ * Convert the long to positive: we subtract one if negative so we can
+ * cleanly handle the padding if only the MSB of the leading octet is
+ * set.
+ */
+ if (ltmp < 0)
+ utmp = -ltmp - 1;
+ else
+ utmp = ltmp;
+ clen = BN_num_bits_word(utmp);
+ /* If MSB of leading octet set we need to pad */
+ if (!(clen & 0x7))
+ pad = 1;
+ else
+ pad = 0;
+
+ /* Convert number of bits to number of octets */
+ clen = (clen + 7) >> 3;
+
+ if (cont) {
+ if (pad)
+ *cont++ = (ltmp < 0) ? 0xff : 0;
+ for (i = clen - 1; i >= 0; i--) {
+ cont[i] = (unsigned char)(utmp & 0xff);
+ if (ltmp < 0)
+ cont[i] ^= 0xff;
+ utmp >>= 8;
+ }
+ }
+ return clen + pad;
}
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
- int utype, char *free_cont, const ASN1_ITEM *it)
+ int utype, char *free_cont, const ASN1_ITEM *it)
{
- int neg, i;
- long ltmp;
- unsigned long utmp = 0;
- char *cp = (char *)pval;
- if(len > (int)sizeof(long)) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
- return 0;
- }
- /* Is it negative? */
- if(len && (cont[0] & 0x80)) neg = 1;
- else neg = 0;
- utmp = 0;
- for(i = 0; i < len; i++) {
- utmp <<= 8;
- if(neg) utmp |= cont[i] ^ 0xff;
- else utmp |= cont[i];
- }
- ltmp = (long)utmp;
- if(neg) {
- ltmp++;
- ltmp = -ltmp;
- }
- if(ltmp == it->size) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
- return 0;
- }
- memcpy(cp, &ltmp, sizeof(long));
- return 1;
+ int neg, i;
+ long ltmp;
+ unsigned long utmp = 0;
+ char *cp = (char *)pval;
+ if (len > (int)sizeof(long)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ /* Is it negative? */
+ if (len && (cont[0] & 0x80))
+ neg = 1;
+ else
+ neg = 0;
+ utmp = 0;
+ for (i = 0; i < len; i++) {
+ utmp <<= 8;
+ if (neg)
+ utmp |= cont[i] ^ 0xff;
+ else
+ utmp |= cont[i];
+ }
+ ltmp = (long)utmp;
+ if (neg) {
+ ltmp++;
+ ltmp = -ltmp;
+ }
+ if (ltmp == it->size) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ memcpy(cp, &ltmp, sizeof(long));
+ return 1;
}
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
- int indent, const ASN1_PCTX *pctx)
- {
- return BIO_printf(out, "%ld\n", *(long *)pval);
- }
+ int indent, const ASN1_PCTX *pctx)
+{
+ return BIO_printf(out, "%ld\n", *(long *)pval);
+}
diff --git a/src/crypto/base64/base64_test.cc b/src/crypto/base64/base64_test.cc
index fde0b469..da016e66 100644
--- a/src/crypto/base64/base64_test.cc
+++ b/src/crypto/base64/base64_test.cc
@@ -116,7 +116,6 @@ static bool TestDecode() {
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!TestEncode() ||
!TestDecode()) {
diff --git a/src/crypto/bio/bio_mem.c b/src/crypto/bio/bio_mem.c
index 6864f6f1..844fba7e 100644
--- a/src/crypto/bio/bio_mem.c
+++ b/src/crypto/bio/bio_mem.c
@@ -64,7 +64,7 @@
#include <openssl/mem.h>
-BIO *BIO_new_mem_buf(void *buf, int len) {
+BIO *BIO_new_mem_buf(const void *buf, int len) {
BIO *ret;
BUF_MEM *b;
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
@@ -80,7 +80,8 @@ BIO *BIO_new_mem_buf(void *buf, int len) {
}
b = (BUF_MEM *)ret->ptr;
- b->data = buf;
+ /* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */
+ b->data = (void *)buf;
b->length = size;
b->max = size;
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 4d7dfe28..3615ab46 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -331,7 +331,7 @@ static bool TestPrintf() {
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
size_t expected_len, size_t max_len) {
- ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len));
+ ScopedBIO bio(BIO_new_mem_buf(data, data_len));
uint8_t *out;
size_t out_len;
@@ -412,7 +412,6 @@ static bool TestASN1() {
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
#if defined(OPENSSL_WINDOWS)
// Initialize Winsock.
diff --git a/src/crypto/bio/buffer.c b/src/crypto/bio/buffer.c
index 9d0cb3c0..15574510 100644
--- a/src/crypto/bio/buffer.c
+++ b/src/crypto/bio/buffer.c
@@ -100,7 +100,7 @@ static int buffer_new(BIO *bio) {
if (ctx->ibuf == NULL) {
goto err1;
}
- ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
+ ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
if (ctx->obuf == NULL) {
goto err2;
}
@@ -340,13 +340,13 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
p1 = ctx->ibuf;
p2 = ctx->obuf;
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
- p1 = (char *)OPENSSL_malloc(ibs);
+ p1 = OPENSSL_malloc(ibs);
if (p1 == NULL) {
goto malloc_error;
}
}
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
- p2 = (char *)OPENSSL_malloc(obs);
+ p2 = OPENSSL_malloc(obs);
if (p2 == NULL) {
if (p1 != ctx->ibuf) {
OPENSSL_free(p1);
diff --git a/src/crypto/bio/connect.c b/src/crypto/bio/connect.c
index 0b0bf131..01d49b1b 100644
--- a/src/crypto/bio/connect.c
+++ b/src/crypto/bio/connect.c
@@ -58,7 +58,6 @@
#include <assert.h>
#include <errno.h>
-#include <stdio.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
@@ -542,3 +541,7 @@ int BIO_set_conn_port(BIO *bio, const char *port_str) {
int BIO_set_nbio(BIO *bio, int on) {
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
}
+
+int BIO_do_connect(BIO *bio) {
+ return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
+}
diff --git a/src/crypto/bio/fd.c b/src/crypto/bio/fd.c
index 0b3484c9..12e6a72b 100644
--- a/src/crypto/bio/fd.c
+++ b/src/crypto/bio/fd.c
@@ -72,6 +72,8 @@
#include <openssl/err.h>
#include <openssl/mem.h>
+#include "internal.h"
+
static int bio_fd_non_fatal_error(int err) {
if (
diff --git a/src/crypto/bio/file.c b/src/crypto/bio/file.c
index 9e29b43c..b903bc28 100644
--- a/src/crypto/bio/file.c
+++ b/src/crypto/bio/file.c
@@ -87,47 +87,11 @@
#define BIO_FP_WRITE 0x04
#define BIO_FP_APPEND 0x08
-static FILE *open_file(const char *filename, const char *mode) {
-#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
- int sz, len_0 = (int)strlen(filename) + 1;
- DWORD flags;
-
- /* Basically there are three cases to cover: a) filename is pure ASCII
- * string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
- * containing 8-bit characters that are meaningful in current system locale.
- * If filename is pure ASCII or real UTF-8 encoded string,
- * MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
- * string, chances are that MultiByteToWideChar fails reporting
- * ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
- if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
- filename, len_0, NULL, 0)) > 0 ||
- (GetLastError() == ERROR_INVALID_FLAGS &&
- (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
- 0)) > 0)) {
- WCHAR wmode[8];
- WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
-
- if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
- MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
- sizeof(wmode) / sizeof(wmode[0])) &&
- (file = _wfopen(wfilename, wmode)) == NULL &&
- (errno == ENOENT ||
- errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
- * could still have been locale-ized... */
- return fopen(filename, mode);
- } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
- return fopen(filename, mode);
- }
-#else
- return fopen(filename, mode);
-#endif
-}
-
BIO *BIO_new_file(const char *filename, const char *mode) {
BIO *ret;
FILE *file;
- file = open_file(filename, mode);
+ file = fopen(filename, mode);
if (file == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
@@ -256,7 +220,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
ret = 0;
break;
}
- fp = open_file(ptr, p);
+ fp = fopen(ptr, p);
if (fp == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
diff --git a/src/crypto/bio/internal.h b/src/crypto/bio/internal.h
index d9a34f18..eb6b26f6 100644
--- a/src/crypto/bio/internal.h
+++ b/src/crypto/bio/internal.h
@@ -67,6 +67,9 @@ typedef unsigned short u_short;
#include <sys/types.h>
#include <sys/socket.h>
#else
+#pragma warning(push, 3)
+#include <winsock2.h>
+#pragma warning(pop)
typedef int socklen_t;
#endif
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
index fba4be2c..2da2d203 100644
--- a/src/crypto/bio/pair.c
+++ b/src/crypto/bio/pair.c
@@ -742,7 +742,7 @@ static const BIO_METHOD methods_biop = {
bio_free, NULL /* no bio_callback_ctrl */
};
-const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
+static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
BIO** bio2_p, size_t writebuf2) {
diff --git a/src/crypto/bio/socket.c b/src/crypto/bio/socket.c
index 98f32a62..3ef69674 100644
--- a/src/crypto/bio/socket.c
+++ b/src/crypto/bio/socket.c
@@ -110,7 +110,11 @@ static int sock_read(BIO *b, char *out, int outl) {
}
bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
ret = recv(b->num, out, outl, 0);
+#else
+ ret = read(b->num, out, outl);
+#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
@@ -124,7 +128,11 @@ static int sock_write(BIO *b, const char *in, int inl) {
int ret;
bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
ret = send(b->num, in, inl, 0);
+#else
+ ret = write(b->num, in, inl);
+#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
diff --git a/src/crypto/bn/asm/armv4-mont.pl b/src/crypto/bn/asm/armv4-mont.pl
index 4206fd85..b7511128 100644
--- a/src/crypto/bn/asm/armv4-mont.pl
+++ b/src/crypto/bn/asm/armv4-mont.pl
@@ -91,7 +91,6 @@ $code=<<___;
#endif
.global bn_mul_mont
-.hidden bn_mul_mont
.type bn_mul_mont,%function
.align 5
@@ -108,7 +107,7 @@ bn_mul_mont:
#ifdef __APPLE__
ldr r0,[r0]
#endif
- tst r0,#1 @ NEON available?
+ tst r0,#ARMV7_NEON @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
add sp,sp,#8
diff --git a/src/crypto/bn/asm/rsaz-avx2.pl b/src/crypto/bn/asm/rsaz-avx2.pl
index bbceccb3..6b57bd0b 100644..100755
--- a/src/crypto/bn/asm/rsaz-avx2.pl
+++ b/src/crypto/bn/asm/rsaz-avx2.pl
@@ -427,7 +427,7 @@ $TEMP2 = $B2;
$TEMP3 = $Y1;
$TEMP4 = $Y2;
$code.=<<___;
- #we need to fix indexes 32-39 to avoid overflow
+ # we need to fix indices 32-39 to avoid overflow
vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0),
vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0)
vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0)
@@ -1576,68 +1576,128 @@ rsaz_1024_scatter5_avx2:
.type rsaz_1024_gather5_avx2,\@abi-omnipotent
.align 32
rsaz_1024_gather5_avx2:
+ vzeroupper
+ mov %rsp,%r11
___
$code.=<<___ if ($win64);
lea -0x88(%rsp),%rax
- vzeroupper
.LSEH_begin_rsaz_1024_gather5:
# I can't trust assembler to use specific encoding:-(
- .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
- .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6,-0x20(%rax)
- .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7,-0x10(%rax)
- .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8,0(%rax)
- .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9,0x10(%rax)
- .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10,0x20(%rax)
- .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11,0x30(%rax)
- .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12,0x40(%rax)
- .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13,0x50(%rax)
- .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14,0x60(%rax)
- .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15,0x70(%rax)
+ .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax),%rsp
+ .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6,-0x20(%rax)
+ .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7,-0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8,0(%rax)
+ .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9,0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10,0x20(%rax)
+ .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11,0x30(%rax)
+ .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12,0x40(%rax)
+ .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13,0x50(%rax)
+ .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14,0x60(%rax)
+ .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15,0x70(%rax)
___
$code.=<<___;
- lea .Lgather_table(%rip),%r11
- mov $power,%eax
- and \$3,$power
- shr \$2,%eax # cache line number
- shl \$4,$power # offset within cache line
-
- vmovdqu -32(%r11),%ymm7 # .Lgather_permd
- vpbroadcastb 8(%r11,%rax), %xmm8
- vpbroadcastb 7(%r11,%rax), %xmm9
- vpbroadcastb 6(%r11,%rax), %xmm10
- vpbroadcastb 5(%r11,%rax), %xmm11
- vpbroadcastb 4(%r11,%rax), %xmm12
- vpbroadcastb 3(%r11,%rax), %xmm13
- vpbroadcastb 2(%r11,%rax), %xmm14
- vpbroadcastb 1(%r11,%rax), %xmm15
-
- lea 64($inp,$power),$inp
- mov \$64,%r11 # size optimization
- mov \$9,%eax
- jmp .Loop_gather_1024
+ lea -0x100(%rsp),%rsp
+ and \$-32, %rsp
+ lea .Linc(%rip), %r10
+ lea -128(%rsp),%rax # control u-op density
+
+ vmovd $power, %xmm4
+ vmovdqa (%r10),%ymm0
+ vmovdqa 32(%r10),%ymm1
+ vmovdqa 64(%r10),%ymm5
+ vpbroadcastd %xmm4,%ymm4
+
+ vpaddd %ymm5, %ymm0, %ymm2
+ vpcmpeqd %ymm4, %ymm0, %ymm0
+ vpaddd %ymm5, %ymm1, %ymm3
+ vpcmpeqd %ymm4, %ymm1, %ymm1
+ vmovdqa %ymm0, 32*0+128(%rax)
+ vpaddd %ymm5, %ymm2, %ymm0
+ vpcmpeqd %ymm4, %ymm2, %ymm2
+ vmovdqa %ymm1, 32*1+128(%rax)
+ vpaddd %ymm5, %ymm3, %ymm1
+ vpcmpeqd %ymm4, %ymm3, %ymm3
+ vmovdqa %ymm2, 32*2+128(%rax)
+ vpaddd %ymm5, %ymm0, %ymm2
+ vpcmpeqd %ymm4, %ymm0, %ymm0
+ vmovdqa %ymm3, 32*3+128(%rax)
+ vpaddd %ymm5, %ymm1, %ymm3
+ vpcmpeqd %ymm4, %ymm1, %ymm1
+ vmovdqa %ymm0, 32*4+128(%rax)
+ vpaddd %ymm5, %ymm2, %ymm8
+ vpcmpeqd %ymm4, %ymm2, %ymm2
+ vmovdqa %ymm1, 32*5+128(%rax)
+ vpaddd %ymm5, %ymm3, %ymm9
+ vpcmpeqd %ymm4, %ymm3, %ymm3
+ vmovdqa %ymm2, 32*6+128(%rax)
+ vpaddd %ymm5, %ymm8, %ymm10
+ vpcmpeqd %ymm4, %ymm8, %ymm8
+ vmovdqa %ymm3, 32*7+128(%rax)
+ vpaddd %ymm5, %ymm9, %ymm11
+ vpcmpeqd %ymm4, %ymm9, %ymm9
+ vpaddd %ymm5, %ymm10, %ymm12
+ vpcmpeqd %ymm4, %ymm10, %ymm10
+ vpaddd %ymm5, %ymm11, %ymm13
+ vpcmpeqd %ymm4, %ymm11, %ymm11
+ vpaddd %ymm5, %ymm12, %ymm14
+ vpcmpeqd %ymm4, %ymm12, %ymm12
+ vpaddd %ymm5, %ymm13, %ymm15
+ vpcmpeqd %ymm4, %ymm13, %ymm13
+ vpcmpeqd %ymm4, %ymm14, %ymm14
+ vpcmpeqd %ymm4, %ymm15, %ymm15
+
+ vmovdqa -32(%r10),%ymm7 # .Lgather_permd
+ lea 128($inp), $inp
+ mov \$9,$power
-.align 32
.Loop_gather_1024:
- vpand -64($inp), %xmm8,%xmm0
- vpand ($inp), %xmm9,%xmm1
- vpand 64($inp), %xmm10,%xmm2
- vpand ($inp,%r11,2), %xmm11,%xmm3
- vpor %xmm0,%xmm1,%xmm1
- vpand 64($inp,%r11,2), %xmm12,%xmm4
- vpor %xmm2,%xmm3,%xmm3
- vpand ($inp,%r11,4), %xmm13,%xmm5
- vpor %xmm1,%xmm3,%xmm3
- vpand 64($inp,%r11,4), %xmm14,%xmm6
- vpor %xmm4,%xmm5,%xmm5
- vpand -128($inp,%r11,8), %xmm15,%xmm2
- lea ($inp,%r11,8),$inp
- vpor %xmm3,%xmm5,%xmm5
- vpor %xmm2,%xmm6,%xmm6
- vpor %xmm5,%xmm6,%xmm6
- vpermd %ymm6,%ymm7,%ymm6
- vmovdqu %ymm6,($out)
+ vmovdqa 32*0-128($inp), %ymm0
+ vmovdqa 32*1-128($inp), %ymm1
+ vmovdqa 32*2-128($inp), %ymm2
+ vmovdqa 32*3-128($inp), %ymm3
+ vpand 32*0+128(%rax), %ymm0, %ymm0
+ vpand 32*1+128(%rax), %ymm1, %ymm1
+ vpand 32*2+128(%rax), %ymm2, %ymm2
+ vpor %ymm0, %ymm1, %ymm4
+ vpand 32*3+128(%rax), %ymm3, %ymm3
+ vmovdqa 32*4-128($inp), %ymm0
+ vmovdqa 32*5-128($inp), %ymm1
+ vpor %ymm2, %ymm3, %ymm5
+ vmovdqa 32*6-128($inp), %ymm2
+ vmovdqa 32*7-128($inp), %ymm3
+ vpand 32*4+128(%rax), %ymm0, %ymm0
+ vpand 32*5+128(%rax), %ymm1, %ymm1
+ vpand 32*6+128(%rax), %ymm2, %ymm2
+ vpor %ymm0, %ymm4, %ymm4
+ vpand 32*7+128(%rax), %ymm3, %ymm3
+ vpand 32*8-128($inp), %ymm8, %ymm0
+ vpor %ymm1, %ymm5, %ymm5
+ vpand 32*9-128($inp), %ymm9, %ymm1
+ vpor %ymm2, %ymm4, %ymm4
+ vpand 32*10-128($inp),%ymm10, %ymm2
+ vpor %ymm3, %ymm5, %ymm5
+ vpand 32*11-128($inp),%ymm11, %ymm3
+ vpor %ymm0, %ymm4, %ymm4
+ vpand 32*12-128($inp),%ymm12, %ymm0
+ vpor %ymm1, %ymm5, %ymm5
+ vpand 32*13-128($inp),%ymm13, %ymm1
+ vpor %ymm2, %ymm4, %ymm4
+ vpand 32*14-128($inp),%ymm14, %ymm2
+ vpor %ymm3, %ymm5, %ymm5
+ vpand 32*15-128($inp),%ymm15, %ymm3
+ lea 32*16($inp), $inp
+ vpor %ymm0, %ymm4, %ymm4
+ vpor %ymm1, %ymm5, %ymm5
+ vpor %ymm2, %ymm4, %ymm4
+ vpor %ymm3, %ymm5, %ymm5
+
+ vpor %ymm5, %ymm4, %ymm4
+ vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared
+ vpor %xmm4, %xmm5, %xmm5
+ vpermd %ymm5,%ymm7,%ymm5
+ vmovdqu %ymm5,($out)
lea 32($out),$out
- dec %eax
+ dec $power
jnz .Loop_gather_1024
vpxor %ymm0,%ymm0,%ymm0
@@ -1645,20 +1705,20 @@ $code.=<<___;
vzeroupper
___
$code.=<<___ if ($win64);
- movaps (%rsp),%xmm6
- movaps 0x10(%rsp),%xmm7
- movaps 0x20(%rsp),%xmm8
- movaps 0x30(%rsp),%xmm9
- movaps 0x40(%rsp),%xmm10
- movaps 0x50(%rsp),%xmm11
- movaps 0x60(%rsp),%xmm12
- movaps 0x70(%rsp),%xmm13
- movaps 0x80(%rsp),%xmm14
- movaps 0x90(%rsp),%xmm15
- lea 0xa8(%rsp),%rsp
+ movaps -0xa8(%r11),%xmm6
+ movaps -0x98(%r11),%xmm7
+ movaps -0x88(%r11),%xmm8
+ movaps -0x78(%r11),%xmm9
+ movaps -0x68(%r11),%xmm10
+ movaps -0x58(%r11),%xmm11
+ movaps -0x48(%r11),%xmm12
+ movaps -0x38(%r11),%xmm13
+ movaps -0x28(%r11),%xmm14
+ movaps -0x18(%r11),%xmm15
.LSEH_end_rsaz_1024_gather5:
___
$code.=<<___;
+ lea (%r11),%rsp
ret
.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
___
@@ -1692,8 +1752,10 @@ $code.=<<___;
.long 0,2,4,6,7,7,7,7
.Lgather_permd:
.long 0,7,1,7,2,7,3,7
-.Lgather_table:
- .byte 0,0,0,0,0,0,0,0, 0xff,0,0,0,0,0,0,0
+.Linc:
+ .long 0,0,0,0, 1,1,1,1
+ .long 2,2,2,2, 3,3,3,3
+ .long 4,4,4,4, 4,4,4,4
.align 64
___
@@ -1821,18 +1883,19 @@ rsaz_se_handler:
.rva rsaz_se_handler
.rva .Lmul_1024_body,.Lmul_1024_epilogue
.LSEH_info_rsaz_1024_gather5:
- .byte 0x01,0x33,0x16,0x00
- .byte 0x36,0xf8,0x09,0x00 #vmovaps 0x90(rsp),xmm15
- .byte 0x31,0xe8,0x08,0x00 #vmovaps 0x80(rsp),xmm14
- .byte 0x2c,0xd8,0x07,0x00 #vmovaps 0x70(rsp),xmm13
- .byte 0x27,0xc8,0x06,0x00 #vmovaps 0x60(rsp),xmm12
- .byte 0x22,0xb8,0x05,0x00 #vmovaps 0x50(rsp),xmm11
- .byte 0x1d,0xa8,0x04,0x00 #vmovaps 0x40(rsp),xmm10
- .byte 0x18,0x98,0x03,0x00 #vmovaps 0x30(rsp),xmm9
- .byte 0x13,0x88,0x02,0x00 #vmovaps 0x20(rsp),xmm8
- .byte 0x0e,0x78,0x01,0x00 #vmovaps 0x10(rsp),xmm7
- .byte 0x09,0x68,0x00,0x00 #vmovaps 0x00(rsp),xmm6
- .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
+ .byte 0x01,0x36,0x17,0x0b
+ .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
+ .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
+ .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
+ .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
+ .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
+ .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
+ .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
+ .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
+ .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
+ .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8
+ .byte 0x00,0xb3,0x00,0x00 # set_frame r11
___
}
diff --git a/src/crypto/bn/asm/rsaz-x86_64.pl b/src/crypto/bn/asm/rsaz-x86_64.pl
index 4113d533..c38bde95 100644..100755
--- a/src/crypto/bn/asm/rsaz-x86_64.pl
+++ b/src/crypto/bn/asm/rsaz-x86_64.pl
@@ -902,9 +902,76 @@ rsaz_512_mul_gather4:
push %r14
push %r15
- mov $pwr, $pwr
- subq \$128+24, %rsp
+ subq \$`128+24+($win64?0xb0:0)`, %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,0xa0(%rsp)
+ movaps %xmm7,0xb0(%rsp)
+ movaps %xmm8,0xc0(%rsp)
+ movaps %xmm9,0xd0(%rsp)
+ movaps %xmm10,0xe0(%rsp)
+ movaps %xmm11,0xf0(%rsp)
+ movaps %xmm12,0x100(%rsp)
+ movaps %xmm13,0x110(%rsp)
+ movaps %xmm14,0x120(%rsp)
+ movaps %xmm15,0x130(%rsp)
+___
+$code.=<<___;
.Lmul_gather4_body:
+ movd $pwr,%xmm8
+ movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
+ movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
+
+ pshufd \$0,%xmm8,%xmm8 # broadcast $power
+ movdqa %xmm1,%xmm7
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..15 to $power
+#
+for($i=0;$i<4;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+ movdqa %xmm7,%xmm`$i+3`
+___
+}
+for(;$i<7;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+___
+}
+$code.=<<___;
+ pcmpeqd %xmm8,%xmm7
+
+ movdqa 16*0($bp),%xmm8
+ movdqa 16*1($bp),%xmm9
+ movdqa 16*2($bp),%xmm10
+ movdqa 16*3($bp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4($bp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5($bp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6($bp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7($bp),%xmm15
+ leaq 128($bp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
___
$code.=<<___ if ($addx);
movl \$0x80100,%r11d
@@ -913,45 +980,38 @@ $code.=<<___ if ($addx);
je .Lmulx_gather
___
$code.=<<___;
- movl 64($bp,$pwr,4), %eax
- movq $out, %xmm0 # off-load arguments
- movl ($bp,$pwr,4), %ebx
- movq $mod, %xmm1
- movq $n0, 128(%rsp)
+ movq %xmm8,%rbx
+
+ movq $n0, 128(%rsp) # off-load arguments
+ movq $out, 128+8(%rsp)
+ movq $mod, 128+16(%rsp)
- shlq \$32, %rax
- or %rax, %rbx
movq ($ap), %rax
movq 8($ap), %rcx
- leaq 128($bp,$pwr,4), %rbp
mulq %rbx # 0 iteration
movq %rax, (%rsp)
movq %rcx, %rax
movq %rdx, %r8
mulq %rbx
- movd (%rbp), %xmm4
addq %rax, %r8
movq 16($ap), %rax
movq %rdx, %r9
adcq \$0, %r9
mulq %rbx
- movd 64(%rbp), %xmm5
addq %rax, %r9
movq 24($ap), %rax
movq %rdx, %r10
adcq \$0, %r10
mulq %rbx
- pslldq \$4, %xmm5
addq %rax, %r10
movq 32($ap), %rax
movq %rdx, %r11
adcq \$0, %r11
mulq %rbx
- por %xmm5, %xmm4
addq %rax, %r11
movq 40($ap), %rax
movq %rdx, %r12
@@ -964,14 +1024,12 @@ $code.=<<___;
adcq \$0, %r13
mulq %rbx
- leaq 128(%rbp), %rbp
addq %rax, %r13
movq 56($ap), %rax
movq %rdx, %r14
adcq \$0, %r14
mulq %rbx
- movq %xmm4, %rbx
addq %rax, %r14
movq ($ap), %rax
movq %rdx, %r15
@@ -983,6 +1041,35 @@ $code.=<<___;
.align 32
.Loop_mul_gather:
+ movdqa 16*0(%rbp),%xmm8
+ movdqa 16*1(%rbp),%xmm9
+ movdqa 16*2(%rbp),%xmm10
+ movdqa 16*3(%rbp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4(%rbp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5(%rbp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6(%rbp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7(%rbp),%xmm15
+ leaq 128(%rbp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,%rbx
+
mulq %rbx
addq %rax, %r8
movq 8($ap), %rax
@@ -991,7 +1078,6 @@ $code.=<<___;
adcq \$0, %r8
mulq %rbx
- movd (%rbp), %xmm4
addq %rax, %r9
movq 16($ap), %rax
adcq \$0, %rdx
@@ -1000,7 +1086,6 @@ $code.=<<___;
adcq \$0, %r9
mulq %rbx
- movd 64(%rbp), %xmm5
addq %rax, %r10
movq 24($ap), %rax
adcq \$0, %rdx
@@ -1009,7 +1094,6 @@ $code.=<<___;
adcq \$0, %r10
mulq %rbx
- pslldq \$4, %xmm5
addq %rax, %r11
movq 32($ap), %rax
adcq \$0, %rdx
@@ -1018,7 +1102,6 @@ $code.=<<___;
adcq \$0, %r11
mulq %rbx
- por %xmm5, %xmm4
addq %rax, %r12
movq 40($ap), %rax
adcq \$0, %rdx
@@ -1043,7 +1126,6 @@ $code.=<<___;
adcq \$0, %r14
mulq %rbx
- movq %xmm4, %rbx
addq %rax, %r15
movq ($ap), %rax
adcq \$0, %rdx
@@ -1051,7 +1133,6 @@ $code.=<<___;
movq %rdx, %r15
adcq \$0, %r15
- leaq 128(%rbp), %rbp
leaq 8(%rdi), %rdi
decl %ecx
@@ -1066,8 +1147,8 @@ $code.=<<___;
movq %r14, 48(%rdi)
movq %r15, 56(%rdi)
- movq %xmm0, $out
- movq %xmm1, %rbp
+ movq 128+8(%rsp), $out
+ movq 128+16(%rsp), %rbp
movq (%rsp), %r8
movq 8(%rsp), %r9
@@ -1085,45 +1166,37 @@ $code.=<<___ if ($addx);
.align 32
.Lmulx_gather:
- mov 64($bp,$pwr,4), %eax
- movq $out, %xmm0 # off-load arguments
- lea 128($bp,$pwr,4), %rbp
- mov ($bp,$pwr,4), %edx
- movq $mod, %xmm1
- mov $n0, 128(%rsp)
+ movq %xmm8,%rdx
+
+ mov $n0, 128(%rsp) # off-load arguments
+ mov $out, 128+8(%rsp)
+ mov $mod, 128+16(%rsp)
- shl \$32, %rax
- or %rax, %rdx
mulx ($ap), %rbx, %r8 # 0 iteration
mov %rbx, (%rsp)
xor %edi, %edi # cf=0, of=0
mulx 8($ap), %rax, %r9
- movd (%rbp), %xmm4
mulx 16($ap), %rbx, %r10
- movd 64(%rbp), %xmm5
adcx %rax, %r8
mulx 24($ap), %rax, %r11
- pslldq \$4, %xmm5
adcx %rbx, %r9
mulx 32($ap), %rbx, %r12
- por %xmm5, %xmm4
adcx %rax, %r10
mulx 40($ap), %rax, %r13
adcx %rbx, %r11
mulx 48($ap), %rbx, %r14
- lea 128(%rbp), %rbp
adcx %rax, %r12
mulx 56($ap), %rax, %r15
- movq %xmm4, %rdx
adcx %rbx, %r13
adcx %rax, %r14
+ .byte 0x67
mov %r8, %rbx
adcx %rdi, %r15 # %rdi is 0
@@ -1132,24 +1205,48 @@ $code.=<<___ if ($addx);
.align 32
.Loop_mulx_gather:
- mulx ($ap), %rax, %r8
+ movdqa 16*0(%rbp),%xmm8
+ movdqa 16*1(%rbp),%xmm9
+ movdqa 16*2(%rbp),%xmm10
+ movdqa 16*3(%rbp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4(%rbp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5(%rbp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6(%rbp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7(%rbp),%xmm15
+ leaq 128(%rbp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,%rdx
+
+ .byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # mulx ($ap), %rax, %r8
adcx %rax, %rbx
adox %r9, %r8
mulx 8($ap), %rax, %r9
- .byte 0x66,0x0f,0x6e,0xa5,0x00,0x00,0x00,0x00 # movd (%rbp), %xmm4
adcx %rax, %r8
adox %r10, %r9
mulx 16($ap), %rax, %r10
- movd 64(%rbp), %xmm5
- lea 128(%rbp), %rbp
adcx %rax, %r9
adox %r11, %r10
.byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11
- pslldq \$4, %xmm5
- por %xmm5, %xmm4
adcx %rax, %r10
adox %r12, %r11
@@ -1163,10 +1260,10 @@ $code.=<<___ if ($addx);
.byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14
adcx %rax, %r13
+ .byte 0x67
adox %r15, %r14
mulx 56($ap), %rax, %r15
- movq %xmm4, %rdx
mov %rbx, 64(%rsp,%rcx,8)
adcx %rax, %r14
adox %rdi, %r15
@@ -1185,10 +1282,10 @@ $code.=<<___ if ($addx);
mov %r14, 64+48(%rsp)
mov %r15, 64+56(%rsp)
- movq %xmm0, $out
- movq %xmm1, %rbp
+ mov 128(%rsp), %rdx # pull arguments
+ mov 128+8(%rsp), $out
+ mov 128+16(%rsp), %rbp
- mov 128(%rsp), %rdx # pull $n0
mov (%rsp), %r8
mov 8(%rsp), %r9
mov 16(%rsp), %r10
@@ -1216,6 +1313,21 @@ $code.=<<___;
call __rsaz_512_subtract
leaq 128+24+48(%rsp), %rax
+___
+$code.=<<___ if ($win64);
+ movaps 0xa0-0xc8(%rax),%xmm6
+ movaps 0xb0-0xc8(%rax),%xmm7
+ movaps 0xc0-0xc8(%rax),%xmm8
+ movaps 0xd0-0xc8(%rax),%xmm9
+ movaps 0xe0-0xc8(%rax),%xmm10
+ movaps 0xf0-0xc8(%rax),%xmm11
+ movaps 0x100-0xc8(%rax),%xmm12
+ movaps 0x110-0xc8(%rax),%xmm13
+ movaps 0x120-0xc8(%rax),%xmm14
+ movaps 0x130-0xc8(%rax),%xmm15
+ lea 0xb0(%rax),%rax
+___
+$code.=<<___;
movq -48(%rax), %r15
movq -40(%rax), %r14
movq -32(%rax), %r13
@@ -1245,7 +1357,7 @@ rsaz_512_mul_scatter4:
mov $pwr, $pwr
subq \$128+24, %rsp
.Lmul_scatter4_body:
- leaq ($tbl,$pwr,4), $tbl
+ leaq ($tbl,$pwr,8), $tbl
movq $out, %xmm0 # off-load arguments
movq $mod, %xmm1
movq $tbl, %xmm2
@@ -1316,30 +1428,14 @@ $code.=<<___;
call __rsaz_512_subtract
- movl %r8d, 64*0($inp) # scatter
- shrq \$32, %r8
- movl %r9d, 64*2($inp)
- shrq \$32, %r9
- movl %r10d, 64*4($inp)
- shrq \$32, %r10
- movl %r11d, 64*6($inp)
- shrq \$32, %r11
- movl %r12d, 64*8($inp)
- shrq \$32, %r12
- movl %r13d, 64*10($inp)
- shrq \$32, %r13
- movl %r14d, 64*12($inp)
- shrq \$32, %r14
- movl %r15d, 64*14($inp)
- shrq \$32, %r15
- movl %r8d, 64*1($inp)
- movl %r9d, 64*3($inp)
- movl %r10d, 64*5($inp)
- movl %r11d, 64*7($inp)
- movl %r12d, 64*9($inp)
- movl %r13d, 64*11($inp)
- movl %r14d, 64*13($inp)
- movl %r15d, 64*15($inp)
+ movq %r8, 128*0($inp) # scatter
+ movq %r9, 128*1($inp)
+ movq %r10, 128*2($inp)
+ movq %r11, 128*3($inp)
+ movq %r12, 128*4($inp)
+ movq %r13, 128*5($inp)
+ movq %r14, 128*6($inp)
+ movq %r15, 128*7($inp)
leaq 128+24+48(%rsp), %rax
movq -48(%rax), %r15
@@ -1943,16 +2039,14 @@ $code.=<<___;
.type rsaz_512_scatter4,\@abi-omnipotent
.align 16
rsaz_512_scatter4:
- leaq ($out,$power,4), $out
+ leaq ($out,$power,8), $out
movl \$8, %r9d
jmp .Loop_scatter
.align 16
.Loop_scatter:
movq ($inp), %rax
leaq 8($inp), $inp
- movl %eax, ($out)
- shrq \$32, %rax
- movl %eax, 64($out)
+ movq %rax, ($out)
leaq 128($out), $out
decl %r9d
jnz .Loop_scatter
@@ -1963,22 +2057,106 @@ rsaz_512_scatter4:
.type rsaz_512_gather4,\@abi-omnipotent
.align 16
rsaz_512_gather4:
- leaq ($inp,$power,4), $inp
+___
+$code.=<<___ if ($win64);
+.LSEH_begin_rsaz_512_gather4:
+ .byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp
+ .byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp)
+ .byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp)
+ .byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp)
+ .byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp)
+ .byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp)
+ .byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp)
+ .byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp)
+ .byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp)
+ .byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp)
+ .byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp)
+___
+$code.=<<___;
+ movd $power,%xmm8
+ movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
+ movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
+
+ pshufd \$0,%xmm8,%xmm8 # broadcast $power
+ movdqa %xmm1,%xmm7
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..15 to $power
+#
+for($i=0;$i<4;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+ movdqa %xmm7,%xmm`$i+3`
+___
+}
+for(;$i<7;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+___
+}
+$code.=<<___;
+ pcmpeqd %xmm8,%xmm7
movl \$8, %r9d
jmp .Loop_gather
.align 16
.Loop_gather:
- movl ($inp), %eax
- movl 64($inp), %r8d
+ movdqa 16*0($inp),%xmm8
+ movdqa 16*1($inp),%xmm9
+ movdqa 16*2($inp),%xmm10
+ movdqa 16*3($inp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4($inp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5($inp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6($inp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7($inp),%xmm15
leaq 128($inp), $inp
- shlq \$32, %r8
- or %r8, %rax
- movq %rax, ($out)
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,($out)
leaq 8($out), $out
decl %r9d
jnz .Loop_gather
+___
+$code.=<<___ if ($win64);
+ movaps 0x00(%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ movaps 0x40(%rsp),%xmm10
+ movaps 0x50(%rsp),%xmm11
+ movaps 0x60(%rsp),%xmm12
+ movaps 0x70(%rsp),%xmm13
+ movaps 0x80(%rsp),%xmm14
+ movaps 0x90(%rsp),%xmm15
+ add \$0xa8,%rsp
+___
+$code.=<<___;
ret
+.LSEH_end_rsaz_512_gather4:
.size rsaz_512_gather4,.-rsaz_512_gather4
+
+.align 64
+.Linc:
+ .long 0,0, 1,1
+ .long 2,2, 2,2
___
}
@@ -2026,6 +2204,18 @@ se_handler:
lea 128+24+48(%rax),%rax
+ lea .Lmul_gather4_epilogue(%rip),%rbx
+ cmp %r10,%rbx
+ jne .Lse_not_in_mul_gather4
+
+ lea 0xb0(%rax),%rax
+
+ lea -48-0xa8(%rax),%rsi
+ lea 512($context),%rdi
+ mov \$20,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lse_not_in_mul_gather4:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -2077,7 +2267,7 @@ se_handler:
pop %rdi
pop %rsi
ret
-.size sqr_handler,.-sqr_handler
+.size se_handler,.-se_handler
.section .pdata
.align 4
@@ -2101,6 +2291,10 @@ se_handler:
.rva .LSEH_end_rsaz_512_mul_by_one
.rva .LSEH_info_rsaz_512_mul_by_one
+ .rva .LSEH_begin_rsaz_512_gather4
+ .rva .LSEH_end_rsaz_512_gather4
+ .rva .LSEH_info_rsaz_512_gather4
+
.section .xdata
.align 8
.LSEH_info_rsaz_512_sqr:
@@ -2123,6 +2317,19 @@ se_handler:
.byte 9,0,0,0
.rva se_handler
.rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_gather4:
+ .byte 0x01,0x46,0x16,0x00
+ .byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
+ .byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
+ .byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
+ .byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
+ .byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
+ .byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
+ .byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
+ .byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
+ .byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
+ .byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
+ .byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8
___
}
diff --git a/src/crypto/bn/asm/x86_64-gcc.c b/src/crypto/bn/asm/x86_64-gcc.c
index 0496b959..214c12af 100644
--- a/src/crypto/bn/asm/x86_64-gcc.c
+++ b/src/crypto/bn/asm/x86_64-gcc.c
@@ -1,9 +1,3 @@
-#include <openssl/bn.h>
-
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
-
-#include "../internal.h"
-
/* x86_64 BIGNUM accelerator version 0.1, December 2002.
*
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
@@ -56,7 +50,13 @@
* machine.
*/
- /* TODO(davidben): Get this file working on Windows x64. */
+#include <openssl/bn.h>
+
+/* TODO(davidben): Get this file working on Windows x64. */
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
+
+#include "../internal.h"
+
#undef mul
#undef mul_add
@@ -186,14 +186,6 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
}
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- BN_ULONG ret, waste;
-
- asm("divq %4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
-
- return ret;
-}
-
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n) {
BN_ULONG ret;
@@ -220,7 +212,6 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
return ret & 1;
}
-#ifndef SIMICS
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n) {
BN_ULONG ret;
@@ -246,65 +237,6 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
return ret & 1;
}
-#else
-/* Simics 1.4<7 has buggy sbbq:-( */
-#define BN_MASK2 0xffffffffffffffffL
-BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
- BN_ULONG t1, t2;
- int c = 0;
-
- if (n <= 0) {
- return (BN_ULONG)0;
- }
-
- for (;;) {
- t1 = a[0];
- t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2) {
- c = (t1 < t2);
- }
- if (--n <= 0) {
- break;
- }
-
- t1 = a[1];
- t2 = b[1];
- r[1] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2) {
- c = (t1 < t2);
- }
- if (--n <= 0) {
- break;
- }
-
- t1 = a[2];
- t2 = b[2];
- r[2] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2) {
- c = (t1 < t2);
- }
- if (--n <= 0) {
- break;
- }
-
- t1 = a[3];
- t2 = b[3];
- r[3] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2) {
- c = (t1 < t2);
- }
- if (--n <= 0) {
- break;
- }
-
- a += 4;
- b += 4;
- r += 4;
- }
- return c;
-}
-#endif
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
@@ -596,4 +528,4 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
r[7] = c2;
}
-#endif /* !NO_ASM && X86_64 && !WINDOWS */
+#endif /* !NO_ASM && X86_64 && __GNUC__ */
diff --git a/src/crypto/bn/asm/x86_64-mont.pl b/src/crypto/bn/asm/x86_64-mont.pl
index 04c4beaf..1ca2b1ef 100644..100755
--- a/src/crypto/bn/asm/x86_64-mont.pl
+++ b/src/crypto/bn/asm/x86_64-mont.pl
@@ -761,100 +761,126 @@ bn_sqr8x_mont:
# 4096. this is done to allow memory disambiguation logic
# do its job.
#
- lea -64(%rsp,$num,4),%r11
+ lea -64(%rsp,$num,2),%r11
mov ($n0),$n0 # *n0
sub $aptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lsqr8x_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
jmp .Lsqr8x_sp_done
.align 32
.Lsqr8x_sp_alt:
- lea 4096-64(,$num,4),%r10 # 4096-frame-4*$num
- lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rsp
.Lsqr8x_sp_done:
and \$-64,%rsp
- mov $num,%r10
+ mov $num,%r10
neg $num
- lea 64(%rsp,$num,2),%r11 # copy of modulus
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.Lsqr8x_body:
- mov $num,$i
- movq %r11, %xmm2 # save pointer to modulus copy
- shr \$3+2,$i
- mov OPENSSL_ia32cap_P+8(%rip),%eax
- jmp .Lsqr8x_copy_n
-
-.align 32
-.Lsqr8x_copy_n:
- movq 8*0($nptr),%xmm0
- movq 8*1($nptr),%xmm1
- movq 8*2($nptr),%xmm3
- movq 8*3($nptr),%xmm4
- lea 8*4($nptr),$nptr
- movdqa %xmm0,16*0(%r11)
- movdqa %xmm1,16*1(%r11)
- movdqa %xmm3,16*2(%r11)
- movdqa %xmm4,16*3(%r11)
- lea 16*4(%r11),%r11
- dec $i
- jnz .Lsqr8x_copy_n
-
+ movq $nptr, %xmm2 # save pointer to modulus
pxor %xmm0,%xmm0
movq $rptr,%xmm1 # save $rptr
movq %r10, %xmm3 # -$num
___
$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%eax
and \$0x80100,%eax
cmp \$0x80100,%eax
jne .Lsqr8x_nox
call bn_sqrx8x_internal # see x86_64-mont5 module
-
- pxor %xmm0,%xmm0
- lea 48(%rsp),%rax
- lea 64(%rsp,$num,2),%rdx
- shr \$3+2,$num
- mov 40(%rsp),%rsi # restore %rsp
- jmp .Lsqr8x_zero
+ # %rax top-most carry
+ # %rbp nptr
+ # %rcx -8*num
+ # %r8 end of tp[2*num]
+ lea (%r8,%rcx),%rbx
+ mov %rcx,$num
+ mov %rcx,%rdx
+ movq %xmm1,$rptr
+ sar \$3+2,%rcx # %cf=0
+ jmp .Lsqr8x_sub
.align 32
.Lsqr8x_nox:
___
$code.=<<___;
call bn_sqr8x_internal # see x86_64-mont5 module
+ # %rax top-most carry
+ # %rbp nptr
+ # %r8 -8*num
+ # %rdi end of tp[2*num]
+ lea (%rdi,$num),%rbx
+ mov $num,%rcx
+ mov $num,%rdx
+ movq %xmm1,$rptr
+ sar \$3+2,%rcx # %cf=0
+ jmp .Lsqr8x_sub
+.align 32
+.Lsqr8x_sub:
+ mov 8*0(%rbx),%r12
+ mov 8*1(%rbx),%r13
+ mov 8*2(%rbx),%r14
+ mov 8*3(%rbx),%r15
+ lea 8*4(%rbx),%rbx
+ sbb 8*0(%rbp),%r12
+ sbb 8*1(%rbp),%r13
+ sbb 8*2(%rbp),%r14
+ sbb 8*3(%rbp),%r15
+ lea 8*4(%rbp),%rbp
+ mov %r12,8*0($rptr)
+ mov %r13,8*1($rptr)
+ mov %r14,8*2($rptr)
+ mov %r15,8*3($rptr)
+ lea 8*4($rptr),$rptr
+ inc %rcx # preserves %cf
+ jnz .Lsqr8x_sub
+
+ sbb \$0,%rax # top-most carry
+ lea (%rbx,$num),%rbx # rewind
+ lea ($rptr,$num),$rptr # rewind
+
+ movq %rax,%xmm1
pxor %xmm0,%xmm0
- lea 48(%rsp),%rax
- lea 64(%rsp,$num,2),%rdx
- shr \$3+2,$num
+ pshufd \$0,%xmm1,%xmm1
mov 40(%rsp),%rsi # restore %rsp
- jmp .Lsqr8x_zero
+ jmp .Lsqr8x_cond_copy
.align 32
-.Lsqr8x_zero:
- movdqa %xmm0,16*0(%rax) # wipe t
- movdqa %xmm0,16*1(%rax)
- movdqa %xmm0,16*2(%rax)
- movdqa %xmm0,16*3(%rax)
- lea 16*4(%rax),%rax
- movdqa %xmm0,16*0(%rdx) # wipe n
- movdqa %xmm0,16*1(%rdx)
- movdqa %xmm0,16*2(%rdx)
- movdqa %xmm0,16*3(%rdx)
- lea 16*4(%rdx),%rdx
- dec $num
- jnz .Lsqr8x_zero
+.Lsqr8x_cond_copy:
+ movdqa 16*0(%rbx),%xmm2
+ movdqa 16*1(%rbx),%xmm3
+ lea 16*2(%rbx),%rbx
+ movdqu 16*0($rptr),%xmm4
+ movdqu 16*1($rptr),%xmm5
+ lea 16*2($rptr),$rptr
+ movdqa %xmm0,-16*2(%rbx) # zero tp
+ movdqa %xmm0,-16*1(%rbx)
+ movdqa %xmm0,-16*2(%rbx,%rdx)
+ movdqa %xmm0,-16*1(%rbx,%rdx)
+ pcmpeqd %xmm1,%xmm0
+ pand %xmm1,%xmm2
+ pand %xmm1,%xmm3
+ pand %xmm0,%xmm4
+ pand %xmm0,%xmm5
+ pxor %xmm0,%xmm0
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+ movdqu %xmm4,-16*2($rptr)
+ movdqu %xmm5,-16*1($rptr)
+ add \$32,$num
+ jnz .Lsqr8x_cond_copy
mov \$1,%rax
mov -48(%rsi),%r15
@@ -1121,64 +1147,75 @@ $code.=<<___;
adc $zero,%r15 # modulo-scheduled
sub 0*8($tptr),$zero # pull top-most carry
adc %r15,%r14
- mov -8($nptr),$mi
sbb %r15,%r15 # top-most carry
mov %r14,-1*8($tptr)
cmp 16(%rsp),$bptr
jne .Lmulx4x_outer
- sub %r14,$mi # compare top-most words
- sbb $mi,$mi
- or $mi,%r15
-
- neg $num
- xor %rdx,%rdx
+ lea 64(%rsp),$tptr
+ sub $num,$nptr # rewind $nptr
+ neg %r15
+ mov $num,%rdx
+ shr \$3+2,$num # %cf=0
mov 32(%rsp),$rptr # restore rp
+ jmp .Lmulx4x_sub
+
+.align 32
+.Lmulx4x_sub:
+ mov 8*0($tptr),%r11
+ mov 8*1($tptr),%r12
+ mov 8*2($tptr),%r13
+ mov 8*3($tptr),%r14
+ lea 8*4($tptr),$tptr
+ sbb 8*0($nptr),%r11
+ sbb 8*1($nptr),%r12
+ sbb 8*2($nptr),%r13
+ sbb 8*3($nptr),%r14
+ lea 8*4($nptr),$nptr
+ mov %r11,8*0($rptr)
+ mov %r12,8*1($rptr)
+ mov %r13,8*2($rptr)
+ mov %r14,8*3($rptr)
+ lea 8*4($rptr),$rptr
+ dec $num # preserves %cf
+ jnz .Lmulx4x_sub
+
+ sbb \$0,%r15 # top-most carry
lea 64(%rsp),$tptr
+ sub %rdx,$rptr # rewind
+ movq %r15,%xmm1
pxor %xmm0,%xmm0
- mov 0*8($nptr,$num),%r8
- mov 1*8($nptr,$num),%r9
- neg %r8
- jmp .Lmulx4x_sub_entry
+ pshufd \$0,%xmm1,%xmm1
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lmulx4x_cond_copy
.align 32
-.Lmulx4x_sub:
- mov 0*8($nptr,$num),%r8
- mov 1*8($nptr,$num),%r9
- not %r8
-.Lmulx4x_sub_entry:
- mov 2*8($nptr,$num),%r10
- not %r9
- and %r15,%r8
- mov 3*8($nptr,$num),%r11
- not %r10
- and %r15,%r9
- not %r11
- and %r15,%r10
- and %r15,%r11
-
- neg %rdx # mov %rdx,%cf
- adc 0*8($tptr),%r8
- adc 1*8($tptr),%r9
- movdqa %xmm0,($tptr)
- adc 2*8($tptr),%r10
- adc 3*8($tptr),%r11
- movdqa %xmm0,16($tptr)
- lea 4*8($tptr),$tptr
- sbb %rdx,%rdx # mov %cf,%rdx
-
- mov %r8,0*8($rptr)
- mov %r9,1*8($rptr)
- mov %r10,2*8($rptr)
- mov %r11,3*8($rptr)
- lea 4*8($rptr),$rptr
+.Lmulx4x_cond_copy:
+ movdqa 16*0($tptr),%xmm2
+ movdqa 16*1($tptr),%xmm3
+ lea 16*2($tptr),$tptr
+ movdqu 16*0($rptr),%xmm4
+ movdqu 16*1($rptr),%xmm5
+ lea 16*2($rptr),$rptr
+ movdqa %xmm0,-16*2($tptr) # zero tp
+ movdqa %xmm0,-16*1($tptr)
+ pcmpeqd %xmm1,%xmm0
+ pand %xmm1,%xmm2
+ pand %xmm1,%xmm3
+ pand %xmm0,%xmm4
+ pand %xmm0,%xmm5
+ pxor %xmm0,%xmm0
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+ movdqu %xmm4,-16*2($rptr)
+ movdqu %xmm5,-16*1($rptr)
+ sub \$32,%rdx
+ jnz .Lmulx4x_cond_copy
- add \$32,$num
- jnz .Lmulx4x_sub
+ mov %rdx,($tptr)
- mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
mov -48(%rsi),%r15
mov -40(%rsi),%r14
diff --git a/src/crypto/bn/asm/x86_64-mont5.pl b/src/crypto/bn/asm/x86_64-mont5.pl
index 3c5a8fc9..ced3acba 100644..100755
--- a/src/crypto/bn/asm/x86_64-mont5.pl
+++ b/src/crypto/bn/asm/x86_64-mont5.pl
@@ -86,58 +86,111 @@ $code.=<<___;
.Lmul_enter:
mov ${num}d,${num}d
mov %rsp,%rax
- mov `($win64?56:8)`(%rsp),%r10d # load 7th argument
+ movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument
+ lea .Linc(%rip),%r10
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
+
lea 2($num),%r11
neg %r11
- lea (%rsp,%r11,8),%rsp # tp=alloca(8*(num+2))
+ lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8)
and \$-1024,%rsp # minimize TLB usage
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.Lmul_body:
- mov $bp,%r12 # reassign $bp
+ lea 128($bp),%r12 # reassign $bp (+size optimization)
___
$bp="%r12";
$STRIDE=2**5*8; # 5 is "window size"
$N=$STRIDE/4; # should match cache line size
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96($bp,%r11,8),$bp # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
-
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
+ movdqa 0(%r10),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%r10),%xmm1 # 00000002000000020000000200000002
+ lea 24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization)
+ and \$-16,%r10
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+ .byte 0x67
+ movdqa %xmm4,%xmm3
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($k+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($k+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($k+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($k+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($k+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
+ .byte 0x67
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($k+1)+112`(%r10)
+
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($k+2)+112`(%r10)
+ pand `16*($k+0)-128`($bp),%xmm0 # while it's still in register
+
+ pand `16*($k+1)-128`($bp),%xmm1
+ pand `16*($k+2)-128`($bp),%xmm2
+ movdqa %xmm3,`16*($k+3)+112`(%r10)
+ pand `16*($k+3)-128`($bp),%xmm3
por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+ movdqa `16*($k+0)-128`($bp),%xmm4
+ movdqa `16*($k+1)-128`($bp),%xmm5
+ movdqa `16*($k+2)-128`($bp),%xmm2
+ pand `16*($k+0)+112`(%r10),%xmm4
+ movdqa `16*($k+3)-128`($bp),%xmm3
+ pand `16*($k+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($k+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($k+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ por %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
movq %xmm0,$m0 # m0=bp[0]
mov ($n0),$n0 # pull n0[0] value
@@ -146,29 +199,14 @@ $code.=<<___;
xor $i,$i # i=0
xor $j,$j # j=0
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
-
mov $n0,$m1
mulq $m0 # ap[0]*bp[0]
mov %rax,$lo0
mov ($np),%rax
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
-
imulq $lo0,$m1 # "tp[0]"*n0
mov %rdx,$hi0
- por %xmm2,%xmm0
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$lo0 # discarded
mov 8($ap),%rax
@@ -199,16 +237,14 @@ $code.=<<___;
mulq $m1 # np[j]*m1
cmp $num,$j
- jne .L1st
-
- movq %xmm0,$m0 # bp[1]
+ jne .L1st # note that upon exit $j==$num, so
+ # they can be used interchangeably
add %rax,$hi1
- mov ($ap),%rax # ap[0]
adc \$0,%rdx
add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
adc \$0,%rdx
- mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov $hi1,-16(%rsp,$num,8) # tp[num-1]
mov %rdx,$hi1
mov $lo0,$hi0
@@ -222,33 +258,48 @@ $code.=<<___;
jmp .Louter
.align 16
.Louter:
+ lea 24+128(%rsp,$num,8),%rdx # where 256-byte mask is (+size optimization)
+ and \$-16,%rdx
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($k=0;$k<$STRIDE/16;$k+=4) {
+$code.=<<___;
+ movdqa `16*($k+0)-128`($bp),%xmm0
+ movdqa `16*($k+1)-128`($bp),%xmm1
+ movdqa `16*($k+2)-128`($bp),%xmm2
+ movdqa `16*($k+3)-128`($bp),%xmm3
+ pand `16*($k+0)-128`(%rdx),%xmm0
+ pand `16*($k+1)-128`(%rdx),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($k+2)-128`(%rdx),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($k+3)-128`(%rdx),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bp),$bp
+
+ mov ($ap),%rax # ap[0]
+ movq %xmm0,$m0 # m0=bp[i]
+
xor $j,$j # j=0
mov $n0,$m1
mov (%rsp),$lo0
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
-
mulq $m0 # ap[0]*bp[i]
add %rax,$lo0 # ap[0]*bp[i]+tp[0]
mov ($np),%rax
adc \$0,%rdx
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
-
imulq $lo0,$m1 # tp[0]*n0
mov %rdx,$hi0
- por %xmm2,%xmm0
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$lo0 # discarded
mov 8($ap),%rax
@@ -282,17 +333,14 @@ $code.=<<___;
mulq $m1 # np[j]*m1
cmp $num,$j
- jne .Linner
-
- movq %xmm0,$m0 # bp[i+1]
-
+ jne .Linner # note that upon exit $j==$num, so
+ # they can be used interchangeably
add %rax,$hi1
- mov ($ap),%rax # ap[0]
adc \$0,%rdx
add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
- mov (%rsp,$j,8),$lo0
+ mov (%rsp,$num,8),$lo0
adc \$0,%rdx
- mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov $hi1,-16(%rsp,$num,8) # tp[num-1]
mov %rdx,$hi1
xor %rdx,%rdx
@@ -338,12 +386,7 @@ $code.=<<___;
mov 8(%rsp,$num,8),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -365,8 +408,8 @@ bn_mul4x_mont_gather5:
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
je .Lmulx4x_enter
___
$code.=<<___;
@@ -378,39 +421,34 @@ $code.=<<___;
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
+
.byte 0x67
- mov ${num}d,%r10d
- shl \$3,${num}d
- shl \$3+2,%r10d # 4*$num
+ shl \$3,${num}d # convert $num to bytes
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num # -$num
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic. [excessive frame is allocated in order
- # to allow bn_from_mont8x to clear it.]
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra [num] is allocated in order
+ # to align with bn_power5's frame, which is cleansed after
+ # completing exponentiation. Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $ap,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmul4xsp_alt
- sub %r11,%rsp # align with $ap
- lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ sub %r11,%rsp # align with $rp
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lmul4xsp_done
.align 32
.Lmul4xsp_alt:
- lea 4096-64(,$num,2),%r10
- lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -426,12 +464,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -446,9 +479,10 @@ $code.=<<___;
.type mul4x_internal,\@abi-omnipotent
.align 32
mul4x_internal:
- shl \$5,$num
- mov `($win64?56:8)`(%rax),%r10d # load 7th argument
- lea 256(%rdx,$num),%r13
+ shl \$5,$num # $num was in bytes
+ movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument, index
+ lea .Linc(%rip),%rax
+ lea 128(%rdx,$num),%r13 # end of powers table (+size optimization)
shr \$5,$num # restore $num
___
$bp="%r12";
@@ -456,44 +490,92 @@ ___
$N=$STRIDE/4; # should match cache line size
$tp=$i;
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96(%rdx,%r11,8),$bp # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- add \$7,%r11
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
- and \$7,%r11
-
- movq `0*$STRIDE/4-96`($bp),%xmm0
- lea $STRIDE($bp),$tp # borrow $tp
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- .byte 0x67
- por %xmm1,%xmm0
- movq `0*$STRIDE/4-96`($tp),%xmm1
- .byte 0x67
- pand %xmm7,%xmm3
- .byte 0x67
- por %xmm2,%xmm0
- movq `1*$STRIDE/4-96`($tp),%xmm2
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 88-112(%rsp,$num),%r10 # place the mask after tp[num+1] (+ICache optimization)
+ lea 128(%rdx),$bp # size optimization
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ .byte 0x67,0x67
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
.byte 0x67
- pand %xmm4,%xmm1
+ movdqa %xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
.byte 0x67
- por %xmm3,%xmm0
- movq `2*$STRIDE/4-96`($tp),%xmm3
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ pand `16*($i+0)-128`($bp),%xmm0 # while it's still in register
+
+ pand `16*($i+1)-128`($bp),%xmm1
+ pand `16*($i+2)-128`($bp),%xmm2
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ pand `16*($i+3)-128`($bp),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bp),%xmm4
+ movdqa `16*($i+1)-128`($bp),%xmm5
+ movdqa `16*($i+2)-128`($bp),%xmm2
+ pand `16*($i+0)+112`(%r10),%xmm4
+ movdqa `16*($i+3)-128`($bp),%xmm3
+ pand `16*($i+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($i+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($i+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ por %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
+ lea $STRIDE($bp),$bp
movq %xmm0,$m0 # m0=bp[0]
- movq `3*$STRIDE/4-96`($tp),%xmm0
+
mov %r13,16+8(%rsp) # save end of b[num]
mov $rp, 56+8(%rsp) # save $rp
@@ -507,26 +589,10 @@ $code.=<<___;
mov %rax,$A[0]
mov ($np),%rax
- pand %xmm5,%xmm2
- pand %xmm6,%xmm3
- por %xmm2,%xmm1
-
imulq $A[0],$m1 # "tp[0]"*n0
- ##############################################################
- # $tp is chosen so that writing to top-most element of the
- # vector occurs just "above" references to powers table,
- # "above" modulo cache-line size, which effectively precludes
- # possibility of memory disambiguation logic failure when
- # accessing the table.
- #
- lea 64+8(%rsp,%r11,8),$tp
+ lea 64+8(%rsp),$tp
mov %rdx,$A[1]
- pand %xmm7,%xmm0
- por %xmm3,%xmm1
- lea 2*$STRIDE($bp),$bp
- por %xmm1,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$A[0] # discarded
mov 8($ap,$num),%rax
@@ -535,7 +601,7 @@ $code.=<<___;
mulq $m0
add %rax,$A[1]
- mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ mov 8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -545,7 +611,7 @@ $code.=<<___;
adc \$0,%rdx
add $A[1],$N[1]
lea 4*8($num),$j # j=4
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[1],($tp)
mov %rdx,$N[0]
@@ -555,7 +621,7 @@ $code.=<<___;
.L1st4x:
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
lea 32($tp),$tp
adc \$0,%rdx
mov %rdx,$A[1]
@@ -571,7 +637,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -586,7 +652,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov 16*0($np),%rax
+ mov 8*0($np),%rax
adc \$0,%rdx
mov %rdx,$A[1]
@@ -601,7 +667,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov 16*1($np),%rax
+ mov 8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -610,7 +676,7 @@ $code.=<<___;
mov 16($ap,$j),%rax
adc \$0,%rdx
add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[1],($tp) # tp[j-1]
mov %rdx,$N[0]
@@ -620,7 +686,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
lea 32($tp),$tp
adc \$0,%rdx
mov %rdx,$A[1]
@@ -636,7 +702,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -649,8 +715,7 @@ $code.=<<___;
mov $N[1],-16($tp) # tp[j-1]
mov %rdx,$N[0]
- movq %xmm0,$m0 # bp[1]
- lea ($np,$num,2),$np # rewind $np
+ lea ($np,$num),$np # rewind $np
xor $N[1],$N[1]
add $A[0],$N[0]
@@ -661,6 +726,33 @@ $code.=<<___;
.align 32
.Louter4x:
+ lea 16+128($tp),%rdx # where 256-byte mask is (+size optimization)
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bp),%xmm0
+ movdqa `16*($i+1)-128`($bp),%xmm1
+ movdqa `16*($i+2)-128`($bp),%xmm2
+ movdqa `16*($i+3)-128`($bp),%xmm3
+ pand `16*($i+0)-128`(%rdx),%xmm0
+ pand `16*($i+1)-128`(%rdx),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)-128`(%rdx),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)-128`(%rdx),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bp),$bp
+ movq %xmm0,$m0 # m0=bp[i]
+
mov ($tp,$num),$A[0]
mov $n0,$m1
mulq $m0 # ap[0]*bp[i]
@@ -668,25 +760,11 @@ $code.=<<___;
mov ($np),%rax
adc \$0,%rdx
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
-
imulq $A[0],$m1 # tp[0]*n0
- .byte 0x67
mov %rdx,$A[1]
mov $N[1],($tp) # store upmost overflow bit
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
- por %xmm2,%xmm0
lea ($tp,$num),$tp # rewind $tp
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
mulq $m1 # np[0]*m1
add %rax,$A[0] # "$N[0]", discarded
@@ -696,7 +774,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ mov 8*1($np),%rax
adc \$0,%rdx
add 8($tp),$A[1] # +tp[1]
adc \$0,%rdx
@@ -708,7 +786,7 @@ $code.=<<___;
adc \$0,%rdx
add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j]
lea 4*8($num),$j # j=4
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov %rdx,$N[0]
jmp .Linner4x
@@ -717,7 +795,7 @@ $code.=<<___;
.Linner4x:
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
adc \$0,%rdx
add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
lea 32($tp),$tp
@@ -735,7 +813,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
add -8($tp),$A[1]
adc \$0,%rdx
@@ -752,7 +830,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov 16*0($np),%rax
+ mov 8*0($np),%rax
adc \$0,%rdx
add ($tp),$A[0] # ap[j]*bp[i]+tp[j]
adc \$0,%rdx
@@ -769,7 +847,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov 16*1($np),%rax
+ mov 8*1($np),%rax
adc \$0,%rdx
add 8($tp),$A[1]
adc \$0,%rdx
@@ -780,7 +858,7 @@ $code.=<<___;
mov 16($ap,$j),%rax
adc \$0,%rdx
add $A[1],$N[1]
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[0],-8($tp) # tp[j-1]
mov %rdx,$N[0]
@@ -790,7 +868,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
adc \$0,%rdx
add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
lea 32($tp),$tp
@@ -809,7 +887,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
mov $m1,%rax
- mov -16*1($np),$m1
+ mov -8*1($np),$m1
adc \$0,%rdx
add -8($tp),$A[1]
adc \$0,%rdx
@@ -824,9 +902,8 @@ $code.=<<___;
mov $N[0],-24($tp) # tp[j-1]
mov %rdx,$N[0]
- movq %xmm0,$m0 # bp[i+1]
mov $N[1],-16($tp) # tp[j-1]
- lea ($np,$num,2),$np # rewind $np
+ lea ($np,$num),$np # rewind $np
xor $N[1],$N[1]
add $A[0],$N[0]
@@ -840,16 +917,23 @@ $code.=<<___;
___
if (1) {
$code.=<<___;
+ xor %rax,%rax
sub $N[0],$m1 # compare top-most words
adc $j,$j # $j is zero
or $j,$N[1]
- xor \$1,$N[1]
+ sub $N[1],%rax # %rax=-$N[1]
lea ($tp,$num),%rbx # tptr in .sqr4x_sub
- lea ($np,$N[1],8),%rbp # nptr in .sqr4x_sub
+ mov ($np),%r12
+ lea ($np),%rbp # nptr in .sqr4x_sub
mov %r9,%rcx
- sar \$3+2,%rcx # cf=0
+ sar \$3+2,%rcx
mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub
- jmp .Lsqr4x_sub
+ dec %r12 # so that after 'not' we get -n[0]
+ xor %r10,%r10
+ mov 8*1(%rbp),%r13
+ mov 8*2(%rbp),%r14
+ mov 8*3(%rbp),%r15
+ jmp .Lsqr4x_sub_entry
___
} else {
my @ri=("%rax",$bp,$m0,$m1);
@@ -916,8 +1000,8 @@ bn_power5:
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
je .Lpowerx5_enter
___
$code.=<<___;
@@ -928,38 +1012,32 @@ $code.=<<___;
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10d # 3*$num
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwr_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lpwr_sp_done
.align 32
.Lpwr_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -981,16 +1059,21 @@ $code.=<<___;
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.Lpower5_body:
- movq $rptr,%xmm1 # save $rptr
+ movq $rptr,%xmm1 # save $rptr, used in sqr8x
movq $nptr,%xmm2 # save $nptr
- movq %r10, %xmm3 # -$num
+ movq %r10, %xmm3 # -$num, used in sqr8x
movq $bptr,%xmm4
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
movq %xmm2,$nptr
movq %xmm4,$bptr
@@ -1551,9 +1634,9 @@ my ($nptr,$tptr,$carry,$m0)=("%rbp","%rdi","%rsi","%rbx");
$code.=<<___;
movq %xmm2,$nptr
-sqr8x_reduction:
+__bn_sqr8x_reduction:
xor %rax,%rax
- lea ($nptr,$num,2),%rcx # end of n[]
+ lea ($nptr,$num),%rcx # end of n[]
lea 48+8(%rsp,$num,2),%rdx # end of t[] buffer
mov %rcx,0+8(%rsp)
lea 48+8(%rsp,$num),$tptr # end of initial t[] window
@@ -1579,21 +1662,21 @@ sqr8x_reduction:
.byte 0x67
mov $m0,%r8
imulq 32+8(%rsp),$m0 # n0*a[0]
- mov 16*0($nptr),%rax # n[0]
+ mov 8*0($nptr),%rax # n[0]
mov \$8,%ecx
jmp .L8x_reduce
.align 32
.L8x_reduce:
mulq $m0
- mov 16*1($nptr),%rax # n[1]
+ mov 8*1($nptr),%rax # n[1]
neg %r8
mov %rdx,%r8
adc \$0,%r8
mulq $m0
add %rax,%r9
- mov 16*2($nptr),%rax
+ mov 8*2($nptr),%rax
adc \$0,%rdx
add %r9,%r8
mov $m0,48-8+8(%rsp,%rcx,8) # put aside n0*a[i]
@@ -1602,7 +1685,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r10
- mov 16*3($nptr),%rax
+ mov 8*3($nptr),%rax
adc \$0,%rdx
add %r10,%r9
mov 32+8(%rsp),$carry # pull n0, borrow $carry
@@ -1611,7 +1694,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r11
- mov 16*4($nptr),%rax
+ mov 8*4($nptr),%rax
adc \$0,%rdx
imulq %r8,$carry # modulo-scheduled
add %r11,%r10
@@ -1620,7 +1703,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r12
- mov 16*5($nptr),%rax
+ mov 8*5($nptr),%rax
adc \$0,%rdx
add %r12,%r11
mov %rdx,%r12
@@ -1628,7 +1711,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r13
- mov 16*6($nptr),%rax
+ mov 8*6($nptr),%rax
adc \$0,%rdx
add %r13,%r12
mov %rdx,%r13
@@ -1636,7 +1719,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r14
- mov 16*7($nptr),%rax
+ mov 8*7($nptr),%rax
adc \$0,%rdx
add %r14,%r13
mov %rdx,%r14
@@ -1645,7 +1728,7 @@ sqr8x_reduction:
mulq $m0
mov $carry,$m0 # n0*a[i]
add %rax,%r15
- mov 16*0($nptr),%rax # n[0]
+ mov 8*0($nptr),%rax # n[0]
adc \$0,%rdx
add %r15,%r14
mov %rdx,%r15
@@ -1654,7 +1737,7 @@ sqr8x_reduction:
dec %ecx
jnz .L8x_reduce
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
xor %rax,%rax
mov 8+8(%rsp),%rdx # pull end of t[]
cmp 0+8(%rsp),$nptr # end of n[]?
@@ -1673,21 +1756,21 @@ sqr8x_reduction:
mov 48+56+8(%rsp),$m0 # pull n0*a[0]
mov \$8,%ecx
- mov 16*0($nptr),%rax
+ mov 8*0($nptr),%rax
jmp .L8x_tail
.align 32
.L8x_tail:
mulq $m0
add %rax,%r8
- mov 16*1($nptr),%rax
+ mov 8*1($nptr),%rax
mov %r8,($tptr) # save result
mov %rdx,%r8
adc \$0,%r8
mulq $m0
add %rax,%r9
- mov 16*2($nptr),%rax
+ mov 8*2($nptr),%rax
adc \$0,%rdx
add %r9,%r8
lea 8($tptr),$tptr # $tptr++
@@ -1696,7 +1779,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r10
- mov 16*3($nptr),%rax
+ mov 8*3($nptr),%rax
adc \$0,%rdx
add %r10,%r9
mov %rdx,%r10
@@ -1704,7 +1787,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r11
- mov 16*4($nptr),%rax
+ mov 8*4($nptr),%rax
adc \$0,%rdx
add %r11,%r10
mov %rdx,%r11
@@ -1712,7 +1795,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r12
- mov 16*5($nptr),%rax
+ mov 8*5($nptr),%rax
adc \$0,%rdx
add %r12,%r11
mov %rdx,%r12
@@ -1720,7 +1803,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r13
- mov 16*6($nptr),%rax
+ mov 8*6($nptr),%rax
adc \$0,%rdx
add %r13,%r12
mov %rdx,%r13
@@ -1728,7 +1811,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r14
- mov 16*7($nptr),%rax
+ mov 8*7($nptr),%rax
adc \$0,%rdx
add %r14,%r13
mov %rdx,%r14
@@ -1739,14 +1822,14 @@ sqr8x_reduction:
add %rax,%r15
adc \$0,%rdx
add %r15,%r14
- mov 16*0($nptr),%rax # pull n[0]
+ mov 8*0($nptr),%rax # pull n[0]
mov %rdx,%r15
adc \$0,%r15
dec %ecx
jnz .L8x_tail
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
mov 8+8(%rsp),%rdx # pull end of t[]
cmp 0+8(%rsp),$nptr # end of n[]?
jae .L8x_tail_done # break out of loop
@@ -1792,7 +1875,7 @@ sqr8x_reduction:
adc 8*6($tptr),%r14
adc 8*7($tptr),%r15
adc \$0,%rax # top-most carry
- mov -16($nptr),%rcx # np[num-1]
+ mov -8($nptr),%rcx # np[num-1]
xor $carry,$carry
movq %xmm2,$nptr # restore $nptr
@@ -1810,6 +1893,8 @@ sqr8x_reduction:
cmp %rdx,$tptr # end of t[]?
jb .L8x_reduction_loop
+ ret
+.size bn_sqr8x_internal,.-bn_sqr8x_internal
___
}
##############################################################
@@ -1818,48 +1903,62 @@ ___
{
my ($tptr,$nptr)=("%rbx","%rbp");
$code.=<<___;
- #xor %rsi,%rsi # %rsi was $carry above
- sub %r15,%rcx # compare top-most words
+.type __bn_post4x_internal,\@abi-omnipotent
+.align 32
+__bn_post4x_internal:
+ mov 8*0($nptr),%r12
lea (%rdi,$num),$tptr # %rdi was $tptr above
- adc %rsi,%rsi
mov $num,%rcx
- or %rsi,%rax
movq %xmm1,$rptr # restore $rptr
- xor \$1,%rax
+ neg %rax
movq %xmm1,$aptr # prepare for back-to-back call
- lea ($nptr,%rax,8),$nptr
- sar \$3+2,%rcx # cf=0
- jmp .Lsqr4x_sub
+ sar \$3+2,%rcx
+ dec %r12 # so that after 'not' we get -n[0]
+ xor %r10,%r10
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+ jmp .Lsqr4x_sub_entry
-.align 32
+.align 16
.Lsqr4x_sub:
- .byte 0x66
- mov 8*0($tptr),%r12
- mov 8*1($tptr),%r13
- sbb 16*0($nptr),%r12
- mov 8*2($tptr),%r14
- sbb 16*1($nptr),%r13
- mov 8*3($tptr),%r15
- lea 8*4($tptr),$tptr
- sbb 16*2($nptr),%r14
+ mov 8*0($nptr),%r12
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+.Lsqr4x_sub_entry:
+ lea 8*4($nptr),$nptr
+ not %r12
+ not %r13
+ not %r14
+ not %r15
+ and %rax,%r12
+ and %rax,%r13
+ and %rax,%r14
+ and %rax,%r15
+
+ neg %r10 # mov %r10,%cf
+ adc 8*0($tptr),%r12
+ adc 8*1($tptr),%r13
+ adc 8*2($tptr),%r14
+ adc 8*3($tptr),%r15
mov %r12,8*0($rptr)
- sbb 16*3($nptr),%r15
- lea 16*4($nptr),$nptr
+ lea 8*4($tptr),$tptr
mov %r13,8*1($rptr)
+ sbb %r10,%r10 # mov %cf,%r10
mov %r14,8*2($rptr)
mov %r15,8*3($rptr)
lea 8*4($rptr),$rptr
inc %rcx # pass %cf
jnz .Lsqr4x_sub
-___
-}
-$code.=<<___;
+
mov $num,%r10 # prepare for back-to-back call
neg $num # restore $num
ret
-.size bn_sqr8x_internal,.-bn_sqr8x_internal
+.size __bn_post4x_internal,.-__bn_post4x_internal
___
+}
{
$code.=<<___;
.globl bn_from_montgomery
@@ -1883,39 +1982,32 @@ bn_from_mont8x:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). The stack is allocated to aligned with
+ # bn_power5's frame, and as bn_from_montgomery happens to be
+ # last operation, we use the opportunity to cleanse it.
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lfrom_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lfrom_sp_done
.align 32
.Lfrom_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -1969,12 +2061,13 @@ $code.=<<___;
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
jne .Lfrom_mont_nox
lea (%rax,$num),$rptr
- call sqrx8x_reduction
+ call __bn_sqrx8x_reduction
+ call __bn_postx4x_internal
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
@@ -1985,7 +2078,8 @@ $code.=<<___ if ($addx);
.Lfrom_mont_nox:
___
$code.=<<___;
- call sqr8x_reduction
+ call __bn_sqr8x_reduction
+ call __bn_post4x_internal
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
@@ -2025,7 +2119,6 @@ $code.=<<___;
.align 32
bn_mulx4x_mont_gather5:
.Lmulx4x_enter:
- .byte 0x67
mov %rsp,%rax
push %rbx
push %rbp
@@ -2033,40 +2126,33 @@ bn_mulx4x_mont_gather5:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num # -$num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers a[num], ret[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic. [excessive frame is allocated in order
- # to allow bn_from_mont8x to clear it.]
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra [num] is allocated in order
+ # to align with bn_power5's frame, which is cleansed after
+ # completing exponentiation. Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $ap,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmulx4xsp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lmulx4xsp_done
-.align 32
.Lmulx4xsp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -2092,12 +2178,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -2112,14 +2193,16 @@ $code.=<<___;
.type mulx4x_internal,\@abi-omnipotent
.align 32
mulx4x_internal:
- .byte 0x4c,0x89,0x8c,0x24,0x08,0x00,0x00,0x00 # mov $num,8(%rsp) # save -$num
- .byte 0x67
+ mov $num,8(%rsp) # save -$num (it was in bytes)
+ mov $num,%r10
neg $num # restore $num
shl \$5,$num
- lea 256($bp,$num),%r13
+ neg %r10 # restore $num
+ lea 128($bp,$num),%r13 # end of powers table (+size optimization)
shr \$5+5,$num
- mov `($win64?56:8)`(%rax),%r10d # load 7th argument
+ movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument
sub \$1,$num
+ lea .Linc(%rip),%rax
mov %r13,16+8(%rsp) # end of b[num]
mov $num,24+8(%rsp) # inner counter
mov $rp, 56+8(%rsp) # save $rp
@@ -2130,52 +2213,92 @@ my $rptr=$bptr;
my $STRIDE=2**5*8; # 5 is "window size"
my $N=$STRIDE/4; # should match cache line size
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96($bp,%r11,8),$bptr # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- add \$7,%r11
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
- and \$7,%r11
-
- movq `0*$STRIDE/4-96`($bptr),%xmm0
- lea $STRIDE($bptr),$tptr # borrow $tptr
- movq `1*$STRIDE/4-96`($bptr),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bptr),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bptr),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- movq `0*$STRIDE/4-96`($tptr),%xmm1
- pand %xmm7,%xmm3
- por %xmm2,%xmm0
- movq `1*$STRIDE/4-96`($tptr),%xmm2
- por %xmm3,%xmm0
- .byte 0x67,0x67
- pand %xmm4,%xmm1
- movq `2*$STRIDE/4-96`($tptr),%xmm3
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimizaton)
+ lea 128($bp),$bptr # size optimization
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ .byte 0x67
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ .byte 0x67
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+ movdqa %xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ .byte 0x67
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+
+ pand `16*($i+0)-128`($bptr),%xmm0 # while it's still in register
+ pand `16*($i+1)-128`($bptr),%xmm1
+ pand `16*($i+2)-128`($bptr),%xmm2
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ pand `16*($i+3)-128`($bptr),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bptr),%xmm4
+ movdqa `16*($i+1)-128`($bptr),%xmm5
+ movdqa `16*($i+2)-128`($bptr),%xmm2
+ pand `16*($i+0)+112`(%r10),%xmm4
+ movdqa `16*($i+3)-128`($bptr),%xmm3
+ pand `16*($i+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($i+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($i+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ pxor %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
+ lea $STRIDE($bptr),$bptr
movq %xmm0,%rdx # bp[0]
- movq `3*$STRIDE/4-96`($tptr),%xmm0
- lea 2*$STRIDE($bptr),$bptr # next &b[i]
- pand %xmm5,%xmm2
- .byte 0x67,0x67
- pand %xmm6,%xmm3
- ##############################################################
- # $tptr is chosen so that writing to top-most element of the
- # vector occurs just "above" references to powers table,
- # "above" modulo cache-line size, which effectively precludes
- # possibility of memory disambiguation logic failure when
- # accessing the table.
- #
- lea 64+8*4+8(%rsp,%r11,8),$tptr
+ lea 64+8*4+8(%rsp),$tptr
mov %rdx,$bi
mulx 0*8($aptr),$mi,%rax # a[0]*b[0]
@@ -2191,37 +2314,31 @@ $code.=<<___;
xor $zero,$zero # cf=0, of=0
mov $mi,%rdx
- por %xmm2,%xmm1
- pand %xmm7,%xmm0
- por %xmm3,%xmm1
mov $bptr,8+8(%rsp) # off-load &b[i]
- por %xmm1,%xmm0
- .byte 0x48,0x8d,0xb6,0x20,0x00,0x00,0x00 # lea 4*8($aptr),$aptr
+ lea 4*8($aptr),$aptr
adcx %rax,%r13
adcx $zero,%r14 # cf=0
- mulx 0*16($nptr),%rax,%r10
+ mulx 0*8($nptr),%rax,%r10
adcx %rax,%r15 # discarded
adox %r11,%r10
- mulx 1*16($nptr),%rax,%r11
+ mulx 1*8($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- mulx 2*16($nptr),%rax,%r12
+ mulx 2*8($nptr),%rax,%r12
mov 24+8(%rsp),$bptr # counter value
- .byte 0x66
mov %r10,-8*4($tptr)
adcx %rax,%r11
adox %r13,%r12
- mulx 3*16($nptr),%rax,%r15
- .byte 0x67,0x67
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
mov %r11,-8*3($tptr)
adcx %rax,%r12
adox $zero,%r15 # of=0
- .byte 0x48,0x8d,0x89,0x40,0x00,0x00,0x00 # lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r12,-8*2($tptr)
- #jmp .Lmulx4x_1st
+ jmp .Lmulx4x_1st
.align 32
.Lmulx4x_1st:
@@ -2241,30 +2358,29 @@ $code.=<<___;
lea 4*8($tptr),$tptr
adox %r15,%r10
- mulx 0*16($nptr),%rax,%r15
+ mulx 0*8($nptr),%rax,%r15
adcx %rax,%r10
adox %r15,%r11
- mulx 1*16($nptr),%rax,%r15
+ mulx 1*8($nptr),%rax,%r15
adcx %rax,%r11
adox %r15,%r12
- mulx 2*16($nptr),%rax,%r15
+ mulx 2*8($nptr),%rax,%r15
mov %r10,-5*8($tptr)
adcx %rax,%r12
mov %r11,-4*8($tptr)
adox %r15,%r13
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
mov %r12,-3*8($tptr)
adcx %rax,%r13
adox $zero,%r15
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r13,-2*8($tptr)
dec $bptr # of=0, pass cf
jnz .Lmulx4x_1st
mov 8(%rsp),$num # load -num
- movq %xmm0,%rdx # bp[1]
adc $zero,%r15 # modulo-scheduled
lea ($aptr,$num),$aptr # rewind $aptr
add %r15,%r14
@@ -2275,6 +2391,34 @@ $code.=<<___;
.align 32
.Lmulx4x_outer:
+ lea 16-256($tptr),%r10 # where 256-byte mask is (+density control)
+ pxor %xmm4,%xmm4
+ .byte 0x67,0x67
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bptr),%xmm0
+ movdqa `16*($i+1)-128`($bptr),%xmm1
+ movdqa `16*($i+2)-128`($bptr),%xmm2
+ pand `16*($i+0)+256`(%r10),%xmm0
+ movdqa `16*($i+3)-128`($bptr),%xmm3
+ pand `16*($i+1)+256`(%r10),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)+256`(%r10),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)+256`(%r10),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bptr),$bptr
+ movq %xmm0,%rdx # m0=bp[i]
+
mov $zero,($tptr) # save top-most carry
lea 4*8($tptr,$num),$tptr # rewind $tptr
mulx 0*8($aptr),$mi,%r11 # a[0]*b[i]
@@ -2289,54 +2433,37 @@ $code.=<<___;
mulx 3*8($aptr),%rdx,%r14
adox -2*8($tptr),%r12
adcx %rdx,%r13
- lea ($nptr,$num,2),$nptr # rewind $nptr
+ lea ($nptr,$num),$nptr # rewind $nptr
lea 4*8($aptr),$aptr
adox -1*8($tptr),%r13
adcx $zero,%r14
adox $zero,%r14
- .byte 0x67
mov $mi,%r15
imulq 32+8(%rsp),$mi # "t[0]"*n0
- movq `0*$STRIDE/4-96`($bptr),%xmm0
- .byte 0x67,0x67
mov $mi,%rdx
- movq `1*$STRIDE/4-96`($bptr),%xmm1
- .byte 0x67
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bptr),%xmm2
- .byte 0x67
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bptr),%xmm3
- add \$$STRIDE,$bptr # next &b[i]
- .byte 0x67
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
xor $zero,$zero # cf=0, of=0
mov $bptr,8+8(%rsp) # off-load &b[i]
- mulx 0*16($nptr),%rax,%r10
+ mulx 0*8($nptr),%rax,%r10
adcx %rax,%r15 # discarded
adox %r11,%r10
- mulx 1*16($nptr),%rax,%r11
+ mulx 1*8($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- mulx 2*16($nptr),%rax,%r12
+ mulx 2*8($nptr),%rax,%r12
adcx %rax,%r11
adox %r13,%r12
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
- por %xmm2,%xmm0
mov 24+8(%rsp),$bptr # counter value
mov %r10,-8*4($tptr)
- por %xmm3,%xmm0
adcx %rax,%r12
mov %r11,-8*3($tptr)
adox $zero,%r15 # of=0
mov %r12,-8*2($tptr)
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
jmp .Lmulx4x_inner
.align 32
@@ -2361,20 +2488,20 @@ $code.=<<___;
adcx $zero,%r14 # cf=0
adox %r15,%r10
- mulx 0*16($nptr),%rax,%r15
+ mulx 0*8($nptr),%rax,%r15
adcx %rax,%r10
adox %r15,%r11
- mulx 1*16($nptr),%rax,%r15
+ mulx 1*8($nptr),%rax,%r15
adcx %rax,%r11
adox %r15,%r12
- mulx 2*16($nptr),%rax,%r15
+ mulx 2*8($nptr),%rax,%r15
mov %r10,-5*8($tptr)
adcx %rax,%r12
adox %r15,%r13
mov %r11,-4*8($tptr)
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r12,-3*8($tptr)
adcx %rax,%r13
adox $zero,%r15
@@ -2384,7 +2511,6 @@ $code.=<<___;
jnz .Lmulx4x_inner
mov 0+8(%rsp),$num # load -num
- movq %xmm0,%rdx # bp[i+1]
adc $zero,%r15 # modulo-scheduled
sub 0*8($tptr),$bptr # pull top-most carry to %cf
mov 8+8(%rsp),$bptr # re-load &b[i]
@@ -2397,20 +2523,26 @@ $code.=<<___;
cmp %r10,$bptr
jb .Lmulx4x_outer
- mov -16($nptr),%r10
+ mov -8($nptr),%r10
+ mov $zero,%r8
+ mov ($nptr,$num),%r12
+ lea ($nptr,$num),%rbp # rewind $nptr
+ mov $num,%rcx
+ lea ($tptr,$num),%rdi # rewind $tptr
+ xor %eax,%eax
xor %r15,%r15
sub %r14,%r10 # compare top-most words
adc %r15,%r15
- or %r15,$zero
- xor \$1,$zero
- lea ($tptr,$num),%rdi # rewind $tptr
- lea ($nptr,$num,2),$nptr # rewind $nptr
- .byte 0x67,0x67
- sar \$3+2,$num # cf=0
- lea ($nptr,$zero,8),%rbp
+ or %r15,%r8
+ sar \$3+2,%rcx
+ sub %r8,%rax # %rax=-%r8
mov 56+8(%rsp),%rdx # restore rp
- mov $num,%rcx
- jmp .Lsqrx4x_sub # common post-condition
+ dec %r12 # so that after 'not' we get -n[0]
+ mov 8*1(%rbp),%r13
+ xor %r8,%r8
+ mov 8*2(%rbp),%r14
+ mov 8*3(%rbp),%r15
+ jmp .Lsqrx4x_sub_entry # common post-condition
.size mulx4x_internal,.-mulx4x_internal
___
} {
@@ -2434,7 +2566,6 @@ $code.=<<___;
.align 32
bn_powerx5:
.Lpowerx5_enter:
- .byte 0x67
mov %rsp,%rax
push %rbx
push %rbp
@@ -2442,39 +2573,32 @@ bn_powerx5:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwrx_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lpwrx_sp_done
.align 32
.Lpwrx_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -2505,10 +2629,15 @@ $code.=<<___;
.Lpowerx5_body:
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
mov %r10,$num # -num
mov $aptr,$rptr
@@ -2520,12 +2649,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -2959,11 +3083,11 @@ my ($nptr,$carry,$m0)=("%rbp","%rsi","%rdx");
$code.=<<___;
movq %xmm2,$nptr
-sqrx8x_reduction:
+__bn_sqrx8x_reduction:
xor %eax,%eax # initial top-most carry bit
mov 32+8(%rsp),%rbx # n0
mov 48+8(%rsp),%rdx # "%r8", 8*0($tptr)
- lea -128($nptr,$num,2),%rcx # end of n[]
+ lea -8*8($nptr,$num),%rcx # end of n[]
#lea 48+8(%rsp,$num,2),$tptr # end of t[] buffer
mov %rcx, 0+8(%rsp) # save end of n[]
mov $tptr,8+8(%rsp) # save end of t[]
@@ -2992,23 +3116,23 @@ sqrx8x_reduction:
.align 32
.Lsqrx8x_reduce:
mov %r8, %rbx
- mulx 16*0($nptr),%rax,%r8 # n[0]
+ mulx 8*0($nptr),%rax,%r8 # n[0]
adcx %rbx,%rax # discarded
adox %r9,%r8
- mulx 16*1($nptr),%rbx,%r9 # n[1]
+ mulx 8*1($nptr),%rbx,%r9 # n[1]
adcx %rbx,%r8
adox %r10,%r9
- mulx 16*2($nptr),%rbx,%r10
+ mulx 8*2($nptr),%rbx,%r10
adcx %rbx,%r9
adox %r11,%r10
- mulx 16*3($nptr),%rbx,%r11
+ mulx 8*3($nptr),%rbx,%r11
adcx %rbx,%r10
adox %r12,%r11
- .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rbx,%r12
+ .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rbx,%r12
mov %rdx,%rax
mov %r8,%rdx
adcx %rbx,%r11
@@ -3018,15 +3142,15 @@ sqrx8x_reduction:
mov %rax,%rdx
mov %rax,64+48+8(%rsp,%rcx,8) # put aside n0*a[i]
- mulx 16*5($nptr),%rax,%r13
+ mulx 8*5($nptr),%rax,%r13
adcx %rax,%r12
adox %r14,%r13
- mulx 16*6($nptr),%rax,%r14
+ mulx 8*6($nptr),%rax,%r14
adcx %rax,%r13
adox %r15,%r14
- mulx 16*7($nptr),%rax,%r15
+ mulx 8*7($nptr),%rax,%r15
mov %rbx,%rdx
adcx %rax,%r14
adox $carry,%r15 # $carry is 0
@@ -3042,7 +3166,7 @@ sqrx8x_reduction:
mov 48+8(%rsp),%rdx # pull n0*a[0]
add 8*0($tptr),%r8
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
mov \$-8,%rcx
adcx 8*1($tptr),%r9
adcx 8*2($tptr),%r10
@@ -3061,35 +3185,35 @@ sqrx8x_reduction:
.align 32
.Lsqrx8x_tail:
mov %r8,%rbx
- mulx 16*0($nptr),%rax,%r8
+ mulx 8*0($nptr),%rax,%r8
adcx %rax,%rbx
adox %r9,%r8
- mulx 16*1($nptr),%rax,%r9
+ mulx 8*1($nptr),%rax,%r9
adcx %rax,%r8
adox %r10,%r9
- mulx 16*2($nptr),%rax,%r10
+ mulx 8*2($nptr),%rax,%r10
adcx %rax,%r9
adox %r11,%r10
- mulx 16*3($nptr),%rax,%r11
+ mulx 8*3($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rax,%r12
+ .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rax,%r12
adcx %rax,%r11
adox %r13,%r12
- mulx 16*5($nptr),%rax,%r13
+ mulx 8*5($nptr),%rax,%r13
adcx %rax,%r12
adox %r14,%r13
- mulx 16*6($nptr),%rax,%r14
+ mulx 8*6($nptr),%rax,%r14
adcx %rax,%r13
adox %r15,%r14
- mulx 16*7($nptr),%rax,%r15
+ mulx 8*7($nptr),%rax,%r15
mov 72+48+8(%rsp,%rcx,8),%rdx # pull n0*a[i]
adcx %rax,%r14
adox $carry,%r15
@@ -3105,7 +3229,7 @@ sqrx8x_reduction:
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
mov 48+8(%rsp),%rdx # pull n0*a[0]
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
adc 8*0($tptr),%r8
adc 8*1($tptr),%r9
adc 8*2($tptr),%r10
@@ -3141,7 +3265,7 @@ sqrx8x_reduction:
adc 8*0($tptr),%r8
movq %xmm3,%rcx
adc 8*1($tptr),%r9
- mov 16*7($nptr),$carry
+ mov 8*7($nptr),$carry
movq %xmm2,$nptr # restore $nptr
adc 8*2($tptr),%r10
adc 8*3($tptr),%r11
@@ -3167,6 +3291,8 @@ sqrx8x_reduction:
lea 8*8($tptr,%rcx),$tptr # start of current t[] window
cmp 8+8(%rsp),%r8 # end of t[]?
jb .Lsqrx8x_reduction_loop
+ ret
+.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
___
}
##############################################################
@@ -3174,52 +3300,59 @@ ___
#
{
my ($rptr,$nptr)=("%rdx","%rbp");
-my @ri=map("%r$_",(10..13));
-my @ni=map("%r$_",(14..15));
$code.=<<___;
- xor %ebx,%ebx
- sub %r15,%rsi # compare top-most words
- adc %rbx,%rbx
+.align 32
+__bn_postx4x_internal:
+ mov 8*0($nptr),%r12
mov %rcx,%r10 # -$num
- or %rbx,%rax
mov %rcx,%r9 # -$num
- xor \$1,%rax
- sar \$3+2,%rcx # cf=0
+ neg %rax
+ sar \$3+2,%rcx
#lea 48+8(%rsp,%r9),$tptr
- lea ($nptr,%rax,8),$nptr
movq %xmm1,$rptr # restore $rptr
movq %xmm1,$aptr # prepare for back-to-back call
- jmp .Lsqrx4x_sub
+ dec %r12 # so that after 'not' we get -n[0]
+ mov 8*1($nptr),%r13
+ xor %r8,%r8
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+ jmp .Lsqrx4x_sub_entry
-.align 32
+.align 16
.Lsqrx4x_sub:
- .byte 0x66
- mov 8*0($tptr),%r12
- mov 8*1($tptr),%r13
- sbb 16*0($nptr),%r12
- mov 8*2($tptr),%r14
- sbb 16*1($nptr),%r13
- mov 8*3($tptr),%r15
- lea 8*4($tptr),$tptr
- sbb 16*2($nptr),%r14
+ mov 8*0($nptr),%r12
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+.Lsqrx4x_sub_entry:
+ andn %rax,%r12,%r12
+ lea 8*4($nptr),$nptr
+ andn %rax,%r13,%r13
+ andn %rax,%r14,%r14
+ andn %rax,%r15,%r15
+
+ neg %r8 # mov %r8,%cf
+ adc 8*0($tptr),%r12
+ adc 8*1($tptr),%r13
+ adc 8*2($tptr),%r14
+ adc 8*3($tptr),%r15
mov %r12,8*0($rptr)
- sbb 16*3($nptr),%r15
- lea 16*4($nptr),$nptr
+ lea 8*4($tptr),$tptr
mov %r13,8*1($rptr)
+ sbb %r8,%r8 # mov %cf,%r8
mov %r14,8*2($rptr)
mov %r15,8*3($rptr)
lea 8*4($rptr),$rptr
inc %rcx
jnz .Lsqrx4x_sub
-___
-}
-$code.=<<___;
+
neg %r9 # restore $num
ret
-.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
+.size __bn_postx4x_internal,.-__bn_postx4x_internal
___
+}
}}}
{
my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order
@@ -3249,56 +3382,91 @@ bn_scatter5:
.globl bn_gather5
.type bn_gather5,\@abi-omnipotent
-.align 16
+.align 32
bn_gather5:
-___
-$code.=<<___ if ($win64);
-.LSEH_begin_bn_gather5:
+.LSEH_begin_bn_gather5: # Win64 thing, but harmless in other cases
# I can't trust assembler to use specific encoding:-(
- .byte 0x48,0x83,0xec,0x28 #sub \$0x28,%rsp
- .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
- .byte 0x0f,0x29,0x7c,0x24,0x10 #movdqa %xmm7,0x10(%rsp)
+ .byte 0x4c,0x8d,0x14,0x24 #lea (%rsp),%r10
+ .byte 0x48,0x81,0xec,0x08,0x01,0x00,0x00 #sub $0x108,%rsp
+ lea .Linc(%rip),%rax
+ and \$-16,%rsp # shouldn't be formally required
+
+ movd $idx,%xmm5
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 128($tbl),%r11 # size optimization
+ lea 128(%rsp),%rax # size optimization
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast $idx
+ movdqa %xmm1,%xmm4
+ movdqa %xmm1,%xmm2
___
+########################################################################
+# calculate mask by comparing 0..31 to $idx and save result to stack
+#
+for($i=0;$i<$STRIDE/16;$i+=4) {
$code.=<<___;
- mov $idx,%r11d
- shr \$`log($N/8)/log(2)`,$idx
- and \$`$N/8-1`,%r11
- not $idx
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,$idx # 5 is "window size"
- lea 128($tbl,%r11,8),$tbl # pointer within 1st cache line
- movq 0(%rax,$idx,8),%xmm4 # set of masks denoting which
- movq 8(%rax,$idx,8),%xmm5 # cache line contains element
- movq 16(%rax,$idx,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,$idx,8),%xmm7
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+___
+$code.=<<___ if ($i);
+ movdqa %xmm3,`16*($i-1)-128`(%rax)
+___
+$code.=<<___;
+ movdqa %xmm4,%xmm3
+
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)-128`(%rax)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)-128`(%rax)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)-128`(%rax)
+ movdqa %xmm4,%xmm2
+___
+}
+$code.=<<___;
+ movdqa %xmm3,`16*($i-1)-128`(%rax)
jmp .Lgather
-.align 16
-.Lgather:
- movq `0*$STRIDE/4-128`($tbl),%xmm0
- movq `1*$STRIDE/4-128`($tbl),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-128`($tbl),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-128`($tbl),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
- .byte 0x67,0x67
- por %xmm2,%xmm0
- lea $STRIDE($tbl),$tbl
- por %xmm3,%xmm0
+.align 32
+.Lgather:
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`(%r11),%xmm0
+ movdqa `16*($i+1)-128`(%r11),%xmm1
+ movdqa `16*($i+2)-128`(%r11),%xmm2
+ pand `16*($i+0)-128`(%rax),%xmm0
+ movdqa `16*($i+3)-128`(%r11),%xmm3
+ pand `16*($i+1)-128`(%rax),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)-128`(%rax),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)-128`(%rax),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ lea $STRIDE(%r11),%r11
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
movq %xmm0,($out) # m0=bp[0]
lea 8($out),$out
sub \$1,$num
jnz .Lgather
-___
-$code.=<<___ if ($win64);
- movaps (%rsp),%xmm6
- movaps 0x10(%rsp),%xmm7
- lea 0x28(%rsp),%rsp
-___
-$code.=<<___;
+
+ lea (%r10),%rsp
ret
.LSEH_end_bn_gather5:
.size bn_gather5,.-bn_gather5
@@ -3306,9 +3474,9 @@ ___
}
$code.=<<___;
.align 64
-.Lmagic_masks:
- .long 0,0, 0,0, 0,0, -1,-1
- .long 0,0, 0,0, 0,0, 0,0
+.Linc:
+ .long 0,0, 1,1
+ .long 2,2, 2,2
.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
___
@@ -3356,19 +3524,16 @@ mul_handler:
lea .Lmul_epilogue(%rip),%r10
cmp %r10,%rbx
- jb .Lbody_40
+ ja .Lbody_40
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
+
jmp .Lbody_proceed
.Lbody_40:
mov 40(%rax),%rax # pull saved stack pointer
.Lbody_proceed:
-
- movaps -88(%rax),%xmm0
- movaps -72(%rax),%xmm1
-
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -3381,8 +3546,6 @@ mul_handler:
mov %r13,224($context) # restore context->R13
mov %r14,232($context) # restore context->R14
mov %r15,240($context) # restore context->R15
- movups %xmm0,512($context) # restore context->Xmm6
- movups %xmm1,528($context) # restore context->Xmm7
.Lcommon_seh_tail:
mov 8(%rax),%rdi
@@ -3493,10 +3656,9 @@ ___
$code.=<<___;
.align 8
.LSEH_info_bn_gather5:
- .byte 0x01,0x0d,0x05,0x00
- .byte 0x0d,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
- .byte 0x08,0x68,0x00,0x00 #movaps (rsp),xmm6
- .byte 0x04,0x42,0x00,0x00 #sub rsp,0x28
+ .byte 0x01,0x0b,0x03,0x0a
+ .byte 0x0b,0x01,0x21,0x00 # sub rsp,0x108
+ .byte 0x04,0xa3,0x00,0x00 # lea r10,(rsp)
.align 8
___
}
diff --git a/src/crypto/bn/bn.c b/src/crypto/bn/bn.c
index 543c1482..0ecaf825 100644
--- a/src/crypto/bn/bn.c
+++ b/src/crypto/bn/bn.c
@@ -266,6 +266,18 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) {
return 1;
}
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
+ if (bn_wexpand(bn, num) == NULL) {
+ return 0;
+ }
+ memmove(bn->d, words, num * sizeof(BN_ULONG));
+ /* |bn_wexpand| verified that |num| isn't too large. */
+ bn->top = (int)num;
+ bn_correct_top(bn);
+ bn->neg = 0;
+ return 1;
+}
+
int BN_is_negative(const BIGNUM *bn) {
return bn->neg != 0;
}
@@ -295,7 +307,7 @@ BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) {
return NULL;
}
- a = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
+ a = OPENSSL_malloc(sizeof(BN_ULONG) * words);
if (a == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL;
diff --git a/src/crypto/bn/bn_asn1.c b/src/crypto/bn/bn_asn1.c
index 9d70ba8e..efb23355 100644
--- a/src/crypto/bn/bn_asn1.c
+++ b/src/crypto/bn/bn_asn1.c
@@ -18,7 +18,7 @@
#include <openssl/err.h>
-int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
+int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
CBS_len(&child) == 0) {
@@ -42,7 +42,7 @@ int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
-int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
+int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
CBS_len(&child) == 0) {
@@ -58,7 +58,7 @@ int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
-int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
+int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
/* Negative numbers are unsupported. */
if (BN_is_negative(bn)) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
@@ -66,28 +66,15 @@ int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
}
CBB child;
- if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
+ /* The number must be padded with a leading zero if the high bit would
+ * otherwise be set or if |bn| is zero. */
+ (BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
+ !BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
+ !CBB_flush(cbb)) {
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
return 0;
}
- /* The number must be padded with a leading zero if the high bit would
- * otherwise be set (or |bn| is zero). */
- if (BN_num_bits(bn) % 8 == 0 &&
- !CBB_add_u8(&child, 0x00)) {
- OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
- return 0;
- }
-
- uint8_t *out;
- if (!CBB_add_space(&child, &out, BN_num_bytes(bn))) {
- OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
- return 0;
- }
- BN_bn2bin(bn, out);
- if (!CBB_flush(cbb)) {
- OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
- return 0;
- }
return 1;
}
diff --git a/src/crypto/bn/bn_test.cc b/src/crypto/bn/bn_test.cc
index e7e04f18..fe8cfd05 100644
--- a/src/crypto/bn/bn_test.cc
+++ b/src/crypto/bn/bn_test.cc
@@ -1799,8 +1799,8 @@ static const ASN1InvalidTest kASN1InvalidTests[] = {
{"\x02\x00", 2},
};
-// kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy|
-// should interpret them.
+// kASN1BuggyTests contains incorrect encodings and the corresponding, expected
+// results of |BN_parse_asn1_unsigned_buggy| given that input.
static const ASN1Test kASN1BuggyTests[] = {
// Negative numbers.
{"128", "\x02\x01\x80", 3},
@@ -1823,7 +1823,7 @@ static bool test_asn1() {
}
CBS cbs;
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
+ if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
return false;
}
@@ -1838,7 +1838,7 @@ static bool test_asn1() {
size_t der_len;
CBB_zero(&cbb);
if (!CBB_init(&cbb, 0) ||
- !BN_bn2cbb(&cbb, bn.get()) ||
+ !BN_marshal_asn1(&cbb, bn.get()) ||
!CBB_finish(&cbb, &der, &der_len)) {
CBB_cleanup(&cbb);
return false;
@@ -1850,9 +1850,9 @@ static bool test_asn1() {
return false;
}
- // |BN_cbs2unsigned_buggy| parses all valid input.
+ // |BN_parse_asn1_unsigned_buggy| parses all valid input.
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
+ if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
return false;
}
@@ -1869,16 +1869,16 @@ static bool test_asn1() {
}
CBS cbs;
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (BN_cbs2unsigned(&cbs, bn.get())) {
+ if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
fprintf(stderr, "Parsed invalid input.\n");
return false;
}
ERR_clear_error();
// All tests in kASN1InvalidTests are also rejected by
- // |BN_cbs2unsigned_buggy|.
+ // |BN_parse_asn1_unsigned_buggy|.
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (BN_cbs2unsigned_buggy(&cbs, bn.get())) {
+ if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) {
fprintf(stderr, "Parsed invalid input.\n");
return false;
}
@@ -1886,7 +1886,7 @@ static bool test_asn1() {
}
for (const ASN1Test &test : kASN1BuggyTests) {
- // These broken encodings are rejected by |BN_cbs2unsigned|.
+ // These broken encodings are rejected by |BN_parse_asn1_unsigned|.
ScopedBIGNUM bn(BN_new());
if (!bn) {
return false;
@@ -1894,20 +1894,20 @@ static bool test_asn1() {
CBS cbs;
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (BN_cbs2unsigned(&cbs, bn.get())) {
+ if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
fprintf(stderr, "Parsed invalid input.\n");
return false;
}
ERR_clear_error();
- // However |BN_cbs2unsigned_buggy| accepts them.
+ // However |BN_parse_asn1_unsigned_buggy| accepts them.
ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii);
if (!bn2) {
return false;
}
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
+ if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n");
return false;
}
@@ -1926,7 +1926,7 @@ static bool test_asn1() {
CBB cbb;
CBB_zero(&cbb);
if (!CBB_init(&cbb, 0) ||
- BN_bn2cbb(&cbb, bn.get())) {
+ BN_marshal_asn1(&cbb, bn.get())) {
fprintf(stderr, "Serialized negative number.\n");
CBB_cleanup(&cbb);
return false;
diff --git a/src/crypto/bn/convert.c b/src/crypto/bn/convert.c
index 1f7af64b..9125bf84 100644
--- a/src/crypto/bn/convert.c
+++ b/src/crypto/bn/convert.c
@@ -208,7 +208,7 @@ char *BN_bn2hex(const BIGNUM *bn) {
char *buf;
char *p;
- buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
+ buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
if (buf == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -385,9 +385,8 @@ char *BN_bn2dec(const BIGNUM *a) {
*/
i = BN_num_bits(a) * 3;
num = i / 10 + i / 1000 + 1 + 1;
- bn_data =
- (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
- buf = (char *)OPENSSL_malloc(num + 3);
+ bn_data = OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
+ buf = OPENSSL_malloc(num + 3);
if ((buf == NULL) || (bn_data == NULL)) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
goto err;
@@ -578,12 +577,14 @@ BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
return NULL;
}
+ int out_is_alloced = 0;
if (out == NULL) {
out = BN_new();
- }
- if (out == NULL) {
- OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
- return NULL;
+ if (out == NULL) {
+ OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ out_is_alloced = 1;
}
if (in_len == 0) {
@@ -593,6 +594,9 @@ BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
in += 4;
if (BN_bin2bn(in, in_len, out) == NULL) {
+ if (out_is_alloced) {
+ BN_free(out);
+ }
return NULL;
}
out->neg = ((*in) & 0x80) != 0;
diff --git a/src/crypto/bn/div.c b/src/crypto/bn/div.c
index f9e144a3..6f672914 100644
--- a/src/crypto/bn/div.c
+++ b/src/crypto/bn/div.c
@@ -56,55 +56,126 @@
#include <openssl/bn.h>
+#include <assert.h>
#include <limits.h>
#include <openssl/err.h>
#include "internal.h"
-#define asm __asm__
-
-#if !defined(OPENSSL_NO_ASM)
-# if defined(__GNUC__) && __GNUC__>=2
-# if defined(OPENSSL_X86)
- /*
- * There were two reasons for implementing this template:
- * - GNU C generates a call to a function (__udivdi3 to be exact)
- * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
- * understand why...);
- * - divl doesn't only calculate quotient, but also leaves
- * remainder in %edx which we can definitely use here:-)
- *
- * <appro@fy.chalmers.se>
- */
-#undef div_asm
-# define div_asm(n0,n1,d0) \
- ({ asm volatile ( \
- "divl %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# elif defined(OPENSSL_X86_64)
- /*
- * Same story here, but it's 128-bit by 64-bit division. Wow!
- * <appro@fy.chalmers.se>
- */
-# undef div_asm
-# define div_asm(n0,n1,d0) \
- ({ asm volatile ( \
- "divq %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# endif /* __<cpu> */
-# endif /* __GNUC__ */
-#endif /* OPENSSL_NO_ASM */
+#if !defined(BN_ULLONG)
+/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
+ * which must fit in a |BN_ULONG|. */
+static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
+ BN_ULONG dh, dl, q, ret = 0, th, tl, t;
+ int i, count = 2;
+
+ if (d == 0) {
+ return BN_MASK2;
+ }
+
+ i = BN_num_bits_word(d);
+ assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
+
+ i = BN_BITS2 - i;
+ if (h >= d) {
+ h -= d;
+ }
+
+ if (i) {
+ d <<= i;
+ h = (h << i) | (l >> (BN_BITS2 - i));
+ l <<= i;
+ }
+ dh = (d & BN_MASK2h) >> BN_BITS4;
+ dl = (d & BN_MASK2l);
+ for (;;) {
+ if ((h >> BN_BITS4) == dh) {
+ q = BN_MASK2l;
+ } else {
+ q = h / dh;
+ }
+
+ th = q * dh;
+ tl = dl * q;
+ for (;;) {
+ t = h - th;
+ if ((t & BN_MASK2h) ||
+ ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
+ break;
+ }
+ q--;
+ th -= dh;
+ tl -= dl;
+ }
+ t = (tl >> BN_BITS4);
+ tl = (tl << BN_BITS4) & BN_MASK2h;
+ th += t;
+
+ if (l < tl) {
+ th++;
+ }
+ l -= tl;
+ if (h < th) {
+ h += d;
+ q--;
+ }
+ h -= th;
+
+ if (--count == 0) {
+ break;
+ }
+
+ ret = q << BN_BITS4;
+ h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
+ l = (l & BN_MASK2l) << BN_BITS4;
+ }
+
+ ret |= q;
+ return ret;
+}
+#endif /* !defined(BN_ULLONG) */
+
+static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
+ BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
+ /* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
+ * the |BN_ULLONG|-based C code is used.
+ *
+ * GCC bugs:
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
+ *
+ * Clang bugs:
+ * * https://llvm.org/bugs/show_bug.cgi?id=6397
+ * * https://llvm.org/bugs/show_bug.cgi?id=12418
+ *
+ * These issues aren't specific to x86 and x86_64, so it might be worthwhile
+ * to add more assembly language implementations. */
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
+ __asm__ volatile (
+ "divl %4"
+ : "=a"(*quotient_out), "=d"(*rem_out)
+ : "a"(n1), "d"(n0), "g"(d0)
+ : "cc" );
+#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
+ __asm__ volatile (
+ "divq %4"
+ : "=a"(*quotient_out), "=d"(*rem_out)
+ : "a"(n1), "d"(n0), "g"(d0)
+ : "cc" );
+#else
+#if defined(BN_ULLONG)
+ BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
+ *quotient_out = (BN_ULONG)(n / d0);
+#else
+ *quotient_out = bn_div_words(n0, n1, d0);
+#endif
+ *rem_out = n1 - (*quotient_out * d0);
+#endif
+}
/* BN_div computes dv := num / divisor, rounding towards
* zero, and sets up rm such that dv*divisor + rm = num holds.
@@ -260,23 +331,10 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
q = BN_MASK2;
} else {
/* n0 < d0 */
-#ifdef BN_ULLONG
- BN_ULLONG t2;
-
-#if defined(BN_ULLONG) && !defined(div_asm)
- q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
-#else
- q = div_asm(n0, n1, d0);
-#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;
+ bn_div_rem_words(&q, &rem, n0, n1, d0);
+#ifdef BN_ULLONG
+ BN_ULLONG t2 = (BN_ULLONG)d1 * q;
for (;;) {
if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
break;
@@ -290,33 +348,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
}
#else /* !BN_ULLONG */
BN_ULONG t2l, t2h;
-
-#if defined(div_asm)
- q = div_asm(n0, n1, d0);
-#else
- q = bn_div_words(n0, n1, d0);
-#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
- {
- BN_ULONG ql, qh;
- 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;
@@ -576,7 +608,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
return 0;
}
- /* normalize input (so bn_div_words doesn't complain) */
+ /* normalize input for |bn_div_rem_words|. */
j = BN_BITS2 - BN_num_bits_word(w);
w <<= j;
if (!BN_lshift(a, a, j)) {
@@ -584,10 +616,10 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
}
for (i = a->top - 1; i >= 0; i--) {
- BN_ULONG l, d;
-
- l = a->d[i];
- d = bn_div_words(ret, l, w);
+ BN_ULONG l = a->d[i];
+ BN_ULONG d;
+ BN_ULONG unused_rem;
+ bn_div_rem_words(&d, &unused_rem, ret, l, w);
ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
a->d[i] = d;
}
diff --git a/src/crypto/bn/exponentiation.c b/src/crypto/bn/exponentiation.c
index 72a8db4b..bb7a2f40 100644
--- a/src/crypto/bn/exponentiation.c
+++ b/src/crypto/bn/exponentiation.c
@@ -209,6 +209,7 @@ static void BN_RECP_CTX_init(BN_RECP_CTX *recp) {
BN_init(&recp->N);
BN_init(&recp->Nr);
recp->num_bits = 0;
+ recp->shift = 0;
recp->flags = 0;
}
@@ -787,29 +788,65 @@ err:
* pattern as far as cache lines are concerned. The following functions are
* used to transfer a BIGNUM from/to that table. */
static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
- int width) {
- size_t i, j;
+ int window) {
+ int i, j;
+ const int width = 1 << window;
+ BN_ULONG *table = (BN_ULONG *) buf;
if (top > b->top) {
top = b->top; /* this works because 'buf' is explicitly zeroed */
}
- for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
- buf[j] = ((unsigned char *)b->d)[i];
+
+ for (i = 0, j = idx; i < top; i++, j += width) {
+ table[j] = b->d[i];
}
return 1;
}
static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
- int width) {
- size_t i, j;
+ int window) {
+ int i, j;
+ const int width = 1 << window;
+ volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
if (bn_wexpand(b, top) == NULL) {
return 0;
}
- for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
- ((unsigned char *)b->d)[i] = buf[j];
+ if (window <= 3) {
+ for (i = 0; i < top; i++, table += width) {
+ BN_ULONG acc = 0;
+
+ for (j = 0; j < width; j++) {
+ acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+ }
+
+ b->d[i] = acc;
+ }
+ } else {
+ int xstride = 1 << (window - 2);
+ BN_ULONG y0, y1, y2, y3;
+
+ i = idx >> (window - 2); /* equivalent of idx / xstride */
+ idx &= xstride - 1; /* equivalent of idx % xstride */
+
+ y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1);
+ y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1);
+ y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1);
+ y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1);
+
+ for (i = 0; i < top; i++, table += width) {
+ BN_ULONG acc = 0;
+
+ for (j = 0; j < xstride; j++) {
+ acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) |
+ (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) &
+ ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+ }
+
+ b->d[i] = acc;
+ }
}
b->top = top;
@@ -891,8 +928,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
return BN_one(rr);
}
- BN_CTX_start(ctx);
-
/* Allocate a montgomery context if it was not supplied by the caller. */
if (mont == NULL) {
new_mont = BN_MONT_CTX_new();
@@ -935,9 +970,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
#if defined(OPENSSL_BN_ASM_MONT5)
if (window >= 5) {
window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
- if ((top & 7) == 0) {
- powerbufLen += 2 * top * sizeof(m->d[0]);
- }
+ /* reserve space for mont->N.d[] copy */
+ powerbufLen += top * sizeof(mont->N.d[0]);
}
#endif
@@ -954,7 +988,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
} else
#endif
{
- if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
+ if ((powerbufFree = OPENSSL_malloc(
powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) {
goto err;
}
@@ -1008,7 +1042,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
* 512-bit RSA is hardly relevant, we omit it to spare size... */
if (window == 5 && top > 1) {
- const BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;
+ const BN_ULONG *n0 = mont->n0;
+ BN_ULONG *np;
/* BN_to_montgomery can contaminate words above .top
* [in BN_DEBUG[_DEBUG] build]... */
@@ -1019,14 +1054,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.d[i] = 0;
}
- if (top & 7) {
- np2 = np;
- } else {
- BN_ULONG *np_double = am.d + top;
- for (i = 0; i < top; i++) {
- np_double[2 * i] = np[i];
- }
- np2 = np_double;
+ /* copy mont->N.d[] to improve cache locality */
+ for (np = am.d + top, i = 0; i < top; i++) {
+ np[i] = mont->N.d[i];
}
bn_scatter5(tmp.d, top, powerbuf, 0);
@@ -1041,7 +1071,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
for (i = 3; i < 8; i += 2) {
int j;
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
for (j = 2 * i; j < 32; j *= 2) {
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
@@ -1049,13 +1079,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
}
for (; i < 16; i += 2) {
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, 2 * i);
}
for (; i < 32; i += 2) {
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
}
@@ -1103,7 +1133,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
wvalue >>= (bits - 4) & 7;
wvalue &= 0x1f;
bits -= 5;
- bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
}
while (bits >= 0) {
/* Read five bits from |bits-4| through |bits|, inclusive. */
@@ -1112,11 +1142,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
wvalue >>= first_bit & 7;
wvalue &= 0x1f;
bits -= 5;
- bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
}
}
- ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);
+ ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
tmp.top = top;
bn_correct_top(&tmp);
if (ret) {
@@ -1128,8 +1158,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
} else
#endif
{
- if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers) ||
- !copy_to_prebuf(&am, top, powerbuf, 1, numPowers)) {
+ if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) ||
+ !copy_to_prebuf(&am, top, powerbuf, 1, window)) {
goto err;
}
@@ -1140,13 +1170,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
*/
if (window > 1) {
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
- !copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers)) {
+ !copy_to_prebuf(&tmp, top, powerbuf, 2, window)) {
goto err;
}
for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
- !copy_to_prebuf(&tmp, top, powerbuf, i, numPowers)) {
+ !copy_to_prebuf(&tmp, top, powerbuf, i, window)) {
goto err;
}
}
@@ -1156,7 +1186,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) {
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
}
- if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers)) {
+ if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) {
goto err;
}
@@ -1175,7 +1205,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
/* Fetch the appropriate pre-computed value from the pre-buf */
- if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers)) {
+ if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) {
goto err;
}
@@ -1198,7 +1228,6 @@ err:
OPENSSL_cleanse(powerbuf, powerbufLen);
OPENSSL_free(powerbufFree);
}
- BN_CTX_end(ctx);
return (ret);
}
diff --git a/src/crypto/bn/generic.c b/src/crypto/bn/generic.c
index 7303ca5b..f552d99f 100644
--- a/src/crypto/bn/generic.c
+++ b/src/crypto/bn/generic.c
@@ -61,13 +61,10 @@
#include "internal.h"
-/* Generic implementations of most operations are needed for:
- * - Configurations without inline assembly.
- * - Architectures other than x86 or x86_64.
- * - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
+/* This file has two other implementations: x86 assembly language in
+ * asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */
#if defined(OPENSSL_NO_ASM) || \
- (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
- (defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
+ !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
#ifdef BN_ULLONG
#define mul_add(r, a, w, c) \
@@ -94,7 +91,8 @@
(r1) = Hw(t); \
}
-#elif defined(BN_UMULT_LOHI)
+#else
+
#define mul_add(r, a, w, c) \
{ \
BN_ULONG high, low, ret, tmp = (a); \
@@ -124,102 +122,8 @@
BN_UMULT_LOHI(r0, r1, tmp, tmp); \
}
-#else
-
-/*************************************************************
- * No long long type
- */
-
-#define LBITS(a) ((a) & BN_MASK2l)
-#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
-#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
-
-#define LLBITS(a) ((a) & BN_MASKl)
-#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
-#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
-
-#define mul64(l, h, bl, bh) \
- { \
- BN_ULONG m, m1, lt, ht; \
- \
- lt = l; \
- ht = h; \
- m = (bh) * (lt); \
- lt = (bl) * (lt); \
- m1 = (bl) * (ht); \
- ht = (bh) * (ht); \
- m = (m + m1) & BN_MASK2; \
- if (m < m1) \
- ht += L2HBITS((BN_ULONG)1); \
- ht += HBITS(m); \
- m1 = L2HBITS(m); \
- lt = (lt + m1) & BN_MASK2; \
- if (lt < m1) \
- ht++; \
- (l) = lt; \
- (h) = ht; \
- }
-
-#define sqr64(lo, ho, in) \
- { \
- BN_ULONG l, h, m; \
- \
- h = (in); \
- l = LBITS(h); \
- h = HBITS(h); \
- m = (l) * (h); \
- l *= l; \
- h *= h; \
- h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \
- m = (m & BN_MASK2l) << (BN_BITS4 + 1); \
- l = (l + m) & BN_MASK2; \
- if (l < m) \
- h++; \
- (lo) = l; \
- (ho) = h; \
- }
-
-#define mul_add(r, a, bl, bh, c) \
- { \
- BN_ULONG l, h; \
- \
- h = (a); \
- l = LBITS(h); \
- h = HBITS(h); \
- mul64(l, h, (bl), (bh)); \
- \
- /* non-multiply part */ \
- l = (l + (c)) & BN_MASK2; \
- if (l < (c)) \
- h++; \
- (c) = (r); \
- l = (l + (c)) & BN_MASK2; \
- if (l < (c)) \
- h++; \
- (c) = h & BN_MASK2; \
- (r) = l; \
- }
-
-#define mul(r, a, bl, bh, c) \
- { \
- BN_ULONG l, h; \
- \
- h = (a); \
- l = LBITS(h); \
- h = HBITS(h); \
- mul64(l, h, (bl), (bh)); \
- \
- /* non-multiply part */ \
- l += (c); \
- if ((l & BN_MASK2) < (c)) \
- h++; \
- (c) = h & BN_MASK2; \
- (r) = l & BN_MASK2; \
- }
#endif /* !BN_ULLONG */
-#if defined(BN_ULLONG) || defined(BN_UMULT_HIGH)
-
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
BN_ULONG c1 = 0;
@@ -298,174 +202,6 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
}
-#else /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
-
-BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
- BN_ULONG w) {
- BN_ULONG c = 0;
- BN_ULONG bl, bh;
-
- assert(num >= 0);
- if (num <= 0) {
- return (BN_ULONG)0;
- }
-
- bl = LBITS(w);
- bh = HBITS(w);
-
- while (num & ~3) {
- mul_add(rp[0], ap[0], bl, bh, c);
- mul_add(rp[1], ap[1], bl, bh, c);
- mul_add(rp[2], ap[2], bl, bh, c);
- mul_add(rp[3], ap[3], bl, bh, c);
- ap += 4;
- rp += 4;
- num -= 4;
- }
- while (num) {
- mul_add(rp[0], ap[0], bl, bh, c);
- ap++;
- rp++;
- num--;
- }
- return c;
-}
-
-BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
- BN_ULONG carry = 0;
- BN_ULONG bl, bh;
-
- assert(num >= 0);
- if (num <= 0) {
- return (BN_ULONG)0;
- }
-
- bl = LBITS(w);
- bh = HBITS(w);
-
- while (num & ~3) {
- mul(rp[0], ap[0], bl, bh, carry);
- mul(rp[1], ap[1], bl, bh, carry);
- mul(rp[2], ap[2], bl, bh, carry);
- mul(rp[3], ap[3], bl, bh, carry);
- ap += 4;
- rp += 4;
- num -= 4;
- }
- while (num) {
- mul(rp[0], ap[0], bl, bh, carry);
- ap++;
- rp++;
- num--;
- }
- return carry;
-}
-
-void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
- assert(n >= 0);
- if (n <= 0) {
- return;
- }
-
- while (n & ~3) {
- sqr64(r[0], r[1], a[0]);
- sqr64(r[2], r[3], a[1]);
- sqr64(r[4], r[5], a[2]);
- sqr64(r[6], r[7], a[3]);
- a += 4;
- r += 8;
- n -= 4;
- }
- while (n) {
- sqr64(r[0], r[1], a[0]);
- a++;
- r += 2;
- n--;
- }
-}
-
-#endif /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
-
-#if defined(BN_ULLONG)
-
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- return (BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2) | l) / (BN_ULLONG)d);
-}
-
-#else
-
-/* Divide h,l by d and return the result. */
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- BN_ULONG dh, dl, q, ret = 0, th, tl, t;
- int i, count = 2;
-
- if (d == 0) {
- return BN_MASK2;
- }
-
- i = BN_num_bits_word(d);
- assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
-
- i = BN_BITS2 - i;
- if (h >= d) {
- h -= d;
- }
-
- if (i) {
- d <<= i;
- h = (h << i) | (l >> (BN_BITS2 - i));
- l <<= i;
- }
- dh = (d & BN_MASK2h) >> BN_BITS4;
- dl = (d & BN_MASK2l);
- for (;;) {
- if ((h >> BN_BITS4) == dh) {
- q = BN_MASK2l;
- } else {
- q = h / dh;
- }
-
- th = q * dh;
- tl = dl * q;
- for (;;) {
- t = h - th;
- if ((t & BN_MASK2h) ||
- ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
- break;
- }
- q--;
- th -= dh;
- tl -= dl;
- }
- t = (tl >> BN_BITS4);
- tl = (tl << BN_BITS4) & BN_MASK2h;
- th += t;
-
- if (l < tl) {
- th++;
- }
- l -= tl;
- if (h < th) {
- h += d;
- q--;
- }
- h -= th;
-
- if (--count == 0) {
- break;
- }
-
- ret = q << BN_BITS4;
- h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
- l = (l & BN_MASK2l) << BN_BITS4;
- }
-
- ret |= q;
- return ret;
-}
-
-#endif /* !defined(BN_ULLONG) */
-
#ifdef BN_ULLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n) {
@@ -673,7 +409,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
-#elif defined(BN_UMULT_LOHI)
+#else
/* Keep in mind that additions to hi can not overflow, because the high word of
* a multiplication result cannot be all-ones. */
@@ -716,58 +452,6 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
-#else /* !BN_ULLONG */
-
-/* Keep in mind that additions to hi can not overflow, because
- * the high word of a multiplication result cannot be all-ones. */
-
-#define mul_add_c(a, b, c0, c1, c2) \
- do { \
- BN_ULONG lo = LBITS(a), hi = HBITS(a); \
- BN_ULONG bl = LBITS(b), bh = HBITS(b); \
- mul64(lo, hi, bl, bh); \
- c0 = (c0 + lo) & BN_MASK2; \
- if (c0 < lo) \
- hi++; \
- c1 = (c1 + hi) & BN_MASK2; \
- if (c1 < hi) \
- c2++; \
- } while (0)
-
-#define mul_add_c2(a, b, c0, c1, c2) \
- do { \
- BN_ULONG tt; \
- BN_ULONG lo = LBITS(a), hi = HBITS(a); \
- BN_ULONG bl = LBITS(b), bh = HBITS(b); \
- mul64(lo, hi, bl, bh); \
- tt = hi; \
- c0 = (c0 + lo) & BN_MASK2; \
- if (c0 < lo) \
- tt++; \
- c1 = (c1 + tt) & BN_MASK2; \
- if (c1 < tt) \
- c2++; \
- c0 = (c0 + lo) & BN_MASK2; \
- if (c0 < lo) \
- hi++; \
- c1 = (c1 + hi) & BN_MASK2; \
- if (c1 < hi) \
- c2++; \
- } while (0)
-
-#define sqr_add_c(a, i, c0, c1, c2) \
- do { \
- BN_ULONG lo, hi; \
- sqr64(lo, hi, (a)[i]); \
- c0 = (c0 + lo) & BN_MASK2; \
- if (c0 < lo) \
- hi++; \
- c1 = (c1 + hi) & BN_MASK2; \
- if (c1 < hi) \
- c2++; \
- } while (0)
-
-#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
#endif /* !BN_ULLONG */
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
diff --git a/src/crypto/bn/internal.h b/src/crypto/bn/internal.h
index 72ef4e95..0a2982c7 100644
--- a/src/crypto/bn/internal.h
+++ b/src/crypto/bn/internal.h
@@ -125,13 +125,15 @@
#include <openssl/base.h>
-#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
#pragma warning(push, 3)
#include <intrin.h>
#pragma warning(pop)
#pragma intrinsic(__umulh, _umul128)
#endif
+#include "../internal.h"
+
#if defined(__cplusplus)
extern "C" {
#endif
@@ -144,7 +146,7 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
#if !defined(_MSC_VER)
/* MSVC doesn't support two-word integers on 64-bit. */
-#define BN_ULLONG __uint128_t
+#define BN_ULLONG uint128_t
#endif
#define BN_BITS2 64
@@ -179,14 +181,6 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
#endif
-/* Pentium pro 16,16,16,32,64 */
-/* Alpha 16,16,16,16.64 */
-#define BN_MULL_SIZE_NORMAL (16) /* 32 */
-#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
-#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
-#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
-#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
-
#define STATIC_BIGNUM(x) \
{ \
(BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \
@@ -198,10 +192,14 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
#endif
+
+/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
+ * least significant word first. */
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
+
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
@@ -223,67 +221,12 @@ int bn_cmp_part_words(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);
-#if !defined(BN_ULLONG)
-
-#define LBITS(a) ((a) & BN_MASK2l)
-#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
-#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
-
-#define LLBITS(a) ((a) & BN_MASKl)
-#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
-#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
-
-#define mul64(l, h, bl, bh) \
- { \
- BN_ULONG m, m1, lt, ht; \
- \
- lt = l; \
- ht = h; \
- m = (bh) * (lt); \
- lt = (bl) * (lt); \
- m1 = (bl) * (ht); \
- ht = (bh) * (ht); \
- m = (m + m1) & BN_MASK2; \
- if (m < m1) \
- ht += L2HBITS((BN_ULONG)1); \
- ht += HBITS(m); \
- m1 = L2HBITS(m); \
- lt = (lt + m1) & BN_MASK2; \
- if (lt < m1) \
- ht++; \
- (l) = lt; \
- (h) = ht; \
- }
-
-#endif /* !defined(BN_ULLONG) */
+#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
+#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
+#endif
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
-# if defined(__GNUC__) && __GNUC__ >= 2
-# define BN_UMULT_HIGH(a,b) ({ \
- register BN_ULONG ret,discard; \
- __asm__ ("mulq %3" \
- : "=a"(discard),"=d"(ret) \
- : "a"(a), "g"(b) \
- : "cc"); \
- ret; })
-# define BN_UMULT_LOHI(low,high,a,b) \
- __asm__ ("mulq %3" \
- : "=a"(low),"=d"(high) \
- : "a"(a),"g"(b) \
- : "cc");
-# elif defined(_MSC_VER) && _MSC_VER >= 1400
-# define BN_UMULT_HIGH(a, b) __umulh((a), (b))
-# define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
-# endif
-#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
-# if defined(__GNUC__) && __GNUC__>=2
-# define BN_UMULT_HIGH(a,b) ({ \
- register BN_ULONG ret; \
- __asm__ ("umulh %0,%1,%2" \
- : "=r"(ret) \
- : "r"(a), "r"(b)); \
- ret; })
-# endif
+#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
+#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
#endif
diff --git a/src/crypto/bn/montgomery.c b/src/crypto/bn/montgomery.c
index 18da0dad..f56998e0 100644
--- a/src/crypto/bn/montgomery.c
+++ b/src/crypto/bn/montgomery.c
@@ -289,14 +289,14 @@ err:
return ret;
}
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
- const BIGNUM *mod, BN_CTX *bn_ctx) {
+int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+ const BIGNUM *mod, BN_CTX *bn_ctx) {
CRYPTO_MUTEX_lock_read(lock);
BN_MONT_CTX *ctx = *pmont;
CRYPTO_MUTEX_unlock(lock);
if (ctx) {
- return ctx;
+ return 1;
}
CRYPTO_MUTEX_lock_write(lock);
@@ -318,7 +318,7 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
out:
CRYPTO_MUTEX_unlock(lock);
- return ctx;
+ return ctx != NULL;
}
int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -326,14 +326,12 @@ int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
}
-#if 0
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
const BN_MONT_CTX *mont) {
- const BIGNUM *n;
BN_ULONG *ap, *np, *rp, n0, v, carry;
int nl, max, i;
- n = &mont->N;
+ const BIGNUM *n = &mont->N;
nl = n->top;
if (nl == 0) {
ret->top = 0;
@@ -376,13 +374,13 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
{
BN_ULONG *nrp;
- size_t m;
+ uintptr_t m;
v = bn_sub_words(rp, ap, np, nl) - carry;
/* if subtraction result is real, then trick unconditional memcpy below to
* perform in-place "refresh" instead of actual copy. */
- m = (0 - (size_t)v);
- nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
+ m = (0u - (uintptr_t)v);
+ nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m));
for (i = 0, nl -= 4; i < nl; i += 4) {
BN_ULONG t1, t2, t3, t4;
@@ -411,104 +409,25 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
return 1;
}
-#endif
-
-#define PTR_SIZE_INT size_t
-
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
- {
- BIGNUM *n;
- BN_ULONG *ap,*np,*rp,n0,v,carry;
- int nl,max,i;
-
- n= (BIGNUM*) &(mont->N);
- nl=n->top;
- if (nl == 0) { ret->top=0; return(1); }
- max=(2*nl); /* carry is stored separately */
- if (bn_wexpand(r,max) == NULL) return(0);
-
- r->neg^=n->neg;
- np=n->d;
- rp=r->d;
-
- /* clear the top words of T */
-#if 1
- for (i=r->top; i<max; i++) /* memset? XXX */
- rp[i]=0;
-#else
- memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
-#endif
-
- r->top=max;
- n0=mont->n0[0];
-
- for (carry=0, i=0; i<nl; i++, rp++)
- {
- v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
- v = (v+carry+rp[nl])&BN_MASK2;
- carry |= (v != rp[nl]);
- carry &= (v <= rp[nl]);
- rp[nl]=v;
- }
-
- if (bn_wexpand(ret,nl) == NULL) return(0);
- ret->top=nl;
- ret->neg=r->neg;
-
- rp=ret->d;
- ap=&(r->d[nl]);
-
- {
- BN_ULONG *nrp;
- size_t m;
-
- v=bn_sub_words(rp,ap,np,nl)-carry;
- /* if subtraction result is real, then
- * trick unconditional memcpy below to perform in-place
- * "refresh" instead of actual copy. */
- m=(0-(size_t)v);
- nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
-
- for (i=0,nl-=4; i<nl; 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 (nl+=4; i<nl; i++)
- rp[i]=nrp[i], ap[i]=0;
- }
- bn_correct_top(r);
- bn_correct_top(ret);
-
- return(1);
- }
-
-int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
+int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
BN_CTX *ctx) {
- int retn = 0;
+ int ret = 0;
BIGNUM *t;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
- if (t == NULL) {
- return 0;
+ if (t == NULL ||
+ !BN_copy(t, a)) {
+ goto err;
}
- if (BN_copy(t, a)) {
- retn = BN_from_montgomery_word(ret, t, mont);
- }
+ ret = BN_from_montgomery_word(r, t, mont);
+
+err:
BN_CTX_end(ctx);
- return retn;
+ return ret;
}
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
diff --git a/src/crypto/bn/mul.c b/src/crypto/bn/mul.c
index 029a59e2..06e53ee0 100644
--- a/src/crypto/bn/mul.c
+++ b/src/crypto/bn/mul.c
@@ -62,7 +62,12 @@
#include "internal.h"
-void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
+#define BN_MUL_RECURSIVE_SIZE_NORMAL 16
+#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
+
+
+static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
+ int nb) {
BN_ULONG *rr;
if (na < nb) {
@@ -107,31 +112,6 @@ void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
}
}
-void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
- bn_mul_words(r, a, n, b[0]);
-
- for (;;) {
- if (--n <= 0) {
- return;
- }
- bn_mul_add_words(&(r[1]), a, n, b[1]);
- if (--n <= 0) {
- return;
- }
- bn_mul_add_words(&(r[2]), a, n, b[2]);
- if (--n <= 0) {
- return;
- }
- bn_mul_add_words(&(r[3]), a, n, b[3]);
- if (--n <= 0) {
- return;
- }
- bn_mul_add_words(&(r[4]), a, n, b[4]);
- r += 4;
- b += 4;
- }
-}
-
#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
/* Here follows specialised variants of bn_add_words() and bn_sub_words(). They
* have the property performing operations on arrays of different sizes. The
@@ -618,7 +598,8 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
}
}
- if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
+ static const int kMulNormalSize = 16;
+ if (al >= kMulNormalSize && bl >= kMulNormalSize) {
if (i >= -1 && i <= 1) {
/* Find out the power of two lower or equal
to the longest of the two numbers */
diff --git a/src/crypto/bn/rsaz_exp.c b/src/crypto/bn/rsaz_exp.c
index c8027520..30f08e5f 100644
--- a/src/crypto/bn/rsaz_exp.c
+++ b/src/crypto/bn/rsaz_exp.c
@@ -48,6 +48,9 @@
#include <openssl/mem.h>
+#include "../internal.h"
+
+
/*
* See crypto/bn/asm/rsaz-avx2.pl for further details.
*/
@@ -58,42 +61,30 @@ void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i);
void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
void rsaz_1024_red2norm_avx2(void *norm,const void *red);
-#if defined(__GNUC__)
-# define ALIGN64 __attribute__((aligned(64)))
-#elif defined(_MSC_VER)
-# define ALIGN64 __declspec(align(64))
-#elif defined(__SUNPRO_C)
-# define ALIGN64
-# pragma align 64(one,two80)
-#else
-# define ALIGN64 /* not fatal, might hurt performance a little */
-#endif
-
-ALIGN64 static const BN_ULONG one[40] =
+alignas(64) static const BN_ULONG one[40] =
{1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-ALIGN64 static const BN_ULONG two80[40] =
+alignas(64) static const BN_ULONG two80[40] =
{0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
{
- unsigned char storage[320*3+32*9*16+64]; /* 5.5KB */
- unsigned char *p_str = storage + (64-((size_t)storage%64));
+ alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */
unsigned char *a_inv, *m, *result,
- *table_s = p_str+320*3,
+ *table_s = storage + (320 * 3),
*R2 = table_s; /* borrow */
int index;
int wvalue;
- if ((((size_t)p_str&4095)+320)>>12) {
- result = p_str;
- a_inv = p_str + 320;
- m = p_str + 320*2; /* should not cross page */
+ if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
+ result = storage;
+ a_inv = storage + 320;
+ m = storage + (320 * 2); /* should not cross page */
} else {
- m = p_str; /* should not cross page */
- result = p_str + 320;
- a_inv = p_str + 320*2;
+ m = storage; /* should not cross page */
+ result = storage + 320;
+ a_inv = storage + (320 * 2);
}
rsaz_1024_norm2red_avx2(m, m_norm);
@@ -224,8 +215,9 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
rsaz_1024_scatter5_avx2(table_s,result,31);
#endif
+ const uint8_t *p_str = (const uint8_t *)exponent;
+
/* load first window */
- p_str = (unsigned char*)exponent;
wvalue = p_str[127] >> 3;
rsaz_1024_gather5_avx2(result,table_s,wvalue);
@@ -235,7 +227,7 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
rsaz_1024_sqr_avx2(result, result, m, k0, 5);
- wvalue = *((unsigned short*)&p_str[index/8]);
+ wvalue = *((const unsigned short*)&p_str[index / 8]);
wvalue = (wvalue>> (index%8)) & 31;
index-=5;
@@ -274,11 +266,10 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
const BN_ULONG base[8], const BN_ULONG exponent[8],
const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8])
{
- unsigned char storage[16*8*8+64*2+64]; /* 1.2KB */
- unsigned char *table = storage + (64-((size_t)storage%64));
+ alignas(64) uint8_t storage[(16*8*8) + (64 * 2)]; /* 1.2KB */
+ unsigned char *table = storage;
BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8),
*temp = (BN_ULONG *)(table+16*8*8+8*8);
- unsigned char *p_str = (unsigned char*)exponent;
int index;
unsigned int wvalue;
@@ -300,6 +291,8 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
for (index=3; index<16; index++)
rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index);
+ const uint8_t *p_str = (const uint8_t *)exponent;
+
/* load first window */
wvalue = p_str[63];
diff --git a/src/crypto/bytestring/CMakeLists.txt b/src/crypto/bytestring/CMakeLists.txt
index 33d3c217..362e702f 100644
--- a/src/crypto/bytestring/CMakeLists.txt
+++ b/src/crypto/bytestring/CMakeLists.txt
@@ -5,6 +5,7 @@ add_library(
OBJECT
+ asn1_compat.c
ber.c
cbs.c
cbb.c
diff --git a/src/crypto/bytestring/asn1_compat.c b/src/crypto/bytestring/asn1_compat.c
new file mode 100644
index 00000000..b17d2d12
--- /dev/null
+++ b/src/crypto/bytestring/asn1_compat.c
@@ -0,0 +1,51 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+
+#include <openssl/bytestring.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
+ assert(cbb->base->can_resize);
+
+ uint8_t *der;
+ size_t der_len;
+ if (!CBB_finish(cbb, &der, &der_len)) {
+ CBB_cleanup(cbb);
+ return -1;
+ }
+ if (der_len > INT_MAX) {
+ OPENSSL_free(der);
+ return -1;
+ }
+ if (outp != NULL) {
+ if (*outp == NULL) {
+ *outp = der;
+ der = NULL;
+ } else {
+ memcpy(*outp, der, der_len);
+ *outp += der_len;
+ }
+ }
+ OPENSSL_free(der);
+ return (int)der_len;
+}
diff --git a/src/crypto/bytestring/ber.c b/src/crypto/bytestring/ber.c
index 9e8daaa5..04fcac6a 100644
--- a/src/crypto/bytestring/ber.c
+++ b/src/crypto/bytestring/ber.c
@@ -14,6 +14,7 @@
#include <openssl/bytestring.h>
+#include <assert.h>
#include <string.h>
#include "internal.h"
@@ -24,11 +25,37 @@
* input could otherwise cause the stack to overflow. */
static const unsigned kMaxDepth = 2048;
+/* is_string_type returns one if |tag| is a string type and zero otherwise. It
+ * ignores the constructed bit. */
+static int is_string_type(unsigned tag) {
+ if ((tag & 0xc0) != 0) {
+ return 0;
+ }
+ switch (tag & 0x1f) {
+ case CBS_ASN1_BITSTRING:
+ case CBS_ASN1_OCTETSTRING:
+ case CBS_ASN1_UTF8STRING:
+ case CBS_ASN1_NUMERICSTRING:
+ case CBS_ASN1_PRINTABLESTRING:
+ case CBS_ASN1_T16STRING:
+ case CBS_ASN1_VIDEOTEXSTRING:
+ case CBS_ASN1_IA5STRING:
+ case CBS_ASN1_GRAPHICSTRING:
+ case CBS_ASN1_VISIBLESTRING:
+ case CBS_ASN1_GENERALSTRING:
+ case CBS_ASN1_UNIVERSALSTRING:
+ case CBS_ASN1_BMPSTRING:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
- * depending on whether an indefinite length element was found. The value of
- * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
- * and zero on error. */
-static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
+ * depending on whether an indefinite length element or constructed string was
+ * found. The value of |orig_in| is not changed. It returns one on success (i.e.
+ * |*ber_found| was set) and zero on error. */
+static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
CBS in;
if (depth > kMaxDepth) {
@@ -49,10 +76,16 @@ static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
if (CBS_len(&contents) == header_len &&
header_len > 0 &&
CBS_data(&contents)[header_len-1] == 0x80) {
+ /* Found an indefinite-length element. */
*ber_found = 1;
return 1;
}
if (tag & CBS_ASN1_CONSTRUCTED) {
+ if (is_string_type(tag)) {
+ /* Constructed strings are only legal in BER and require conversion. */
+ *ber_found = 1;
+ return 1;
+ }
if (!CBS_skip(&contents, header_len) ||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
return 0;
@@ -63,16 +96,6 @@ static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
return 1;
}
-/* is_primitive_type returns true if |tag| likely a primitive type. Normally
- * one can just test the "constructed" bit in the tag but, in BER, even
- * primitive tags can have the constructed bit if they have indefinite
- * length. */
-static char is_primitive_type(unsigned tag) {
- return (tag & 0xc0) == 0 &&
- (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
- (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
-}
-
/* is_eoc returns true if |header_len| and |contents|, as returned by
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
static char is_eoc(size_t header_len, CBS *contents) {
@@ -81,92 +104,65 @@ static char is_eoc(size_t header_len, CBS *contents) {
}
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
- * |squash_header| is set then the top-level of elements from |in| will not
- * have their headers written. This is used when concatenating the fragments of
- * an indefinite length, primitive value. If |looking_for_eoc| is set then any
- * EOC elements found will cause the function to return after consuming it.
- * It returns one on success and zero on error. */
-static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
+ * |string_tag| is non-zero, then all elements must match |string_tag| up to the
+ * constructed bit and primitive element bodies are written to |out| without
+ * element headers. This is used when concatenating the fragments of a
+ * constructed string. If |looking_for_eoc| is set then any EOC elements found
+ * will cause the function to return after consuming it. It returns one on
+ * success and zero on error. */
+static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
char looking_for_eoc, unsigned depth) {
+ assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
+
if (depth > kMaxDepth) {
return 0;
}
while (CBS_len(in) > 0) {
CBS contents;
- unsigned tag;
+ unsigned tag, child_string_tag = string_tag;
size_t header_len;
CBB *out_contents, out_contents_storage;
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
return 0;
}
- out_contents = out;
- if (CBS_len(&contents) == header_len) {
- if (is_eoc(header_len, &contents)) {
- return looking_for_eoc;
- }
+ if (is_eoc(header_len, &contents)) {
+ return looking_for_eoc;
+ }
- if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
- /* This is an indefinite length element. If it's a SEQUENCE or SET then
- * we just need to write the out the contents as normal, but with a
- * concrete length prefix.
- *
- * If it's a something else then the contents will be a series of BER
- * elements of the same type which need to be concatenated. */
- const char context_specific = (tag & 0xc0) == 0x80;
- char squash_child_headers = is_primitive_type(tag);
-
- /* This is a hack, but it sufficies to handle NSS's output. If we find
- * an indefinite length, context-specific tag with a definite, primitive
- * tag inside it, then we assume that the context-specific tag is
- * implicit and the tags within are fragments of a primitive type that
- * need to be concatenated. */
- if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
- CBS in_copy, inner_contents;
- unsigned inner_tag;
- size_t inner_header_len;
-
- CBS_init(&in_copy, CBS_data(in), CBS_len(in));
- if (!CBS_get_any_ber_asn1_element(&in_copy, &inner_contents,
- &inner_tag, &inner_header_len)) {
- return 0;
- }
- if (CBS_len(&inner_contents) > inner_header_len &&
- is_primitive_type(inner_tag)) {
- squash_child_headers = 1;
- }
- }
-
- if (!squash_header) {
- unsigned out_tag = tag;
- if (squash_child_headers) {
- out_tag &= ~CBS_ASN1_CONSTRUCTED;
- }
- if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
- return 0;
- }
- out_contents = &out_contents_storage;
- }
-
- if (!cbs_convert_ber(in, out_contents,
- squash_child_headers,
- 1 /* looking for eoc */, depth + 1)) {
- return 0;
- }
- if (out_contents != out && !CBB_flush(out)) {
- return 0;
- }
- continue;
+ if (string_tag != 0) {
+ /* This is part of a constructed string. All elements must match
+ * |string_tag| up to the constructed bit and get appended to |out|
+ * without a child element. */
+ if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
+ return 0;
+ }
+ out_contents = out;
+ } else {
+ unsigned out_tag = tag;
+ if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
+ /* If a constructed string, clear the constructed bit and inform
+ * children to concatenate bodies. */
+ out_tag &= ~CBS_ASN1_CONSTRUCTED;
+ child_string_tag = out_tag;
+ }
+ if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
+ return 0;
}
+ out_contents = &out_contents_storage;
}
- if (!squash_header) {
- if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
+ if (CBS_len(&contents) == header_len && header_len > 0 &&
+ CBS_data(&contents)[header_len - 1] == 0x80) {
+ /* This is an indefinite length element. */
+ if (!cbs_convert_ber(in, out_contents, child_string_tag,
+ 1 /* looking for eoc */, depth + 1) ||
+ !CBB_flush(out)) {
return 0;
}
- out_contents = &out_contents_storage;
+ continue;
}
if (!CBS_skip(&contents, header_len)) {
@@ -174,18 +170,20 @@ static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
}
if (tag & CBS_ASN1_CONSTRUCTED) {
- if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
+ /* Recurse into children. */
+ if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
0 /* not looking for eoc */, depth + 1)) {
return 0;
}
} else {
+ /* Copy primitive contents as-is. */
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
CBS_len(&contents))) {
return 0;
}
}
- if (out_contents != out && !CBB_flush(out)) {
+ if (!CBB_flush(out)) {
return 0;
}
}
@@ -209,13 +207,57 @@ int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
return 1;
}
- if (!CBB_init(&cbb, CBS_len(in))) {
- return 0;
- }
- if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
+ if (!CBB_init(&cbb, CBS_len(in)) ||
+ !cbs_convert_ber(in, &cbb, 0, 0, 0) ||
+ !CBB_finish(&cbb, out, out_len)) {
CBB_cleanup(&cbb);
return 0;
}
- return CBB_finish(&cbb, out, out_len);
+ return 1;
+}
+
+int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
+ unsigned outer_tag, unsigned inner_tag) {
+ assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
+ assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
+ assert(is_string_type(inner_tag));
+
+ if (CBS_peek_asn1_tag(in, outer_tag)) {
+ /* Normal implicitly-tagged string. */
+ *out_storage = NULL;
+ return CBS_get_asn1(in, out, outer_tag);
+ }
+
+ /* Otherwise, try to parse an implicitly-tagged constructed string.
+ * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
+ * of nesting. */
+ CBB result;
+ CBS child;
+ if (!CBB_init(&result, CBS_len(in)) ||
+ !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
+ goto err;
+ }
+
+ while (CBS_len(&child) > 0) {
+ CBS chunk;
+ if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
+ !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
+ goto err;
+ }
+ }
+
+ uint8_t *data;
+ size_t len;
+ if (!CBB_finish(&result, &data, &len)) {
+ goto err;
+ }
+
+ CBS_init(out, data, len);
+ *out_storage = data;
+ return 1;
+
+err:
+ CBB_cleanup(&result);
+ return 0;
}
diff --git a/src/crypto/bytestring/bytestring_test.cc b/src/crypto/bytestring/bytestring_test.cc
index 188c63d5..84ecffcd 100644
--- a/src/crypto/bytestring/bytestring_test.cc
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -579,7 +579,7 @@ static bool TestBerConvert() {
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
- // kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
+ // kOctetStringBER contains an indefinite length OCTET STRING with two parts.
// These parts need to be concatenated in DER form.
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
0x04, 0x02, 2, 3, 0x00, 0x00};
@@ -609,6 +609,16 @@ static bool TestBerConvert() {
0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
};
+ // kConstructedStringBER contains a deeply-nested constructed OCTET STRING.
+ // The BER conversion collapses this to one level deep, but not completely.
+ static const uint8_t kConstructedStringBER[] = {
+ 0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01,
+ 0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03,
+ };
+ static const uint8_t kConstructedStringDER[] = {
+ 0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03,
+ };
+
return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
kSimpleBER, sizeof(kSimpleBER)) &&
DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
@@ -617,7 +627,59 @@ static bool TestBerConvert() {
sizeof(kOctetStringDER), kOctetStringBER,
sizeof(kOctetStringBER)) &&
DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
- sizeof(kNSSBER));
+ sizeof(kNSSBER)) &&
+ DoBerConvert("kConstructedStringBER", kConstructedStringDER,
+ sizeof(kConstructedStringDER), kConstructedStringBER,
+ sizeof(kConstructedStringBER));
+}
+
+struct ImplicitStringTest {
+ const char *in;
+ size_t in_len;
+ bool ok;
+ const char *out;
+ size_t out_len;
+};
+
+static const ImplicitStringTest kImplicitStringTests[] = {
+ // A properly-encoded string.
+ {"\x80\x03\x61\x61\x61", 5, true, "aaa", 3},
+ // An implicit-tagged string.
+ {"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3},
+ // |CBS_get_asn1_implicit_string| only accepts one level deep of nesting.
+ {"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr,
+ 0},
+ // The outer tag must match.
+ {"\x81\x03\x61\x61\x61", 5, false, nullptr, 0},
+ {"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0},
+ // The inner tag must match.
+ {"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0},
+};
+
+static bool TestImplicitString() {
+ for (const auto &test : kImplicitStringTests) {
+ uint8_t *storage = nullptr;
+ CBS in, out;
+ CBS_init(&in, reinterpret_cast<const uint8_t *>(test.in), test.in_len);
+ int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
+ CBS_ASN1_CONTEXT_SPECIFIC | 0,
+ CBS_ASN1_OCTETSTRING);
+ ScopedOpenSSLBytes scoper(storage);
+
+ if (static_cast<bool>(ok) != test.ok) {
+ fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
+ ok ? "succeeded" : "failed");
+ return false;
+ }
+
+ if (ok && (CBS_len(&out) != test.out_len ||
+ memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
+ fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
+ return false;
+ }
+ }
+
+ return true;
}
struct ASN1Uint64Test {
@@ -747,6 +809,7 @@ int main(void) {
!TestCBBDiscardChild() ||
!TestCBBASN1() ||
!TestBerConvert() ||
+ !TestImplicitString() ||
!TestASN1Uint64() ||
!TestGetOptionalASN1Bool() ||
!TestZero() ||
diff --git a/src/crypto/bytestring/cbs.c b/src/crypto/bytestring/cbs.c
index 5e0c538a..ed54b499 100644
--- a/src/crypto/bytestring/cbs.c
+++ b/src/crypto/bytestring/cbs.c
@@ -181,8 +181,14 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return 0;
}
+ /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
+ * number no greater than 30.
+ *
+ * If the number portion is 31 (0x1f, the largest value that fits in the
+ * allotted bits), then the tag is more than one byte long and the
+ * continuation bytes contain the tag number. This parser only supports tag
+ * numbers less than 31 (and thus single-byte tags). */
if ((tag & 0x1f) == 0x1f) {
- /* Long form tags are not supported. */
return 0;
}
@@ -191,6 +197,8 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
}
size_t len;
+ /* The format for the length encoding is specified in ITU-T X.690 section
+ * 8.1.3. */
if ((length_byte & 0x80) == 0) {
/* Short form length. */
len = ((size_t) length_byte) + 2;
@@ -198,7 +206,9 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
*out_header_len = 2;
}
} else {
- /* Long form length. */
+ /* The high bit indicate that this is the long form, while the next 7 bits
+ * encode the number of subsequent octets used to encode the length (ITU-T
+ * X.690 clause 8.1.3.5.b). */
const size_t num_bytes = length_byte & 0x7f;
uint32_t len32;
@@ -210,12 +220,18 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return CBS_get_bytes(cbs, out, 2);
}
+ /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
+ * used as the first byte of the length. If this parser encounters that
+ * value, num_bytes will be parsed as 127, which will fail the check below.
+ */
if (num_bytes == 0 || num_bytes > 4) {
return 0;
}
if (!cbs_get_u(&header, &len32, num_bytes)) {
return 0;
}
+ /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+ * with the minimum number of octets. */
if (len32 < 128) {
/* Length should have used short-form encoding. */
return 0;
diff --git a/src/crypto/bytestring/internal.h b/src/crypto/bytestring/internal.h
index b4ea7e51..2fed4139 100644
--- a/src/crypto/bytestring/internal.h
+++ b/src/crypto/bytestring/internal.h
@@ -22,22 +22,51 @@ extern "C" {
#endif
-/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
- * indefinite-length elements then it attempts to convert the BER data to DER
- * and sets |*out| and |*out_length| to describe a malloced buffer containing
- * the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
+/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
+ * indefinite-length elements or constructed strings then it converts the BER
+ * data to DER and sets |*out| and |*out_length| to describe a malloced buffer
+ * containing the DER data. Additionally, |*in| will be advanced over the BER
+ * element.
*
- * If it doesn't find any indefinite-length elements then it sets |*out| to
- * NULL and |*in| is unmodified.
+ * If it doesn't find any indefinite-length elements or constructed strings then
+ * it sets |*out| to NULL and |*in| is unmodified.
*
- * A sufficiently complex ASN.1 structure will break this function because it's
- * not possible to generically convert BER to DER without knowledge of the
- * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
- * from NSS.
+ * This function should successfully process any valid BER input, however it
+ * will not convert all of BER's deviations from DER. BER is ambiguous between
+ * implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
+ * strings. Implicitly-tagged strings must be parsed with
+ * |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
+ * must also account for BER variations in the contents of a primitive.
*
* It returns one on success and zero otherwise. */
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
+/* CBS_get_asn1_implicit_string parses a BER string of primitive type
+ * |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
+ * contents. If concatenation was needed, it sets |*out_storage| to a buffer
+ * which the caller must release with |OPENSSL_free|. Otherwise, it sets
+ * |*out_storage| to NULL.
+ *
+ * This function does not parse all of BER. It requires the string be
+ * definite-length. Constructed strings are allowed, but all children of the
+ * outermost element must be primitive. The caller should use
+ * |CBS_asn1_ber_to_der| before running this function.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
+ uint8_t **out_storage,
+ unsigned outer_tag,
+ unsigned inner_tag);
+
+/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
+ * with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
+ * and |*outp| is advanced just past the output. It returns the number of bytes
+ * in the result, whether written or not, or a negative value on error. On
+ * error, it calls |CBB_cleanup| on |cbb|.
+ *
+ * This function may be used to help implement legacy i2d ASN.1 functions. */
+int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/crypto/chacha/CMakeLists.txt b/src/crypto/chacha/CMakeLists.txt
index 266e8699..39d1defb 100644
--- a/src/crypto/chacha/CMakeLists.txt
+++ b/src/crypto/chacha/CMakeLists.txt
@@ -4,7 +4,31 @@ if (${ARCH} STREQUAL "arm")
set(
CHACHA_ARCH_SOURCES
- chacha_vec_arm.S
+ chacha-armv4.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-armv8.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-x86.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-x86_64.${ASM_EXT}
)
endif()
@@ -13,8 +37,22 @@ add_library(
OBJECT
- chacha_generic.c
- chacha_vec.c
+ chacha.c
${CHACHA_ARCH_SOURCES}
)
+
+add_executable(
+ chacha_test
+
+ chacha_test.cc
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(chacha_test crypto)
+add_dependencies(all_tests chacha_test)
+
+perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl)
+perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl)
+perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl)
+perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl) \ No newline at end of file
diff --git a/src/crypto/chacha/asm/chacha-armv4.pl b/src/crypto/chacha/asm/chacha-armv4.pl
new file mode 100755
index 00000000..b190445d
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-armv4.pl
@@ -0,0 +1,1151 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# December 2014
+#
+# ChaCha20 for ARMv4.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc-4.4 1xNEON 3xNEON+1xIALU
+#
+# Cortex-A5 19.3(*)/+95% 21.8 14.1
+# Cortex-A8 10.5(*)/+160% 13.9 6.35
+# Cortex-A9 12.9(**)/+110% 14.3 6.50
+# Cortex-A15 11.0/+40% 16.0 5.00
+# Snapdragon S4 11.5/+125% 13.6 4.90
+#
+# (*) most "favourable" result for aligned data on little-endian
+# processor, result for misaligned data is 10-15% lower;
+# (**) this result is a trade-off: it can be improved by 20%,
+# but then Snapdragon S4 and Cortex-A8 results get
+# 20-25% worse;
+
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x"));
+my @t=map("r$_",(8..11));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my $odd = $d0&1;
+my ($xc,$xc_) = (@t[0..1]);
+my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]);
+my @ret;
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' are permanently allocated in registers, @x[0..7],
+ # while 'c's and pair of 'd's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end. If you observe 'd' column, you'll
+ # notice that 15 and 13 are reused in next pair of rounds.
+ # This is why these two are chosen for offloading to memory,
+ # to make loads count more.
+ push @ret,(
+ "&add (@x[$a0],@x[$a0],@x[$b0])",
+ "&mov ($xd,$xd,'ror#16')",
+ "&add (@x[$a1],@x[$a1],@x[$b1])",
+ "&mov ($xd_,$xd_,'ror#16')",
+ "&eor ($xd,$xd,@x[$a0],'ror#16')",
+ "&eor ($xd_,$xd_,@x[$a1],'ror#16')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b0],@x[$b0],'ror#20')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b1],@x[$b1],'ror#20')",
+ "&eor (@x[$b0],@x[$b0],$xc,'ror#20')",
+ "&eor (@x[$b1],@x[$b1],$xc_,'ror#20')",
+
+ "&add (@x[$a0],@x[$a0],@x[$b0])",
+ "&mov ($xd,$xd,'ror#24')",
+ "&add (@x[$a1],@x[$a1],@x[$b1])",
+ "&mov ($xd_,$xd_,'ror#24')",
+ "&eor ($xd,$xd,@x[$a0],'ror#24')",
+ "&eor ($xd_,$xd_,@x[$a1],'ror#24')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b0],@x[$b0],'ror#25')" );
+ push @ret,(
+ "&str ($xd,'[sp,#4*(16+$d0)]')",
+ "&ldr ($xd,'[sp,#4*(16+$d2)]')" ) if ($odd);
+ push @ret,(
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b1],@x[$b1],'ror#25')" );
+ push @ret,(
+ "&str ($xd_,'[sp,#4*(16+$d1)]')",
+ "&ldr ($xd_,'[sp,#4*(16+$d3)]')" ) if (!$odd);
+ push @ret,(
+ "&eor (@x[$b0],@x[$b0],$xc,'ror#25')",
+ "&eor (@x[$b1],@x[$b1],$xc_,'ror#25')" );
+
+ $xd=@x[$d2] if (!$odd);
+ $xd_=@x[$d3] if ($odd);
+ push @ret,(
+ "&str ($xc,'[sp,#4*(16+$c0)]')",
+ "&ldr ($xc,'[sp,#4*(16+$c2)]')",
+ "&add (@x[$a2],@x[$a2],@x[$b2])",
+ "&mov ($xd,$xd,'ror#16')",
+ "&str ($xc_,'[sp,#4*(16+$c1)]')",
+ "&ldr ($xc_,'[sp,#4*(16+$c3)]')",
+ "&add (@x[$a3],@x[$a3],@x[$b3])",
+ "&mov ($xd_,$xd_,'ror#16')",
+ "&eor ($xd,$xd,@x[$a2],'ror#16')",
+ "&eor ($xd_,$xd_,@x[$a3],'ror#16')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b2],@x[$b2],'ror#20')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b3],@x[$b3],'ror#20')",
+ "&eor (@x[$b2],@x[$b2],$xc,'ror#20')",
+ "&eor (@x[$b3],@x[$b3],$xc_,'ror#20')",
+
+ "&add (@x[$a2],@x[$a2],@x[$b2])",
+ "&mov ($xd,$xd,'ror#24')",
+ "&add (@x[$a3],@x[$a3],@x[$b3])",
+ "&mov ($xd_,$xd_,'ror#24')",
+ "&eor ($xd,$xd,@x[$a2],'ror#24')",
+ "&eor ($xd_,$xd_,@x[$a3],'ror#24')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b2],@x[$b2],'ror#25')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b3],@x[$b3],'ror#25')",
+ "&eor (@x[$b2],@x[$b2],$xc,'ror#25')",
+ "&eor (@x[$b3],@x[$b3],$xc_,'ror#25')" );
+
+ @ret;
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+#else
+.code 32
+#endif
+
+#if defined(__thumb2__) || defined(__clang__)
+#define ldrhsb ldrbhs
+#endif
+
+.align 5
+.Lsigma:
+.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral
+.Lone:
+.long 1,0,0,0
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-.LChaCha20_ctr32
+#else
+.word -1
+#endif
+
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,%function
+.align 5
+ChaCha20_ctr32:
+.LChaCha20_ctr32:
+ ldr r12,[sp,#0] @ pull pointer to counter and nonce
+ stmdb sp!,{r0-r2,r4-r11,lr}
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+ sub r14,pc,#16 @ ChaCha20_ctr32
+#else
+ adr r14,.LChaCha20_ctr32
+#endif
+ cmp r2,#0 @ len==0?
+#ifdef __thumb2__
+ itt eq
+#endif
+ addeq sp,sp,#4*3
+ beq .Lno_data
+#if __ARM_MAX_ARCH__>=7
+ cmp r2,#192 @ test len
+ bls .Lshort
+ ldr r4,[r14,#-32]
+ ldr r4,[r14,r4]
+# ifdef __APPLE__
+ ldr r4,[r4]
+# endif
+ tst r4,#ARMV7_NEON
+ bne .LChaCha20_neon
+.Lshort:
+#endif
+ ldmia r12,{r4-r7} @ load counter and nonce
+ sub sp,sp,#4*(16) @ off-load area
+ sub r14,r14,#64 @ .Lsigma
+ stmdb sp!,{r4-r7} @ copy counter and nonce
+ ldmia r3,{r4-r11} @ load key
+ ldmia r14,{r0-r3} @ load sigma
+ stmdb sp!,{r4-r11} @ copy key
+ stmdb sp!,{r0-r3} @ copy sigma
+ str r10,[sp,#4*(16+10)] @ off-load "@x[10]"
+ str r11,[sp,#4*(16+11)] @ off-load "@x[11]"
+ b .Loop_outer_enter
+
+.align 4
+.Loop_outer:
+ ldmia sp,{r0-r9} @ load key material
+ str @t[3],[sp,#4*(32+2)] @ save len
+ str r12, [sp,#4*(32+1)] @ save inp
+ str r14, [sp,#4*(32+0)] @ save out
+.Loop_outer_enter:
+ ldr @t[3], [sp,#4*(15)]
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ ldr @t[2], [sp,#4*(13)]
+ ldr @x[14],[sp,#4*(14)]
+ str @t[3], [sp,#4*(16+15)]
+ mov @t[3],#10
+ b .Loop
+
+.align 4
+.Loop:
+ subs @t[3],@t[3],#1
+___
+ foreach (&ROUND(0, 4, 8,12)) { eval; }
+ foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ bne .Loop
+
+ ldr @t[3],[sp,#4*(32+2)] @ load len
+
+ str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store
+ str @t[1], [sp,#4*(16+9)]
+ str @x[12],[sp,#4*(16+12)]
+ str @t[2], [sp,#4*(16+13)]
+ str @x[14],[sp,#4*(16+14)]
+
+ @ at this point we have first half of 512-bit result in
+ @ @x[0-7] and second half at sp+4*(16+8)
+
+ cmp @t[3],#64 @ done yet?
+#ifdef __thumb2__
+ itete lo
+#endif
+ addlo r12,sp,#4*(0) @ shortcut or ...
+ ldrhs r12,[sp,#4*(32+1)] @ ... load inp
+ addlo r14,sp,#4*(0) @ shortcut or ...
+ ldrhs r14,[sp,#4*(32+0)] @ ... load out
+
+ ldr @t[0],[sp,#4*(0)] @ load key material
+ ldr @t[1],[sp,#4*(1)]
+
+#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
+# if __ARM_ARCH__<7
+ orr @t[2],r12,r14
+ tst @t[2],#3 @ are input and output aligned?
+ ldr @t[2],[sp,#4*(2)]
+ bne .Lunaligned
+ cmp @t[3],#64 @ restore flags
+# else
+ ldr @t[2],[sp,#4*(2)]
+# endif
+ ldr @t[3],[sp,#4*(3)]
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @x[1],@x[1],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[0],@x[0],@t[0] @ xor with input
+ eorhs @x[1],@x[1],@t[1]
+ add @t[0],sp,#4*(4)
+ str @x[0],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[2],@x[2],@t[2]
+ eorhs @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[1],[r14,#-12]
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[4],@x[4],@t[0]
+ eorhs @x[5],@x[5],@t[1]
+ add @t[0],sp,#4*(8)
+ str @x[4],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[6],@x[6],@t[2]
+ eorhs @x[7],@x[7],@t[3]
+ str @x[5],[r14,#-12]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[6],[r14,#-8]
+ add @x[0],sp,#4*(16+8)
+ str @x[7],[r14,#-4]
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @x[1],@x[1],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+# ifdef __thumb2__
+ itt hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[0],@x[0],@t[0]
+ eorhs @x[1],@x[1],@t[1]
+ add @t[0],sp,#4*(12)
+ str @x[0],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[2],@x[2],@t[2]
+ eorhs @x[3],@x[3],@t[3]
+ str @x[1],[r14,#-12]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi @t[0],@t[0],#1 @ next counter value
+ strhi @t[0],[sp,#4*(12)] @ save next counter value
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[4],@x[4],@t[0]
+ eorhs @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ it ne
+# endif
+ ldrne @t[0],[sp,#4*(32+2)] @ re-load len
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[6],@x[6],@t[2]
+ eorhs @x[7],@x[7],@t[3]
+ str @x[4],[r14],#16 @ store output
+ str @x[5],[r14,#-12]
+# ifdef __thumb2__
+ it hs
+# endif
+ subhs @t[3],@t[0],#64 @ len-=64
+ str @x[6],[r14,#-8]
+ str @x[7],[r14,#-4]
+ bhi .Loop_outer
+
+ beq .Ldone
+# if __ARM_ARCH__<7
+ b .Ltail
+
+.align 4
+.Lunaligned: @ unaligned endian-neutral path
+ cmp @t[3],#64 @ restore flags
+# endif
+#endif
+#if __ARM_ARCH__<7
+ ldr @t[3],[sp,#4*(3)]
+___
+for ($i=0;$i<16;$i+=4) {
+my $j=$i&0x7;
+
+$code.=<<___ if ($i==4);
+ add @x[0],sp,#4*(16+8)
+___
+$code.=<<___ if ($i==8);
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+# ifdef __thumb2__
+ itt hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]"
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]"
+___
+$code.=<<___;
+ add @x[$j+0],@x[$j+0],@t[0] @ accumulate key material
+___
+$code.=<<___ if ($i==12);
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi @t[0],@t[0],#1 @ next counter value
+ strhi @t[0],[sp,#4*(12)] @ save next counter value
+___
+$code.=<<___;
+ add @x[$j+1],@x[$j+1],@t[1]
+ add @x[$j+2],@x[$j+2],@t[2]
+# ifdef __thumb2__
+ itete lo
+# endif
+ eorlo @t[0],@t[0],@t[0] @ zero or ...
+ ldrhsb @t[0],[r12],#16 @ ... load input
+ eorlo @t[1],@t[1],@t[1]
+ ldrhsb @t[1],[r12,#-12]
+
+ add @x[$j+3],@x[$j+3],@t[3]
+# ifdef __thumb2__
+ itete lo
+# endif
+ eorlo @t[2],@t[2],@t[2]
+ ldrhsb @t[2],[r12,#-8]
+ eorlo @t[3],@t[3],@t[3]
+ ldrhsb @t[3],[r12,#-4]
+
+ eor @x[$j+0],@t[0],@x[$j+0] @ xor with input (or zero)
+ eor @x[$j+1],@t[1],@x[$j+1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-15] @ load more input
+ ldrhsb @t[1],[r12,#-11]
+ eor @x[$j+2],@t[2],@x[$j+2]
+ strb @x[$j+0],[r14],#16 @ store output
+ eor @x[$j+3],@t[3],@x[$j+3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-7]
+ ldrhsb @t[3],[r12,#-3]
+ strb @x[$j+1],[r14,#-12]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+2],[r14,#-8]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-14] @ load more input
+ ldrhsb @t[1],[r12,#-10]
+ strb @x[$j+3],[r14,#-4]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+0],[r14,#-15]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-6]
+ ldrhsb @t[3],[r12,#-2]
+ strb @x[$j+1],[r14,#-11]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+2],[r14,#-7]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-13] @ load more input
+ ldrhsb @t[1],[r12,#-9]
+ strb @x[$j+3],[r14,#-3]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+0],[r14,#-14]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-5]
+ ldrhsb @t[3],[r12,#-1]
+ strb @x[$j+1],[r14,#-10]
+ strb @x[$j+2],[r14,#-6]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+3],[r14,#-2]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+ strb @x[$j+0],[r14,#-13]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+1],[r14,#-9]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+ strb @x[$j+2],[r14,#-5]
+ strb @x[$j+3],[r14,#-1]
+___
+$code.=<<___ if ($i<12);
+ add @t[0],sp,#4*(4+$i)
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+___
+}
+$code.=<<___;
+# ifdef __thumb2__
+ it ne
+# endif
+ ldrne @t[0],[sp,#4*(32+2)] @ re-load len
+# ifdef __thumb2__
+ it hs
+# endif
+ subhs @t[3],@t[0],#64 @ len-=64
+ bhi .Loop_outer
+
+ beq .Ldone
+#endif
+
+.Ltail:
+ ldr r12,[sp,#4*(32+1)] @ load inp
+ add @t[1],sp,#4*(0)
+ ldr r14,[sp,#4*(32+0)] @ load out
+
+.Loop_tail:
+ ldrb @t[2],[@t[1]],#1 @ read buffer on stack
+ ldrb @t[3],[r12],#1 @ read input
+ subs @t[0],@t[0],#1
+ eor @t[3],@t[3],@t[2]
+ strb @t[3],[r14],#1 @ store output
+ bne .Loop_tail
+
+.Ldone:
+ add sp,sp,#4*(32+3)
+.Lno_data:
+ ldmia sp!,{r4-r11,pc}
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) =
+ map("q$_",(0..15));
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+ (
+ "&vadd_i32 ($a,$a,$b)",
+ "&veor ($d,$d,$a)",
+ "&vrev32_16 ($d,$d)", # vrot ($d,16)
+
+ "&vadd_i32 ($c,$c,$d)",
+ "&veor ($t,$b,$c)",
+ "&vshr_u32 ($b,$t,20)",
+ "&vsli_32 ($b,$t,12)",
+
+ "&vadd_i32 ($a,$a,$b)",
+ "&veor ($t,$d,$a)",
+ "&vshr_u32 ($d,$t,24)",
+ "&vsli_32 ($d,$t,8)",
+
+ "&vadd_i32 ($c,$c,$d)",
+ "&veor ($t,$b,$c)",
+ "&vshr_u32 ($b,$t,25)",
+ "&vsli_32 ($b,$t,7)",
+
+ "&vext_8 ($c,$c,$c,8)",
+ "&vext_8 ($b,$b,$b,$odd?12:4)",
+ "&vext_8 ($d,$d,$d,$odd?4:12)"
+ );
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type ChaCha20_neon,%function
+.align 5
+ChaCha20_neon:
+ ldr r12,[sp,#0] @ pull pointer to counter and nonce
+ stmdb sp!,{r0-r2,r4-r11,lr}
+.LChaCha20_neon:
+ adr r14,.Lsigma
+ vstmdb sp!,{d8-d15} @ ABI spec says so
+ stmdb sp!,{r0-r3}
+
+ vld1.32 {$b0-$c0},[r3] @ load key
+ ldmia r3,{r4-r11} @ load key
+
+ sub sp,sp,#4*(16+16)
+ vld1.32 {$d0},[r12] @ load counter and nonce
+ add r12,sp,#4*8
+ ldmia r14,{r0-r3} @ load sigma
+ vld1.32 {$a0},[r14]! @ load sigma
+ vld1.32 {$t0},[r14] @ one
+ vst1.32 {$c0-$d0},[r12] @ copy 1/2key|counter|nonce
+ vst1.32 {$a0-$b0},[sp] @ copy sigma|1/2key
+
+ str r10,[sp,#4*(16+10)] @ off-load "@x[10]"
+ str r11,[sp,#4*(16+11)] @ off-load "@x[11]"
+ vshl.i32 $t1#lo,$t0#lo,#1 @ two
+ vstr $t0#lo,[sp,#4*(16+0)]
+ vshl.i32 $t2#lo,$t0#lo,#2 @ four
+ vstr $t1#lo,[sp,#4*(16+2)]
+ vmov $a1,$a0
+ vstr $t2#lo,[sp,#4*(16+4)]
+ vmov $a2,$a0
+ vmov $b1,$b0
+ vmov $b2,$b0
+ b .Loop_neon_enter
+
+.align 4
+.Loop_neon_outer:
+ ldmia sp,{r0-r9} @ load key material
+ cmp @t[3],#64*2 @ if len<=64*2
+ bls .Lbreak_neon @ switch to integer-only
+ vmov $a1,$a0
+ str @t[3],[sp,#4*(32+2)] @ save len
+ vmov $a2,$a0
+ str r12, [sp,#4*(32+1)] @ save inp
+ vmov $b1,$b0
+ str r14, [sp,#4*(32+0)] @ save out
+ vmov $b2,$b0
+.Loop_neon_enter:
+ ldr @t[3], [sp,#4*(15)]
+ vadd.i32 $d1,$d0,$t0 @ counter+1
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ vmov $c1,$c0
+ ldr @t[2], [sp,#4*(13)]
+ vmov $c2,$c0
+ ldr @x[14],[sp,#4*(14)]
+ vadd.i32 $d2,$d1,$t0 @ counter+2
+ str @t[3], [sp,#4*(16+15)]
+ mov @t[3],#10
+ add @x[12],@x[12],#3 @ counter+3
+ b .Loop_neon
+
+.align 4
+.Loop_neon:
+ subs @t[3],@t[3],#1
+___
+ my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0);
+ my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0);
+ my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0);
+ my @thread3=&ROUND(0,4,8,12);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+
+ @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1);
+ @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1);
+ @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1);
+ @thread3=&ROUND(0,5,10,15);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+$code.=<<___;
+ bne .Loop_neon
+
+ add @t[3],sp,#32
+ vld1.32 {$t0-$t1},[sp] @ load key material
+ vld1.32 {$t2-$t3},[@t[3]]
+
+ ldr @t[3],[sp,#4*(32+2)] @ load len
+
+ str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store
+ str @t[1], [sp,#4*(16+9)]
+ str @x[12],[sp,#4*(16+12)]
+ str @t[2], [sp,#4*(16+13)]
+ str @x[14],[sp,#4*(16+14)]
+
+ @ at this point we have first half of 512-bit result in
+ @ @x[0-7] and second half at sp+4*(16+8)
+
+ ldr r12,[sp,#4*(32+1)] @ load inp
+ ldr r14,[sp,#4*(32+0)] @ load out
+
+ vadd.i32 $a0,$a0,$t0 @ accumulate key material
+ vadd.i32 $a1,$a1,$t0
+ vadd.i32 $a2,$a2,$t0
+ vldr $t0#lo,[sp,#4*(16+0)] @ one
+
+ vadd.i32 $b0,$b0,$t1
+ vadd.i32 $b1,$b1,$t1
+ vadd.i32 $b2,$b2,$t1
+ vldr $t1#lo,[sp,#4*(16+2)] @ two
+
+ vadd.i32 $c0,$c0,$t2
+ vadd.i32 $c1,$c1,$t2
+ vadd.i32 $c2,$c2,$t2
+ vadd.i32 $d1#lo,$d1#lo,$t0#lo @ counter+1
+ vadd.i32 $d2#lo,$d2#lo,$t1#lo @ counter+2
+
+ vadd.i32 $d0,$d0,$t3
+ vadd.i32 $d1,$d1,$t3
+ vadd.i32 $d2,$d2,$t3
+
+ cmp @t[3],#64*4
+ blo .Ltail_neon
+
+ vld1.8 {$t0-$t1},[r12]! @ load input
+ mov @t[3],sp
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0 @ xor with input
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ vst1.8 {$a0-$b0},[r14]! @ store output
+ veor $b1,$b1,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c1,$c1,$t2
+ vst1.8 {$c0-$d0},[r14]!
+ veor $d1,$d1,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a2,$a2,$t0
+ vld1.32 {$a0-$b0},[@t[3]]! @ load for next iteration
+ veor $t0#hi,$t0#hi,$t0#hi
+ vldr $t0#lo,[sp,#4*(16+4)] @ four
+ veor $b2,$b2,$t1
+ vld1.32 {$c0-$d0},[@t[3]]
+ veor $c2,$c2,$t2
+ vst1.8 {$a1-$b1},[r14]!
+ veor $d2,$d2,$t3
+ vst1.8 {$c1-$d1},[r14]!
+
+ vadd.i32 $d0#lo,$d0#lo,$t0#lo @ next counter value
+ vldr $t0#lo,[sp,#4*(16+0)] @ one
+
+ ldmia sp,{@t[0]-@t[3]} @ load key material
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ vst1.8 {$a2-$b2},[r14]!
+ add @x[1],@x[1],@t[1]
+ ldr @t[1],[r12,#-12]
+ vst1.8 {$c2-$d2},[r14]!
+ add @x[2],@x[2],@t[2]
+ ldr @t[2],[r12,#-8]
+ add @x[3],@x[3],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+ eor @x[0],@x[0],@t[0] @ xor with input
+ add @t[0],sp,#4*(4)
+ eor @x[1],@x[1],@t[1]
+ str @x[0],[r14],#16 @ store output
+ eor @x[2],@x[2],@t[2]
+ str @x[1],[r14,#-12]
+ eor @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ add @x[5],@x[5],@t[1]
+ ldr @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ ldr @t[2],[r12,#-8]
+ add @x[7],@x[7],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ eor @x[4],@x[4],@t[0]
+ add @t[0],sp,#4*(8)
+ eor @x[5],@x[5],@t[1]
+ str @x[4],[r14],#16 @ store output
+ eor @x[6],@x[6],@t[2]
+ str @x[5],[r14,#-12]
+ eor @x[7],@x[7],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[6],[r14,#-8]
+ add @x[0],sp,#4*(16+8)
+ str @x[7],[r14,#-4]
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ add @x[1],@x[1],@t[1]
+ ldr @t[1],[r12,#-12]
+# ifdef __thumb2__
+ it hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it
+ add @x[2],@x[2],@t[2]
+ ldr @t[2],[r12,#-8]
+# ifdef __thumb2__
+ it hi
+# endif
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it
+ add @x[3],@x[3],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+ eor @x[0],@x[0],@t[0]
+ add @t[0],sp,#4*(12)
+ eor @x[1],@x[1],@t[1]
+ str @x[0],[r14],#16 @ store output
+ eor @x[2],@x[2],@t[2]
+ str @x[1],[r14,#-12]
+ eor @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],@t[0],#4 @ next counter value
+ add @x[5],@x[5],@t[1]
+ str @t[0],[sp,#4*(12)] @ save next counter value
+ ldr @t[0],[r12],#16 @ load input
+ add @x[6],@x[6],@t[2]
+ add @x[4],@x[4],#3 @ counter+3
+ ldr @t[1],[r12,#-12]
+ add @x[7],@x[7],@t[3]
+ ldr @t[2],[r12,#-8]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ eor @x[4],@x[4],@t[0]
+# ifdef __thumb2__
+ it hi
+# endif
+ ldrhi @t[0],[sp,#4*(32+2)] @ re-load len
+ eor @x[5],@x[5],@t[1]
+ eor @x[6],@x[6],@t[2]
+ str @x[4],[r14],#16 @ store output
+ eor @x[7],@x[7],@t[3]
+ str @x[5],[r14,#-12]
+ sub @t[3],@t[0],#64*4 @ len-=64*4
+ str @x[6],[r14,#-8]
+ str @x[7],[r14,#-4]
+ bhi .Loop_neon_outer
+
+ b .Ldone_neon
+
+.align 4
+.Lbreak_neon:
+ @ harmonize NEON and integer-only stack frames: load data
+ @ from NEON frame, but save to integer-only one; distance
+ @ between the two is 4*(32+4+16-32)=4*(20).
+
+ str @t[3], [sp,#4*(20+32+2)] @ save len
+ add @t[3],sp,#4*(32+4)
+ str r12, [sp,#4*(20+32+1)] @ save inp
+ str r14, [sp,#4*(20+32+0)] @ save out
+
+ ldr @x[12],[sp,#4*(16+10)]
+ ldr @x[14],[sp,#4*(16+11)]
+ vldmia @t[3],{d8-d15} @ fulfill ABI requirement
+ str @x[12],[sp,#4*(20+16+10)] @ copy "@x[10]"
+ str @x[14],[sp,#4*(20+16+11)] @ copy "@x[11]"
+
+ ldr @t[3], [sp,#4*(15)]
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ ldr @t[2], [sp,#4*(13)]
+ ldr @x[14],[sp,#4*(14)]
+ str @t[3], [sp,#4*(20+16+15)]
+ add @t[3],sp,#4*(20)
+ vst1.32 {$a0-$b0},[@t[3]]! @ copy key
+ add sp,sp,#4*(20) @ switch frame
+ vst1.32 {$c0-$d0},[@t[3]]
+ mov @t[3],#10
+ b .Loop @ go integer-only
+
+.align 4
+.Ltail_neon:
+ cmp @t[3],#64*3
+ bhs .L192_or_more_neon
+ cmp @t[3],#64*2
+ bhs .L128_or_more_neon
+ cmp @t[3],#64*1
+ bhs .L64_or_more_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a0-$b0},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c0-$d0},[@t[0]]
+ b .Loop_tail_neon
+
+.align 4
+.L64_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vst1.8 {$a0-$b0},[r14]!
+ vst1.8 {$c0-$d0},[r14]!
+
+ beq .Ldone_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a1-$b1},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c1-$d1},[@t[0]]
+ sub @t[3],@t[3],#64*1 @ len-=64*1
+ b .Loop_tail_neon
+
+.align 4
+.L128_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ veor $b1,$b1,$t1
+ vst1.8 {$a0-$b0},[r14]!
+ veor $c1,$c1,$t2
+ vst1.8 {$c0-$d0},[r14]!
+ veor $d1,$d1,$t3
+ vst1.8 {$a1-$b1},[r14]!
+ vst1.8 {$c1-$d1},[r14]!
+
+ beq .Ldone_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a2-$b2},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c2-$d2},[@t[0]]
+ sub @t[3],@t[3],#64*2 @ len-=64*2
+ b .Loop_tail_neon
+
+.align 4
+.L192_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ veor $b1,$b1,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c1,$c1,$t2
+ vst1.8 {$a0-$b0},[r14]!
+ veor $d1,$d1,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a2,$a2,$t0
+ vst1.8 {$c0-$d0},[r14]!
+ veor $b2,$b2,$t1
+ vst1.8 {$a1-$b1},[r14]!
+ veor $c2,$c2,$t2
+ vst1.8 {$c1-$d1},[r14]!
+ veor $d2,$d2,$t3
+ vst1.8 {$a2-$b2},[r14]!
+ vst1.8 {$c2-$d2},[r14]!
+
+ beq .Ldone_neon
+
+ ldmia sp,{@t[0]-@t[3]} @ load key material
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(4)
+ add @x[1],@x[1],@t[1]
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(8)
+ add @x[5],@x[5],@t[1]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ stmia sp,{@x[0]-@x[7]}
+ add @x[0],sp,#4*(16+8)
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(12)
+ add @x[1],@x[1],@t[1]
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(8)
+ add @x[5],@x[5],@t[1]
+ add @x[4],@x[4],#3 @ counter+3
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+ ldr @t[3],[sp,#4*(32+2)] @ re-load len
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ stmia @t[0],{@x[0]-@x[7]}
+ add @t[2],sp,#4*(0)
+ sub @t[3],@t[3],#64*3 @ len-=64*3
+
+.Loop_tail_neon:
+ ldrb @t[0],[@t[2]],#1 @ read buffer on stack
+ ldrb @t[1],[r12],#1 @ read input
+ subs @t[3],@t[3],#1
+ eor @t[0],@t[0],@t[1]
+ strb @t[0],[r14],#1 @ store ouput
+ bne .Loop_tail_neon
+
+.Ldone_neon:
+ add sp,sp,#4*(32+4)
+ vldmia sp,{d8-d15}
+ add sp,sp,#4*(16+3)
+ ldmia sp!,{r4-r11,pc}
+.size ChaCha20_neon,.-ChaCha20_neon
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+}}}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/chacha/asm/chacha-armv8.pl b/src/crypto/chacha/asm/chacha-armv8.pl
new file mode 100755
index 00000000..215d9657
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-armv8.pl
@@ -0,0 +1,1127 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# June 2015
+#
+# ChaCha20 for ARMv8.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU
+#
+# Apple A7 5.50/+49% 3.33 1.70
+# Cortex-A53 8.40/+80% 4.72 4.72(*)
+# Cortex-A57 8.06/+43% 4.90 4.43(**)
+# Denver 4.50/+82% 2.63 2.67(*)
+# X-Gene 9.50/+46% 8.82 8.89(*)
+#
+# (*) it's expected that doubling interleave factor doesn't help
+# all processors, only those with higher NEON latency and
+# higher instruction issue rate;
+# (**) expected improvement was actually higher;
+
+$flavour=shift;
+$output=shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4));
+
+my @x=map("x$_",(5..17,19..21));
+my @d=map("x$_",(22..28,30));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+
+ (
+ "&add_32 (@x[$a0],@x[$a0],@x[$b0])",
+ "&add_32 (@x[$a1],@x[$a1],@x[$b1])",
+ "&add_32 (@x[$a2],@x[$a2],@x[$b2])",
+ "&add_32 (@x[$a3],@x[$a3],@x[$b3])",
+ "&eor_32 (@x[$d0],@x[$d0],@x[$a0])",
+ "&eor_32 (@x[$d1],@x[$d1],@x[$a1])",
+ "&eor_32 (@x[$d2],@x[$d2],@x[$a2])",
+ "&eor_32 (@x[$d3],@x[$d3],@x[$a3])",
+ "&ror_32 (@x[$d0],@x[$d0],16)",
+ "&ror_32 (@x[$d1],@x[$d1],16)",
+ "&ror_32 (@x[$d2],@x[$d2],16)",
+ "&ror_32 (@x[$d3],@x[$d3],16)",
+
+ "&add_32 (@x[$c0],@x[$c0],@x[$d0])",
+ "&add_32 (@x[$c1],@x[$c1],@x[$d1])",
+ "&add_32 (@x[$c2],@x[$c2],@x[$d2])",
+ "&add_32 (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor_32 (@x[$b0],@x[$b0],@x[$c0])",
+ "&eor_32 (@x[$b1],@x[$b1],@x[$c1])",
+ "&eor_32 (@x[$b2],@x[$b2],@x[$c2])",
+ "&eor_32 (@x[$b3],@x[$b3],@x[$c3])",
+ "&ror_32 (@x[$b0],@x[$b0],20)",
+ "&ror_32 (@x[$b1],@x[$b1],20)",
+ "&ror_32 (@x[$b2],@x[$b2],20)",
+ "&ror_32 (@x[$b3],@x[$b3],20)",
+
+ "&add_32 (@x[$a0],@x[$a0],@x[$b0])",
+ "&add_32 (@x[$a1],@x[$a1],@x[$b1])",
+ "&add_32 (@x[$a2],@x[$a2],@x[$b2])",
+ "&add_32 (@x[$a3],@x[$a3],@x[$b3])",
+ "&eor_32 (@x[$d0],@x[$d0],@x[$a0])",
+ "&eor_32 (@x[$d1],@x[$d1],@x[$a1])",
+ "&eor_32 (@x[$d2],@x[$d2],@x[$a2])",
+ "&eor_32 (@x[$d3],@x[$d3],@x[$a3])",
+ "&ror_32 (@x[$d0],@x[$d0],24)",
+ "&ror_32 (@x[$d1],@x[$d1],24)",
+ "&ror_32 (@x[$d2],@x[$d2],24)",
+ "&ror_32 (@x[$d3],@x[$d3],24)",
+
+ "&add_32 (@x[$c0],@x[$c0],@x[$d0])",
+ "&add_32 (@x[$c1],@x[$c1],@x[$d1])",
+ "&add_32 (@x[$c2],@x[$c2],@x[$d2])",
+ "&add_32 (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor_32 (@x[$b0],@x[$b0],@x[$c0])",
+ "&eor_32 (@x[$b1],@x[$b1],@x[$c1])",
+ "&eor_32 (@x[$b2],@x[$b2],@x[$c2])",
+ "&eor_32 (@x[$b3],@x[$b3],@x[$c3])",
+ "&ror_32 (@x[$b0],@x[$b0],25)",
+ "&ror_32 (@x[$b1],@x[$b1],25)",
+ "&ror_32 (@x[$b2],@x[$b2],25)",
+ "&ror_32 (@x[$b3],@x[$b3],25)"
+ );
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+
+.extern OPENSSL_armcap_P
+
+.align 5
+.Lsigma:
+.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral
+.Lone:
+.long 1,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef __ILP32__
+.long OPENSSL_armcap_P-.
+#else
+.quad OPENSSL_armcap_P-.
+#endif
+.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,%function
+.align 5
+ChaCha20_ctr32:
+ cbz $len,.Labort
+ adr @x[0],.LOPENSSL_armcap_P
+ cmp $len,#192
+ b.lo .Lshort
+#ifdef __ILP32__
+ ldrsw @x[1],[@x[0]]
+#else
+ ldr @x[1],[@x[0]]
+#endif
+ ldr w17,[@x[1],@x[0]]
+ tst w17,#ARMV7_NEON
+ b.ne ChaCha20_neon
+
+.Lshort:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ldp @d[6],@d[7],[$ctr] // load counter
+#ifdef __ARMEB__
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+
+.Loop_outer:
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ mov.32 @x[6],@d[3]
+ lsr @x[7],@d[3],#32
+ mov.32 @x[8],@d[4]
+ lsr @x[9],@d[4],#32
+ mov.32 @x[10],@d[5]
+ lsr @x[11],@d[5],#32
+ mov.32 @x[12],@d[6]
+ lsr @x[13],@d[6],#32
+ mov.32 @x[14],@d[7]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#10
+ subs $len,$len,#64
+.Loop:
+ sub $ctr,$ctr,#1
+___
+ foreach (&ROUND(0, 4, 8,12)) { eval; }
+ foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ cbnz $ctr,.Loop
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add @x[1],@x[1],@d[0],lsr#32
+ add.32 @x[2],@x[2],@d[1]
+ add @x[3],@x[3],@d[1],lsr#32
+ add.32 @x[4],@x[4],@d[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add.32 @x[6],@x[6],@d[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add @x[15],@x[15],@d[7],lsr#32
+
+ b.lo .Ltail
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#1 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+
+ b.hi .Loop_outer
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+.Labort:
+ ret
+
+.align 4
+.Ltail:
+ add $len,$len,#64
+.Less_than_64:
+ sub $out,$out,#1
+ add $inp,$inp,$len
+ add $out,$out,$len
+ add $ctr,sp,$len
+ neg $len,$len
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ stp @x[0],@x[2],[sp,#0]
+ stp @x[4],@x[6],[sp,#16]
+ stp @x[8],@x[10],[sp,#32]
+ stp @x[12],@x[14],[sp,#48]
+
+.Loop_tail:
+ ldrb w10,[$inp,$len]
+ ldrb w11,[$ctr,$len]
+ add $len,$len,#1
+ eor w10,w10,w11
+ strb w10,[$out,$len]
+ cbnz $len,.Loop_tail
+
+ stp xzr,xzr,[sp,#0]
+ stp xzr,xzr,[sp,#16]
+ stp xzr,xzr,[sp,#32]
+ stp xzr,xzr,[sp,#48]
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) =
+ map("v$_.4s",(0..7,16..23));
+my (@K)=map("v$_.4s",(24..30));
+my $ONE="v31.4s";
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+ (
+ "&add ('$a','$a','$b')",
+ "&eor ('$d','$d','$a')",
+ "&rev32_16 ('$d','$d')", # vrot ($d,16)
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',20)",
+ "&sli ('$b','$t',12)",
+
+ "&add ('$a','$a','$b')",
+ "&eor ('$t','$d','$a')",
+ "&ushr ('$d','$t',24)",
+ "&sli ('$d','$t',8)",
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',25)",
+ "&sli ('$b','$t',7)",
+
+ "&ext ('$c','$c','$c',8)",
+ "&ext ('$d','$d','$d',$odd?4:12)",
+ "&ext ('$b','$b','$b',$odd?12:4)"
+ );
+}
+
+$code.=<<___;
+
+.type ChaCha20_neon,%function
+.align 5
+ChaCha20_neon:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ cmp $len,#512
+ b.hs .L512_or_more_neon
+
+ sub sp,sp,#64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ld1 {@K[0]},[@x[0]],#16
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ld1 {@K[1],@K[2]},[$key]
+ ldp @d[6],@d[7],[$ctr] // load counter
+ ld1 {@K[3]},[$ctr]
+ ld1 {$ONE},[@x[0]]
+#ifdef __ARMEB__
+ rev64 @K[0],@K[0]
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+ add @K[3],@K[3],$ONE // += 1
+ add @K[4],@K[3],$ONE
+ add @K[5],@K[4],$ONE
+ shl $ONE,$ONE,#2 // 1 -> 4
+
+.Loop_outer_neon:
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ mov $A0,@K[0]
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ mov $A1,@K[0]
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ mov $A2,@K[0]
+ mov.32 @x[6],@d[3]
+ mov $B0,@K[1]
+ lsr @x[7],@d[3],#32
+ mov $B1,@K[1]
+ mov.32 @x[8],@d[4]
+ mov $B2,@K[1]
+ lsr @x[9],@d[4],#32
+ mov $D0,@K[3]
+ mov.32 @x[10],@d[5]
+ mov $D1,@K[4]
+ lsr @x[11],@d[5],#32
+ mov $D2,@K[5]
+ mov.32 @x[12],@d[6]
+ mov $C0,@K[2]
+ lsr @x[13],@d[6],#32
+ mov $C1,@K[2]
+ mov.32 @x[14],@d[7]
+ mov $C2,@K[2]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#10
+ subs $len,$len,#256
+.Loop_neon:
+ sub $ctr,$ctr,#1
+___
+ my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ my @thread3=&ROUND(0,4,8,12);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&ROUND(0,5,10,15);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add $A0,$A0,@K[0]
+ add @x[1],@x[1],@d[0],lsr#32
+ add $A1,$A1,@K[0]
+ add.32 @x[2],@x[2],@d[1]
+ add $A2,$A2,@K[0]
+ add @x[3],@x[3],@d[1],lsr#32
+ add $C0,$C0,@K[2]
+ add.32 @x[4],@x[4],@d[2]
+ add $C1,$C1,@K[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add $C2,$C2,@K[2]
+ add.32 @x[6],@x[6],@d[3]
+ add $D0,$D0,@K[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add $D1,$D1,@K[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add $D2,$D2,@K[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add $B0,$B0,@K[1]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add $B1,$B1,@K[1]
+ add @x[15],@x[15],@d[7],lsr#32
+ add $B2,$B2,@K[1]
+
+ b.lo .Ltail_neon
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor $A0,$A0,$T0
+ eor @x[10],@x[10],@x[11]
+ eor $B0,$B0,$T1
+ eor @x[12],@x[12],@x[13]
+ eor $C0,$C0,$T2
+ eor @x[14],@x[14],@x[15]
+ eor $D0,$D0,$T3
+ ld1.8 {$T0-$T3},[$inp],#64
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#4 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ add @K[3],@K[3],$ONE // += 4
+ stp @x[8],@x[10],[$out,#32]
+ add @K[4],@K[4],$ONE
+ stp @x[12],@x[14],[$out,#48]
+ add @K[5],@K[5],$ONE
+ add $out,$out,#64
+
+ st1.8 {$A0-$D0},[$out],#64
+ ld1.8 {$A0-$D0},[$inp],#64
+
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+
+ eor $A2,$A2,$A0
+ eor $B2,$B2,$B0
+ eor $C2,$C2,$C0
+ eor $D2,$D2,$D0
+ st1.8 {$A2-$D2},[$out],#64
+
+ b.hi .Loop_outer_neon
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+
+.Ltail_neon:
+ add $len,$len,#256
+ cmp $len,#64
+ b.lo .Less_than_64
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#4 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+ cmp $len,#64
+ b.lo .Less_than_128
+
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor $A0,$A0,$T0
+ eor $B0,$B0,$T1
+ eor $C0,$C0,$T2
+ eor $D0,$D0,$T3
+ st1.8 {$A0-$D0},[$out],#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+ cmp $len,#64
+ b.lo .Less_than_192
+
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+
+ st1.8 {$A2-$D2},[sp]
+ b .Last_neon
+
+.Less_than_128:
+ st1.8 {$A0-$D0},[sp]
+ b .Last_neon
+.Less_than_192:
+ st1.8 {$A1-$D1},[sp]
+ b .Last_neon
+
+.align 4
+.Last_neon:
+ sub $out,$out,#1
+ add $inp,$inp,$len
+ add $out,$out,$len
+ add $ctr,sp,$len
+ neg $len,$len
+
+.Loop_tail_neon:
+ ldrb w10,[$inp,$len]
+ ldrb w11,[$ctr,$len]
+ add $len,$len,#1
+ eor w10,w10,w11
+ strb w10,[$out,$len]
+ cbnz $len,.Loop_tail_neon
+
+ stp xzr,xzr,[sp,#0]
+ stp xzr,xzr,[sp,#16]
+ stp xzr,xzr,[sp,#32]
+ stp xzr,xzr,[sp,#48]
+
+.Ldone_neon:
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_neon,.-ChaCha20_neon
+___
+{
+my ($T0,$T1,$T2,$T3,$T4,$T5)=@K;
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,
+ $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23));
+
+$code.=<<___;
+.type ChaCha20_512_neon,%function
+.align 5
+ChaCha20_512_neon:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+
+.L512_or_more_neon:
+ sub sp,sp,#128+64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ld1 {@K[0]},[@x[0]],#16
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ld1 {@K[1],@K[2]},[$key]
+ ldp @d[6],@d[7],[$ctr] // load counter
+ ld1 {@K[3]},[$ctr]
+ ld1 {$ONE},[@x[0]]
+#ifdef __ARMEB__
+ rev64 @K[0],@K[0]
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+ add @K[3],@K[3],$ONE // += 1
+ stp @K[0],@K[1],[sp,#0] // off-load key block, invariant part
+ add @K[3],@K[3],$ONE // not typo
+ str @K[2],[sp,#32]
+ add @K[4],@K[3],$ONE
+ add @K[5],@K[4],$ONE
+ add @K[6],@K[5],$ONE
+ shl $ONE,$ONE,#2 // 1 -> 4
+
+ stp d8,d9,[sp,#128+0] // meet ABI requirements
+ stp d10,d11,[sp,#128+16]
+ stp d12,d13,[sp,#128+32]
+ stp d14,d15,[sp,#128+48]
+
+ sub $len,$len,#512 // not typo
+
+.Loop_outer_512_neon:
+ mov $A0,@K[0]
+ mov $A1,@K[0]
+ mov $A2,@K[0]
+ mov $A3,@K[0]
+ mov $A4,@K[0]
+ mov $A5,@K[0]
+ mov $B0,@K[1]
+ mov.32 @x[0],@d[0] // unpack key block
+ mov $B1,@K[1]
+ lsr @x[1],@d[0],#32
+ mov $B2,@K[1]
+ mov.32 @x[2],@d[1]
+ mov $B3,@K[1]
+ lsr @x[3],@d[1],#32
+ mov $B4,@K[1]
+ mov.32 @x[4],@d[2]
+ mov $B5,@K[1]
+ lsr @x[5],@d[2],#32
+ mov $D0,@K[3]
+ mov.32 @x[6],@d[3]
+ mov $D1,@K[4]
+ lsr @x[7],@d[3],#32
+ mov $D2,@K[5]
+ mov.32 @x[8],@d[4]
+ mov $D3,@K[6]
+ lsr @x[9],@d[4],#32
+ mov $C0,@K[2]
+ mov.32 @x[10],@d[5]
+ mov $C1,@K[2]
+ lsr @x[11],@d[5],#32
+ add $D4,$D0,$ONE // +4
+ mov.32 @x[12],@d[6]
+ add $D5,$D1,$ONE // +4
+ lsr @x[13],@d[6],#32
+ mov $C2,@K[2]
+ mov.32 @x[14],@d[7]
+ mov $C3,@K[2]
+ lsr @x[15],@d[7],#32
+ mov $C4,@K[2]
+ stp @K[3],@K[4],[sp,#48] // off-load key block, variable part
+ mov $C5,@K[2]
+ str @K[5],[sp,#80]
+
+ mov $ctr,#5
+ subs $len,$len,#512
+.Loop_upper_neon:
+ sub $ctr,$ctr,#1
+___
+ my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+ my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+ my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+ my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+ my $diff = ($#thread0+1)*6 - $#thread67 - 1;
+ my $i = 0;
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_upper_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add @x[1],@x[1],@d[0],lsr#32
+ add.32 @x[2],@x[2],@d[1]
+ add @x[3],@x[3],@d[1],lsr#32
+ add.32 @x[4],@x[4],@d[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add.32 @x[6],@x[6],@d[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add @x[15],@x[15],@d[7],lsr#32
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#1 // increment counter
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ stp @x[4],@x[6],[$out,#16]
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ stp @x[8],@x[10],[$out,#32]
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ mov.32 @x[6],@d[3]
+ lsr @x[7],@d[3],#32
+ mov.32 @x[8],@d[4]
+ lsr @x[9],@d[4],#32
+ mov.32 @x[10],@d[5]
+ lsr @x[11],@d[5],#32
+ mov.32 @x[12],@d[6]
+ lsr @x[13],@d[6],#32
+ mov.32 @x[14],@d[7]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#5
+.Loop_lower_neon:
+ sub $ctr,$ctr,#1
+___
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_lower_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ ldp @K[0],@K[1],[sp,#0]
+ add @x[1],@x[1],@d[0],lsr#32
+ ldp @K[2],@K[3],[sp,#32]
+ add.32 @x[2],@x[2],@d[1]
+ ldp @K[4],@K[5],[sp,#64]
+ add @x[3],@x[3],@d[1],lsr#32
+ add $A0,$A0,@K[0]
+ add.32 @x[4],@x[4],@d[2]
+ add $A1,$A1,@K[0]
+ add @x[5],@x[5],@d[2],lsr#32
+ add $A2,$A2,@K[0]
+ add.32 @x[6],@x[6],@d[3]
+ add $A3,$A3,@K[0]
+ add @x[7],@x[7],@d[3],lsr#32
+ add $A4,$A4,@K[0]
+ add.32 @x[8],@x[8],@d[4]
+ add $A5,$A5,@K[0]
+ add @x[9],@x[9],@d[4],lsr#32
+ add $C0,$C0,@K[2]
+ add.32 @x[10],@x[10],@d[5]
+ add $C1,$C1,@K[2]
+ add @x[11],@x[11],@d[5],lsr#32
+ add $C2,$C2,@K[2]
+ add.32 @x[12],@x[12],@d[6]
+ add $C3,$C3,@K[2]
+ add @x[13],@x[13],@d[6],lsr#32
+ add $C4,$C4,@K[2]
+ add.32 @x[14],@x[14],@d[7]
+ add $C5,$C5,@K[2]
+ add @x[15],@x[15],@d[7],lsr#32
+ add $D4,$D4,$ONE // +4
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add $D5,$D5,$ONE // +4
+ add @x[2],@x[2],@x[3],lsl#32
+ add $D0,$D0,@K[3]
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add $D1,$D1,@K[4]
+ add @x[4],@x[4],@x[5],lsl#32
+ add $D2,$D2,@K[5]
+ add @x[6],@x[6],@x[7],lsl#32
+ add $D3,$D3,@K[6]
+ ldp @x[5],@x[7],[$inp,#16]
+ add $D4,$D4,@K[3]
+ add @x[8],@x[8],@x[9],lsl#32
+ add $D5,$D5,@K[4]
+ add @x[10],@x[10],@x[11],lsl#32
+ add $B0,$B0,@K[1]
+ ldp @x[9],@x[11],[$inp,#32]
+ add $B1,$B1,@K[1]
+ add @x[12],@x[12],@x[13],lsl#32
+ add $B2,$B2,@K[1]
+ add @x[14],@x[14],@x[15],lsl#32
+ add $B3,$B3,@K[1]
+ ldp @x[13],@x[15],[$inp,#48]
+ add $B4,$B4,@K[1]
+ add $inp,$inp,#64
+ add $B5,$B5,@K[1]
+
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor $A0,$A0,$T0
+ eor @x[10],@x[10],@x[11]
+ eor $B0,$B0,$T1
+ eor @x[12],@x[12],@x[13]
+ eor $C0,$C0,$T2
+ eor @x[14],@x[14],@x[15]
+ eor $D0,$D0,$T3
+ ld1.8 {$T0-$T3},[$inp],#64
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#7 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ st1.8 {$A0-$D0},[$out],#64
+
+ ld1.8 {$A0-$D0},[$inp],#64
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+
+ ld1.8 {$A1-$D1},[$inp],#64
+ eor $A2,$A2,$A0
+ ldp @K[0],@K[1],[sp,#0]
+ eor $B2,$B2,$B0
+ ldp @K[2],@K[3],[sp,#32]
+ eor $C2,$C2,$C0
+ eor $D2,$D2,$D0
+ st1.8 {$A2-$D2},[$out],#64
+
+ ld1.8 {$A2-$D2},[$inp],#64
+ eor $A3,$A3,$A1
+ eor $B3,$B3,$B1
+ eor $C3,$C3,$C1
+ eor $D3,$D3,$D1
+ st1.8 {$A3-$D3},[$out],#64
+
+ ld1.8 {$A3-$D3},[$inp],#64
+ eor $A4,$A4,$A2
+ eor $B4,$B4,$B2
+ eor $C4,$C4,$C2
+ eor $D4,$D4,$D2
+ st1.8 {$A4-$D4},[$out],#64
+
+ shl $A0,$ONE,#1 // 4 -> 8
+ eor $A5,$A5,$A3
+ eor $B5,$B5,$B3
+ eor $C5,$C5,$C3
+ eor $D5,$D5,$D3
+ st1.8 {$A5-$D5},[$out],#64
+
+ add @K[3],@K[3],$A0 // += 8
+ add @K[4],@K[4],$A0
+ add @K[5],@K[5],$A0
+ add @K[6],@K[6],$A0
+
+ b.hs .Loop_outer_512_neon
+
+ adds $len,$len,#512
+ ushr $A0,$ONE,#2 // 4 -> 1
+
+ ldp d8,d9,[sp,#128+0] // meet ABI requirements
+ ldp d10,d11,[sp,#128+16]
+ ldp d12,d13,[sp,#128+32]
+ ldp d14,d15,[sp,#128+48]
+
+ stp @K[0],$ONE,[sp,#0] // wipe off-load area
+ stp @K[0],$ONE,[sp,#32]
+ stp @K[0],$ONE,[sp,#64]
+
+ b.eq .Ldone_512_neon
+
+ cmp $len,#192
+ sub @K[3],@K[3],$A0 // -= 1
+ sub @K[4],@K[4],$A0
+ sub @K[5],@K[5],$A0
+ add sp,sp,#128
+ b.hs .Loop_outer_neon
+
+ eor @K[1],@K[1],@K[1]
+ eor @K[2],@K[2],@K[2]
+ eor @K[3],@K[3],@K[3]
+ eor @K[4],@K[4],@K[4]
+ eor @K[5],@K[5],@K[5]
+ eor @K[6],@K[6],@K[6]
+ b .Loop_outer
+
+.Ldone_512_neon:
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#128+64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_512_neon,.-ChaCha20_512_neon
+___
+}
+}}}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or
+ (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or
+ (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or
+ (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or
+ (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1));
+
+ #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+ print $_,"\n";
+}
+close STDOUT; # flush
diff --git a/src/crypto/chacha/asm/chacha-x86.pl b/src/crypto/chacha/asm/chacha-x86.pl
new file mode 100755
index 00000000..e5760297
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-x86.pl
@@ -0,0 +1,769 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# January 2015
+#
+# ChaCha20 for x86.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# 1xIALU/gcc 4xSSSE3
+# Pentium 17.5/+80%
+# PIII 14.2/+60%
+# P4 18.6/+84%
+# Core2 9.56/+89% 4.83
+# Westmere 9.50/+45% 3.35
+# Sandy Bridge 10.7/+47% 3.24
+# Haswell 8.22/+50% 2.89
+# Silvermont 17.8/+36% 8.53
+# Sledgehammer 10.2/+54%
+# Bulldozer 13.5/+50% 4.39(*)
+#
+# (*) Bulldozer actually executes 4xXOP code path that delivers 3.50;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
+
+$xmm=$ymm=0;
+for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+$ymm=$xmm;
+
+$a="eax";
+($b,$b_)=("ebx","ebp");
+($c,$c_)=("ecx","esi");
+($d,$d_)=("edx","edi");
+
+sub QUARTERROUND {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
+
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+
+ if ($i==0) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==3) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+ } elsif ($i==4) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==7) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+ }
+
+ #&add ($a,$b); # see elsewhere
+ &xor ($d,$a);
+ &mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3);
+ &rol ($d,16);
+ &mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0);
+ &add ($c,$d);
+ &mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3);
+ &xor ($b,$c);
+ &mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn);
+ &rol ($b,12);
+ &mov ($b_,&DWP(4*$bn,"esp")) if ($i<7);
+ &mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter
+ &add ($a,$b);
+ &xor ($d,$a);
+ &mov (&DWP(4*$ai,"esp"),$a);
+ &rol ($d,8);
+ &mov ($a,&DWP(4*$an,"esp"));
+ &add ($c,$d);
+ &mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn);
+ &mov ($d_,$d) if ($di==$dn);
+ &xor ($b,$c);
+ &add ($a,$b_) if ($i<7); # elsewhere
+ &rol ($b,7);
+
+ ($b,$b_)=($b_,$b);
+ ($c,$c_)=($c_,$c);
+ ($d,$d_)=($d_,$d);
+}
+
+&static_label("ssse3_shortcut");
+&static_label("ssse3_data");
+&static_label("pic_point");
+
+&function_begin("ChaCha20_ctr32");
+ &xor ("eax","eax");
+ &cmp ("eax",&wparam(2)); # len==0?
+ &je (&label("no_data"));
+if ($xmm) {
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("eax");
+ &picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point"));
+ &test (&DWP(0,"ebp"),1<<24); # test FXSR bit
+ &jz (&label("x86"));
+ &test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit
+ &jz (&label("x86"));
+ &jmp (&label("ssse3_shortcut"));
+&set_label("x86");
+}
+ &mov ("esi",&wparam(3)); # key
+ &mov ("edi",&wparam(4)); # counter and nonce
+
+ &stack_push(33);
+
+ &mov ("eax",&DWP(4*0,"esi")); # copy key
+ &mov ("ebx",&DWP(4*1,"esi"));
+ &mov ("ecx",&DWP(4*2,"esi"));
+ &mov ("edx",&DWP(4*3,"esi"));
+ &mov (&DWP(64+4*4,"esp"),"eax");
+ &mov (&DWP(64+4*5,"esp"),"ebx");
+ &mov (&DWP(64+4*6,"esp"),"ecx");
+ &mov (&DWP(64+4*7,"esp"),"edx");
+ &mov ("eax",&DWP(4*4,"esi"));
+ &mov ("ebx",&DWP(4*5,"esi"));
+ &mov ("ecx",&DWP(4*6,"esi"));
+ &mov ("edx",&DWP(4*7,"esi"));
+ &mov (&DWP(64+4*8,"esp"),"eax");
+ &mov (&DWP(64+4*9,"esp"),"ebx");
+ &mov (&DWP(64+4*10,"esp"),"ecx");
+ &mov (&DWP(64+4*11,"esp"),"edx");
+ &mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce
+ &mov ("ebx",&DWP(4*1,"edi"));
+ &mov ("ecx",&DWP(4*2,"edi"));
+ &mov ("edx",&DWP(4*3,"edi"));
+ &sub ("eax",1);
+ &mov (&DWP(64+4*12,"esp"),"eax");
+ &mov (&DWP(64+4*13,"esp"),"ebx");
+ &mov (&DWP(64+4*14,"esp"),"ecx");
+ &mov (&DWP(64+4*15,"esp"),"edx");
+ &jmp (&label("entry"));
+
+&set_label("outer_loop",16);
+ &mov (&wparam(1),$b); # save input
+ &mov (&wparam(0),$a); # save output
+ &mov (&wparam(2),$c); # save len
+&set_label("entry");
+ &mov ($a,0x61707865);
+ &mov (&DWP(4*1,"esp"),0x3320646e);
+ &mov (&DWP(4*2,"esp"),0x79622d32);
+ &mov (&DWP(4*3,"esp"),0x6b206574);
+
+ &mov ($b, &DWP(64+4*5,"esp")); # copy key material
+ &mov ($b_,&DWP(64+4*6,"esp"));
+ &mov ($c, &DWP(64+4*10,"esp"));
+ &mov ($c_,&DWP(64+4*11,"esp"));
+ &mov ($d, &DWP(64+4*13,"esp"));
+ &mov ($d_,&DWP(64+4*14,"esp"));
+ &mov (&DWP(4*5,"esp"),$b);
+ &mov (&DWP(4*6,"esp"),$b_);
+ &mov (&DWP(4*10,"esp"),$c);
+ &mov (&DWP(4*11,"esp"),$c_);
+ &mov (&DWP(4*13,"esp"),$d);
+ &mov (&DWP(4*14,"esp"),$d_);
+
+ &mov ($b, &DWP(64+4*7,"esp"));
+ &mov ($d_,&DWP(64+4*15,"esp"));
+ &mov ($d, &DWP(64+4*12,"esp"));
+ &mov ($b_,&DWP(64+4*4,"esp"));
+ &mov ($c, &DWP(64+4*8,"esp"));
+ &mov ($c_,&DWP(64+4*9,"esp"));
+ &add ($d,1); # counter value
+ &mov (&DWP(4*7,"esp"),$b);
+ &mov (&DWP(4*15,"esp"),$d_);
+ &mov (&DWP(64+4*12,"esp"),$d); # save counter value
+
+ &mov ($b,10); # loop counter
+ &jmp (&label("loop"));
+
+&set_label("loop",16);
+ &add ($a,$b_); # elsewhere
+ &mov (&DWP(128,"esp"),$b); # save loop counter
+ &mov ($b,$b_);
+ &QUARTERROUND(0, 4, 8, 12, 0);
+ &QUARTERROUND(1, 5, 9, 13, 1);
+ &QUARTERROUND(2, 6,10, 14, 2);
+ &QUARTERROUND(3, 7,11, 15, 3);
+ &QUARTERROUND(0, 5,10, 15, 4);
+ &QUARTERROUND(1, 6,11, 12, 5);
+ &QUARTERROUND(2, 7, 8, 13, 6);
+ &QUARTERROUND(3, 4, 9, 14, 7);
+ &dec ($b);
+ &jnz (&label("loop"));
+
+ &mov ($b,&wparam(2)); # load len
+
+ &add ($a,0x61707865); # accumulate key material
+ &add ($b_,&DWP(64+4*4,"esp"));
+ &add ($c, &DWP(64+4*8,"esp"));
+ &add ($c_,&DWP(64+4*9,"esp"));
+
+ &cmp ($b,64);
+ &jb (&label("tail"));
+
+ &mov ($b,&wparam(1)); # load input pointer
+ &add ($d, &DWP(64+4*12,"esp"));
+ &add ($d_,&DWP(64+4*14,"esp"));
+
+ &xor ($a, &DWP(4*0,$b)); # xor with input
+ &xor ($b_,&DWP(4*4,$b));
+ &mov (&DWP(4*0,"esp"),$a); # off-load for later write
+ &mov ($a,&wparam(0)); # load output pointer
+ &xor ($c, &DWP(4*8,$b));
+ &xor ($c_,&DWP(4*9,$b));
+ &xor ($d, &DWP(4*12,$b));
+ &xor ($d_,&DWP(4*14,$b));
+ &mov (&DWP(4*4,"esp"),$b_);
+ &mov ($b_,&DWP(4*0,"esp"));
+ &mov (&DWP(4*8,"esp"),$c);
+ &mov (&DWP(4*9,"esp"),$c_);
+ &mov (&DWP(4*12,"esp"),$d);
+ &mov (&DWP(4*14,"esp"),$d_);
+
+ &mov (&DWP(4*0,$a),$b_); # write output in order
+ &mov ($b_,&DWP(4*1,"esp"));
+ &mov ($c, &DWP(4*2,"esp"));
+ &mov ($c_,&DWP(4*3,"esp"));
+ &mov ($d, &DWP(4*5,"esp"));
+ &mov ($d_,&DWP(4*6,"esp"));
+ &add ($b_,0x3320646e); # accumulate key material
+ &add ($c, 0x79622d32);
+ &add ($c_,0x6b206574);
+ &add ($d, &DWP(64+4*5,"esp"));
+ &add ($d_,&DWP(64+4*6,"esp"));
+ &xor ($b_,&DWP(4*1,$b));
+ &xor ($c, &DWP(4*2,$b));
+ &xor ($c_,&DWP(4*3,$b));
+ &xor ($d, &DWP(4*5,$b));
+ &xor ($d_,&DWP(4*6,$b));
+ &mov (&DWP(4*1,$a),$b_);
+ &mov ($b_,&DWP(4*4,"esp"));
+ &mov (&DWP(4*2,$a),$c);
+ &mov (&DWP(4*3,$a),$c_);
+ &mov (&DWP(4*4,$a),$b_);
+ &mov (&DWP(4*5,$a),$d);
+ &mov (&DWP(4*6,$a),$d_);
+
+ &mov ($c,&DWP(4*7,"esp"));
+ &mov ($d,&DWP(4*8,"esp"));
+ &mov ($d_,&DWP(4*9,"esp"));
+ &add ($c,&DWP(64+4*7,"esp"));
+ &mov ($b_, &DWP(4*10,"esp"));
+ &xor ($c,&DWP(4*7,$b));
+ &mov ($c_,&DWP(4*11,"esp"));
+ &mov (&DWP(4*7,$a),$c);
+ &mov (&DWP(4*8,$a),$d);
+ &mov (&DWP(4*9,$a),$d_);
+
+ &add ($b_, &DWP(64+4*10,"esp"));
+ &add ($c_,&DWP(64+4*11,"esp"));
+ &xor ($b_, &DWP(4*10,$b));
+ &xor ($c_,&DWP(4*11,$b));
+ &mov (&DWP(4*10,$a),$b_);
+ &mov (&DWP(4*11,$a),$c_);
+
+ &mov ($c,&DWP(4*12,"esp"));
+ &mov ($c_,&DWP(4*14,"esp"));
+ &mov ($d, &DWP(4*13,"esp"));
+ &mov ($d_,&DWP(4*15,"esp"));
+ &add ($d, &DWP(64+4*13,"esp"));
+ &add ($d_,&DWP(64+4*15,"esp"));
+ &xor ($d, &DWP(4*13,$b));
+ &xor ($d_,&DWP(4*15,$b));
+ &lea ($b,&DWP(4*16,$b));
+ &mov (&DWP(4*12,$a),$c);
+ &mov ($c,&wparam(2)); # len
+ &mov (&DWP(4*13,$a),$d);
+ &mov (&DWP(4*14,$a),$c_);
+ &mov (&DWP(4*15,$a),$d_);
+ &lea ($a,&DWP(4*16,$a));
+ &sub ($c,64);
+ &jnz (&label("outer_loop"));
+
+ &jmp (&label("done"));
+
+&set_label("tail");
+ &add ($d, &DWP(64+4*12,"esp"));
+ &add ($d_,&DWP(64+4*14,"esp"));
+ &mov (&DWP(4*0,"esp"),$a);
+ &mov (&DWP(4*4,"esp"),$b_);
+ &mov (&DWP(4*8,"esp"),$c);
+ &mov (&DWP(4*9,"esp"),$c_);
+ &mov (&DWP(4*12,"esp"),$d);
+ &mov (&DWP(4*14,"esp"),$d_);
+
+ &mov ($b_,&DWP(4*1,"esp"));
+ &mov ($c, &DWP(4*2,"esp"));
+ &mov ($c_,&DWP(4*3,"esp"));
+ &mov ($d, &DWP(4*5,"esp"));
+ &mov ($d_,&DWP(4*6,"esp"));
+ &add ($b_,0x3320646e); # accumulate key material
+ &add ($c, 0x79622d32);
+ &add ($c_,0x6b206574);
+ &add ($d, &DWP(64+4*5,"esp"));
+ &add ($d_,&DWP(64+4*6,"esp"));
+ &mov (&DWP(4*1,"esp"),$b_);
+ &mov (&DWP(4*2,"esp"),$c);
+ &mov (&DWP(4*3,"esp"),$c_);
+ &mov (&DWP(4*5,"esp"),$d);
+ &mov (&DWP(4*6,"esp"),$d_);
+
+ &mov ($b_,&DWP(4*7,"esp"));
+ &mov ($c, &DWP(4*10,"esp"));
+ &mov ($c_,&DWP(4*11,"esp"));
+ &mov ($d, &DWP(4*13,"esp"));
+ &mov ($d_,&DWP(4*15,"esp"));
+ &add ($b_,&DWP(64+4*7,"esp"));
+ &add ($c, &DWP(64+4*10,"esp"));
+ &add ($c_,&DWP(64+4*11,"esp"));
+ &add ($d, &DWP(64+4*13,"esp"));
+ &add ($d_,&DWP(64+4*15,"esp"));
+ &mov (&DWP(4*7,"esp"),$b_);
+ &mov ($b_,&wparam(1)); # load input
+ &mov (&DWP(4*10,"esp"),$c);
+ &mov ($c,&wparam(0)); # load output
+ &mov (&DWP(4*11,"esp"),$c_);
+ &xor ($c_,$c_);
+ &mov (&DWP(4*13,"esp"),$d);
+ &mov (&DWP(4*15,"esp"),$d_);
+
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+&set_label("tail_loop");
+ &movb ("al",&BP(0,$c_,$b_));
+ &movb ("dl",&BP(0,"esp",$c_));
+ &lea ($c_,&DWP(1,$c_));
+ &xor ("al","dl");
+ &mov (&BP(-1,$c,$c_),"al");
+ &dec ($b);
+ &jnz (&label("tail_loop"));
+
+&set_label("done");
+ &stack_pop(33);
+&set_label("no_data");
+&function_end("ChaCha20_ctr32");
+
+if ($xmm) {
+my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7));
+my ($out,$inp,$len)=("edi","esi","ecx");
+
+sub QUARTERROUND_SSSE3 {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
+
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+
+ if ($i==0) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==3) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+ } elsif ($i==4) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==7) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+ }
+
+ #&paddd ($xa,$xb); # see elsewhere
+ #&pxor ($xd,$xa); # see elsewhere
+ &movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3);
+ &pshufb ($xd,&QWP(0,"eax")); # rot16
+ &movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0);
+ &paddd ($xc,$xd);
+ &movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3);
+ &pxor ($xb,$xc);
+ &movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7);
+ &movdqa ($xa_,$xb); # borrow as temporary
+ &pslld ($xb,12);
+ &psrld ($xa_,20);
+ &por ($xb,$xa_);
+ &movdqa($xa_,&QWP(16*$an-128,"ebx"));
+ &paddd ($xa,$xb);
+ &movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn);
+ &pxor ($xd,$xa);
+ &movdqa (&QWP(16*$ai-128,"ebx"),$xa);
+ &pshufb ($xd,&QWP(16,"eax")); # rot8
+ &paddd ($xc,$xd);
+ &movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn);
+ &movdqa ($xd_,$xd) if ($di==$dn);
+ &pxor ($xb,$xc);
+ &paddd ($xa_,$xb_) if ($i<7); # elsewhere
+ &movdqa ($xa,$xb); # borrow as temporary
+ &pslld ($xb,7);
+ &psrld ($xa,25);
+ &pxor ($xd_,$xa_) if ($i<7); # elsewhere
+ &por ($xb,$xa);
+
+ ($xa,$xa_)=($xa_,$xa);
+ ($xb,$xb_)=($xb_,$xb);
+ ($xc,$xc_)=($xc_,$xc);
+ ($xd,$xd_)=($xd_,$xd);
+}
+
+&function_begin("ChaCha20_ssse3");
+&set_label("ssse3_shortcut");
+ &mov ($out,&wparam(0));
+ &mov ($inp,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ("edx",&wparam(3)); # key
+ &mov ("ebx",&wparam(4)); # counter and nonce
+
+ &mov ("ebp","esp");
+ &stack_push (131);
+ &and ("esp",-64);
+ &mov (&DWP(512,"esp"),"ebp");
+
+ &lea ("eax",&DWP(&label("ssse3_data")."-".
+ &label("pic_point"),"eax"));
+ &movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce
+
+ &cmp ($len,64*4);
+ &jb (&label("1x"));
+
+ &mov (&DWP(512+4,"esp"),"edx"); # offload pointers
+ &mov (&DWP(512+8,"esp"),"ebx");
+ &sub ($len,64*4); # bias len
+ &lea ("ebp",&DWP(256+128,"esp")); # size optimization
+
+ &movdqu ("xmm7",&QWP(0,"edx")); # key
+ &pshufd ("xmm0","xmm3",0x00);
+ &pshufd ("xmm1","xmm3",0x55);
+ &pshufd ("xmm2","xmm3",0xaa);
+ &pshufd ("xmm3","xmm3",0xff);
+ &paddd ("xmm0",&QWP(16*3,"eax")); # fix counters
+ &pshufd ("xmm4","xmm7",0x00);
+ &pshufd ("xmm5","xmm7",0x55);
+ &psubd ("xmm0",&QWP(16*4,"eax"));
+ &pshufd ("xmm6","xmm7",0xaa);
+ &pshufd ("xmm7","xmm7",0xff);
+ &movdqa (&QWP(16*12-128,"ebp"),"xmm0");
+ &movdqa (&QWP(16*13-128,"ebp"),"xmm1");
+ &movdqa (&QWP(16*14-128,"ebp"),"xmm2");
+ &movdqa (&QWP(16*15-128,"ebp"),"xmm3");
+ &movdqu ("xmm3",&QWP(16,"edx")); # key
+ &movdqa (&QWP(16*4-128,"ebp"),"xmm4");
+ &movdqa (&QWP(16*5-128,"ebp"),"xmm5");
+ &movdqa (&QWP(16*6-128,"ebp"),"xmm6");
+ &movdqa (&QWP(16*7-128,"ebp"),"xmm7");
+ &movdqa ("xmm7",&QWP(16*2,"eax")); # sigma
+ &lea ("ebx",&DWP(128,"esp")); # size optimization
+
+ &pshufd ("xmm0","xmm3",0x00);
+ &pshufd ("xmm1","xmm3",0x55);
+ &pshufd ("xmm2","xmm3",0xaa);
+ &pshufd ("xmm3","xmm3",0xff);
+ &pshufd ("xmm4","xmm7",0x00);
+ &pshufd ("xmm5","xmm7",0x55);
+ &pshufd ("xmm6","xmm7",0xaa);
+ &pshufd ("xmm7","xmm7",0xff);
+ &movdqa (&QWP(16*8-128,"ebp"),"xmm0");
+ &movdqa (&QWP(16*9-128,"ebp"),"xmm1");
+ &movdqa (&QWP(16*10-128,"ebp"),"xmm2");
+ &movdqa (&QWP(16*11-128,"ebp"),"xmm3");
+ &movdqa (&QWP(16*0-128,"ebp"),"xmm4");
+ &movdqa (&QWP(16*1-128,"ebp"),"xmm5");
+ &movdqa (&QWP(16*2-128,"ebp"),"xmm6");
+ &movdqa (&QWP(16*3-128,"ebp"),"xmm7");
+
+ &lea ($inp,&DWP(128,$inp)); # size optimization
+ &lea ($out,&DWP(128,$out)); # size optimization
+ &jmp (&label("outer_loop"));
+
+&set_label("outer_loop",16);
+ #&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material
+ &movdqa ("xmm1",&QWP(16*1-128,"ebp"));
+ &movdqa ("xmm2",&QWP(16*2-128,"ebp"));
+ &movdqa ("xmm3",&QWP(16*3-128,"ebp"));
+ #&movdqa ("xmm4",&QWP(16*4-128,"ebp"));
+ &movdqa ("xmm5",&QWP(16*5-128,"ebp"));
+ &movdqa ("xmm6",&QWP(16*6-128,"ebp"));
+ &movdqa ("xmm7",&QWP(16*7-128,"ebp"));
+ #&movdqa (&QWP(16*0-128,"ebx"),"xmm0");
+ &movdqa (&QWP(16*1-128,"ebx"),"xmm1");
+ &movdqa (&QWP(16*2-128,"ebx"),"xmm2");
+ &movdqa (&QWP(16*3-128,"ebx"),"xmm3");
+ #&movdqa (&QWP(16*4-128,"ebx"),"xmm4");
+ &movdqa (&QWP(16*5-128,"ebx"),"xmm5");
+ &movdqa (&QWP(16*6-128,"ebx"),"xmm6");
+ &movdqa (&QWP(16*7-128,"ebx"),"xmm7");
+ #&movdqa ("xmm0",&QWP(16*8-128,"ebp"));
+ #&movdqa ("xmm1",&QWP(16*9-128,"ebp"));
+ &movdqa ("xmm2",&QWP(16*10-128,"ebp"));
+ &movdqa ("xmm3",&QWP(16*11-128,"ebp"));
+ &movdqa ("xmm4",&QWP(16*12-128,"ebp"));
+ &movdqa ("xmm5",&QWP(16*13-128,"ebp"));
+ &movdqa ("xmm6",&QWP(16*14-128,"ebp"));
+ &movdqa ("xmm7",&QWP(16*15-128,"ebp"));
+ &paddd ("xmm4",&QWP(16*4,"eax")); # counter value
+ #&movdqa (&QWP(16*8-128,"ebx"),"xmm0");
+ #&movdqa (&QWP(16*9-128,"ebx"),"xmm1");
+ &movdqa (&QWP(16*10-128,"ebx"),"xmm2");
+ &movdqa (&QWP(16*11-128,"ebx"),"xmm3");
+ &movdqa (&QWP(16*12-128,"ebx"),"xmm4");
+ &movdqa (&QWP(16*13-128,"ebx"),"xmm5");
+ &movdqa (&QWP(16*14-128,"ebx"),"xmm6");
+ &movdqa (&QWP(16*15-128,"ebx"),"xmm7");
+ &movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value
+
+ &movdqa ($xa, &QWP(16*0-128,"ebp"));
+ &movdqa ($xd, "xmm4");
+ &movdqa ($xb_,&QWP(16*4-128,"ebp"));
+ &movdqa ($xc, &QWP(16*8-128,"ebp"));
+ &movdqa ($xc_,&QWP(16*9-128,"ebp"));
+
+ &mov ("edx",10); # loop counter
+ &nop ();
+
+&set_label("loop",16);
+ &paddd ($xa,$xb_); # elsewhere
+ &movdqa ($xb,$xb_);
+ &pxor ($xd,$xa); # elsewhere
+ &QUARTERROUND_SSSE3(0, 4, 8, 12, 0);
+ &QUARTERROUND_SSSE3(1, 5, 9, 13, 1);
+ &QUARTERROUND_SSSE3(2, 6,10, 14, 2);
+ &QUARTERROUND_SSSE3(3, 7,11, 15, 3);
+ &QUARTERROUND_SSSE3(0, 5,10, 15, 4);
+ &QUARTERROUND_SSSE3(1, 6,11, 12, 5);
+ &QUARTERROUND_SSSE3(2, 7, 8, 13, 6);
+ &QUARTERROUND_SSSE3(3, 4, 9, 14, 7);
+ &dec ("edx");
+ &jnz (&label("loop"));
+
+ &movdqa (&QWP(16*4-128,"ebx"),$xb_);
+ &movdqa (&QWP(16*8-128,"ebx"),$xc);
+ &movdqa (&QWP(16*9-128,"ebx"),$xc_);
+ &movdqa (&QWP(16*12-128,"ebx"),$xd);
+ &movdqa (&QWP(16*14-128,"ebx"),$xd_);
+
+ my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7));
+
+ for($i=0;$i<256;$i+=64) {
+ #&movdqa ($xa0,&QWP($i+16*0-128,"ebx")); # it's there
+ &movdqa ($xa1,&QWP($i+16*1-128,"ebx"));
+ &movdqa ($xa2,&QWP($i+16*2-128,"ebx"));
+ &movdqa ($xa3,&QWP($i+16*3-128,"ebx"));
+
+ &paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material
+ &paddd ($xa1,&QWP($i+16*1-128,"ebp"));
+ &paddd ($xa2,&QWP($i+16*2-128,"ebp"));
+ &paddd ($xa3,&QWP($i+16*3-128,"ebp"));
+
+ &movdqa ($xt2,$xa0); # "de-interlace" data
+ &punpckldq ($xa0,$xa1);
+ &movdqa ($xt3,$xa2);
+ &punpckldq ($xa2,$xa3);
+ &punpckhdq ($xt2,$xa1);
+ &punpckhdq ($xt3,$xa3);
+ &movdqa ($xa1,$xa0);
+ &punpcklqdq ($xa0,$xa2); # "a0"
+ &movdqa ($xa3,$xt2);
+ &punpcklqdq ($xt2,$xt3); # "a2"
+ &punpckhqdq ($xa1,$xa2); # "a1"
+ &punpckhqdq ($xa3,$xt3); # "a3"
+
+ #($xa2,$xt2)=($xt2,$xa2);
+
+ &movdqa (&QWP($i+16*0-128,"ebx"),$xa0);
+ &movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192);
+ &movdqa (&QWP($i+16*1-128,"ebx"),$xa1);
+ &movdqa (&QWP($i+16*2-128,"ebx"),$xt2);
+ &movdqa (&QWP($i+16*3-128,"ebx"),$xa3);
+ }
+ for($i=0;$i<256;$i+=64) {
+ my $j = 16*($i/64);
+ &movdqu ($xa0,&QWP($i+16*0-128,$inp)); # load input
+ &movdqu ($xa1,&QWP($i+16*1-128,$inp));
+ &movdqu ($xa2,&QWP($i+16*2-128,$inp));
+ &movdqu ($xa3,&QWP($i+16*3-128,$inp));
+ &pxor ($xa0,&QWP($j+64*0-128,"ebx"));
+ &pxor ($xa1,&QWP($j+64*1-128,"ebx"));
+ &pxor ($xa2,&QWP($j+64*2-128,"ebx"));
+ &pxor ($xa3,&QWP($j+64*3-128,"ebx"));
+ &movdqu (&QWP($i+16*0-128,$out),$xa0); # write output
+ &movdqu (&QWP($i+16*1-128,$out),$xa1);
+ &movdqu (&QWP($i+16*2-128,$out),$xa2);
+ &movdqu (&QWP($i+16*3-128,$out),$xa3);
+ }
+ &lea ($inp,&DWP(256,$inp));
+ &lea ($out,&DWP(256,$out));
+ &sub ($len,64*4);
+ &jnc (&label("outer_loop"));
+
+ &add ($len,64*4);
+ &jz (&label("done"));
+
+ &mov ("ebx",&DWP(512+8,"esp")); # restore pointers
+ &lea ($inp,&DWP(-128,$inp));
+ &mov ("edx",&DWP(512+4,"esp"));
+ &lea ($out,&DWP(-128,$out));
+
+ &movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value
+ &movdqu ("xmm3",&QWP(0,"ebx"));
+ &paddd ("xmm2",&QWP(16*6,"eax")); # +four
+ &pand ("xmm3",&QWP(16*7,"eax"));
+ &por ("xmm3","xmm2"); # counter value
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7));
+
+sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot16);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,20);
+ &pslld ($t,12);
+ &por ($b,$t);
+
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot24);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,25);
+ &pslld ($t,7);
+ &por ($b,$t);
+}
+
+&set_label("1x");
+ &movdqa ($a,&QWP(16*2,"eax")); # sigma
+ &movdqu ($b,&QWP(0,"edx"));
+ &movdqu ($c,&QWP(16,"edx"));
+ #&movdqu ($d,&QWP(0,"ebx")); # already loaded
+ &movdqa ($rot16,&QWP(0,"eax"));
+ &movdqa ($rot24,&QWP(16,"eax"));
+ &mov (&DWP(16*3,"esp"),"ebp");
+
+ &movdqa (&QWP(16*0,"esp"),$a);
+ &movdqa (&QWP(16*1,"esp"),$b);
+ &movdqa (&QWP(16*2,"esp"),$c);
+ &movdqa (&QWP(16*3,"esp"),$d);
+ &mov ("edx",10);
+ &jmp (&label("loop1x"));
+
+&set_label("outer1x",16);
+ &movdqa ($d,&QWP(16*5,"eax")); # one
+ &movdqa ($a,&QWP(16*0,"esp"));
+ &movdqa ($b,&QWP(16*1,"esp"));
+ &movdqa ($c,&QWP(16*2,"esp"));
+ &paddd ($d,&QWP(16*3,"esp"));
+ &mov ("edx",10);
+ &movdqa (&QWP(16*3,"esp"),$d);
+ &jmp (&label("loop1x"));
+
+&set_label("loop1x",16);
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b00111001);
+ &pshufd ($d,$d,0b10010011);
+ &nop ();
+
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b10010011);
+ &pshufd ($d,$d,0b00111001);
+
+ &dec ("edx");
+ &jnz (&label("loop1x"));
+
+ &paddd ($a,&QWP(16*0,"esp"));
+ &paddd ($b,&QWP(16*1,"esp"));
+ &paddd ($c,&QWP(16*2,"esp"));
+ &paddd ($d,&QWP(16*3,"esp"));
+
+ &cmp ($len,64);
+ &jb (&label("tail"));
+
+ &movdqu ($t,&QWP(16*0,$inp));
+ &movdqu ($t1,&QWP(16*1,$inp));
+ &pxor ($a,$t); # xor with input
+ &movdqu ($t,&QWP(16*2,$inp));
+ &pxor ($b,$t1);
+ &movdqu ($t1,&QWP(16*3,$inp));
+ &pxor ($c,$t);
+ &pxor ($d,$t1);
+ &lea ($inp,&DWP(16*4,$inp)); # inp+=64
+
+ &movdqu (&QWP(16*0,$out),$a); # write output
+ &movdqu (&QWP(16*1,$out),$b);
+ &movdqu (&QWP(16*2,$out),$c);
+ &movdqu (&QWP(16*3,$out),$d);
+ &lea ($out,&DWP(16*4,$out)); # inp+=64
+
+ &sub ($len,64);
+ &jnz (&label("outer1x"));
+
+ &jmp (&label("done"));
+
+&set_label("tail");
+ &movdqa (&QWP(16*0,"esp"),$a);
+ &movdqa (&QWP(16*1,"esp"),$b);
+ &movdqa (&QWP(16*2,"esp"),$c);
+ &movdqa (&QWP(16*3,"esp"),$d);
+
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &xor ("ebp","ebp");
+
+&set_label("tail_loop");
+ &movb ("al",&BP(0,"esp","ebp"));
+ &movb ("dl",&BP(0,$inp,"ebp"));
+ &lea ("ebp",&DWP(1,"ebp"));
+ &xor ("al","dl");
+ &movb (&BP(-1,$out,"ebp"),"al");
+ &dec ($len);
+ &jnz (&label("tail_loop"));
+}
+&set_label("done");
+ &mov ("esp",&DWP(512,"esp"));
+&function_end("ChaCha20_ssse3");
+
+&align (64);
+&set_label("ssse3_data");
+&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd);
+&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe);
+&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574);
+&data_word(0,1,2,3);
+&data_word(4,4,4,4);
+&data_word(1,0,0,0);
+&data_word(4,0,0,0);
+&data_word(0,-1,-1,-1);
+&align (64);
+}
+&asciz ("ChaCha20 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/chacha/asm/chacha-x86_64.pl b/src/crypto/chacha/asm/chacha-x86_64.pl
new file mode 100755
index 00000000..55b726d2
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-x86_64.pl
@@ -0,0 +1,1767 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# November 2014
+#
+# ChaCha20 for x86_64.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 8xAVX2
+#
+# P4 9.48/+99% -/22.7(ii) -
+# Core2 7.83/+55% 7.90/8.08 4.35
+# Westmere 7.19/+50% 5.60/6.70 3.00
+# Sandy Bridge 8.31/+42% 5.45/6.76 2.72
+# Ivy Bridge 6.71/+46% 5.40/6.49 2.41
+# Haswell 5.92/+43% 5.20/6.45 2.42 1.23
+# Silvermont 12.0/+33% 7.75/7.40 7.03(iii)
+# Sledgehammer 7.28/+52% -/14.2(ii) -
+# Bulldozer 9.66/+28% 9.85/11.1 3.06(iv)
+# VIA Nano 10.5/+46% 6.72/8.60 6.05
+#
+# (i) compared to older gcc 3.x one can observe >2x improvement on
+# most platforms;
+# (ii) as it can be seen, SSE2 performance is too low on legacy
+# processors; NxSSE2 results are naturally better, but not
+# impressively better than IALU ones, which is why you won't
+# find SSE2 code below;
+# (iii) this is not optimal result for Atom because of MSROM
+# limitations, SSE2 can do better, but gain is considered too
+# low to justify the [maintenance] effort;
+# (iv) Bulldozer actually executes 4xXOP code path that delivers 2.20;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$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";
+
+$avx = 2;
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+# input parameter block
+($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8");
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.align 64
+.Lzero:
+.long 0,0,0,0
+.Lone:
+.long 1,0,0,0
+.Linc:
+.long 0,1,2,3
+.Lfour:
+.long 4,4,4,4
+.Lincy:
+.long 0,2,4,6,1,3,5,7
+.Leight:
+.long 8,8,8,8,8,8,8,8
+.Lrot16:
+.byte 0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd
+.Lrot24:
+.byte 0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe
+.Lsigma:
+.asciz "expand 32-byte k"
+.asciz "ChaCha20 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+
+sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+ my $arg = pop;
+ $arg = "\$$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)),
+ "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15)));
+@t=("%esi","%edi");
+
+sub ROUND { # critical path is 24 cycles per round
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_)=map("\"$_\"",@t);
+my @x=map("\"$_\"",@x);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ # Normally instructions would be interleaved to favour in-order
+ # execution. Generally out-of-order cores manage it gracefully,
+ # but not this time for some reason. As in-order execution
+ # cores are dying breed, old Atom is the only one around,
+ # instructions are left uninterleaved. Besides, Atom is better
+ # off executing 1xSSSE3 code anyway...
+
+ (
+ "&add (@x[$a0],@x[$b0])", # Q1
+ "&xor (@x[$d0],@x[$a0])",
+ "&rol (@x[$d0],16)",
+ "&add (@x[$a1],@x[$b1])", # Q2
+ "&xor (@x[$d1],@x[$a1])",
+ "&rol (@x[$d1],16)",
+
+ "&add ($xc,@x[$d0])",
+ "&xor (@x[$b0],$xc)",
+ "&rol (@x[$b0],12)",
+ "&add ($xc_,@x[$d1])",
+ "&xor (@x[$b1],$xc_)",
+ "&rol (@x[$b1],12)",
+
+ "&add (@x[$a0],@x[$b0])",
+ "&xor (@x[$d0],@x[$a0])",
+ "&rol (@x[$d0],8)",
+ "&add (@x[$a1],@x[$b1])",
+ "&xor (@x[$d1],@x[$a1])",
+ "&rol (@x[$d1],8)",
+
+ "&add ($xc,@x[$d0])",
+ "&xor (@x[$b0],$xc)",
+ "&rol (@x[$b0],7)",
+ "&add ($xc_,@x[$d1])",
+ "&xor (@x[$b1],$xc_)",
+ "&rol (@x[$b1],7)",
+
+ "&mov (\"4*$c0(%rsp)\",$xc)", # reload pair of 'c's
+ "&mov (\"4*$c1(%rsp)\",$xc_)",
+ "&mov ($xc,\"4*$c2(%rsp)\")",
+ "&mov ($xc_,\"4*$c3(%rsp)\")",
+
+ "&add (@x[$a2],@x[$b2])", # Q3
+ "&xor (@x[$d2],@x[$a2])",
+ "&rol (@x[$d2],16)",
+ "&add (@x[$a3],@x[$b3])", # Q4
+ "&xor (@x[$d3],@x[$a3])",
+ "&rol (@x[$d3],16)",
+
+ "&add ($xc,@x[$d2])",
+ "&xor (@x[$b2],$xc)",
+ "&rol (@x[$b2],12)",
+ "&add ($xc_,@x[$d3])",
+ "&xor (@x[$b3],$xc_)",
+ "&rol (@x[$b3],12)",
+
+ "&add (@x[$a2],@x[$b2])",
+ "&xor (@x[$d2],@x[$a2])",
+ "&rol (@x[$d2],8)",
+ "&add (@x[$a3],@x[$b3])",
+ "&xor (@x[$d3],@x[$a3])",
+ "&rol (@x[$d3],8)",
+
+ "&add ($xc,@x[$d2])",
+ "&xor (@x[$b2],$xc)",
+ "&rol (@x[$b2],7)",
+ "&add ($xc_,@x[$d3])",
+ "&xor (@x[$b3],$xc_)",
+ "&rol (@x[$b3],7)"
+ );
+}
+
+########################################################################
+# Generic code path that handles all lengths on pre-SSSE3 processors.
+$code.=<<___;
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,\@function,5
+.align 64
+ChaCha20_ctr32:
+ cmp \$0,$len
+ je .Lno_data
+ mov OPENSSL_ia32cap_P+4(%rip),%r10
+ test \$`1<<(41-32)`,%r10d
+ jnz .LChaCha20_ssse3
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ sub \$64+24,%rsp
+
+ #movdqa .Lsigma(%rip),%xmm0
+ movdqu ($key),%xmm1
+ movdqu 16($key),%xmm2
+ movdqu ($counter),%xmm3
+ movdqa .Lone(%rip),%xmm4
+
+ #movdqa %xmm0,4*0(%rsp) # key[0]
+ movdqa %xmm1,4*4(%rsp) # key[1]
+ movdqa %xmm2,4*8(%rsp) # key[2]
+ movdqa %xmm3,4*12(%rsp) # key[3]
+ mov $len,%rbp # reassign $len
+ jmp .Loop_outer
+
+.align 32
+.Loop_outer:
+ mov \$0x61707865,@x[0] # 'expa'
+ mov \$0x3320646e,@x[1] # 'nd 3'
+ mov \$0x79622d32,@x[2] # '2-by'
+ mov \$0x6b206574,@x[3] # 'te k'
+ mov 4*4(%rsp),@x[4]
+ mov 4*5(%rsp),@x[5]
+ mov 4*6(%rsp),@x[6]
+ mov 4*7(%rsp),@x[7]
+ movd %xmm3,@x[12]
+ mov 4*13(%rsp),@x[13]
+ mov 4*14(%rsp),@x[14]
+ mov 4*15(%rsp),@x[15]
+
+ mov %rbp,64+0(%rsp) # save len
+ mov \$10,%ebp
+ mov $inp,64+8(%rsp) # save inp
+ movq %xmm2,%rsi # "@x[8]"
+ mov $out,64+16(%rsp) # save out
+ mov %rsi,%rdi
+ shr \$32,%rdi # "@x[9]"
+ jmp .Loop
+
+.align 32
+.Loop:
+___
+ foreach (&ROUND (0, 4, 8,12)) { eval; }
+ foreach (&ROUND (0, 5,10,15)) { eval; }
+ &dec ("%ebp");
+ &jnz (".Loop");
+
+$code.=<<___;
+ mov @t[1],4*9(%rsp) # modulo-scheduled
+ mov @t[0],4*8(%rsp)
+ mov 64(%rsp),%rbp # load len
+ movdqa %xmm2,%xmm1
+ mov 64+8(%rsp),$inp # load inp
+ paddd %xmm4,%xmm3 # increment counter
+ mov 64+16(%rsp),$out # load out
+
+ add \$0x61707865,@x[0] # 'expa'
+ add \$0x3320646e,@x[1] # 'nd 3'
+ add \$0x79622d32,@x[2] # '2-by'
+ add \$0x6b206574,@x[3] # 'te k'
+ add 4*4(%rsp),@x[4]
+ add 4*5(%rsp),@x[5]
+ add 4*6(%rsp),@x[6]
+ add 4*7(%rsp),@x[7]
+ add 4*12(%rsp),@x[12]
+ add 4*13(%rsp),@x[13]
+ add 4*14(%rsp),@x[14]
+ add 4*15(%rsp),@x[15]
+ paddd 4*8(%rsp),%xmm1
+
+ cmp \$64,%rbp
+ jb .Ltail
+
+ xor 4*0($inp),@x[0] # xor with input
+ xor 4*1($inp),@x[1]
+ xor 4*2($inp),@x[2]
+ xor 4*3($inp),@x[3]
+ xor 4*4($inp),@x[4]
+ xor 4*5($inp),@x[5]
+ xor 4*6($inp),@x[6]
+ xor 4*7($inp),@x[7]
+ movdqu 4*8($inp),%xmm0
+ xor 4*12($inp),@x[12]
+ xor 4*13($inp),@x[13]
+ xor 4*14($inp),@x[14]
+ xor 4*15($inp),@x[15]
+ lea 4*16($inp),$inp # inp+=64
+ pxor %xmm1,%xmm0
+
+ movdqa %xmm2,4*8(%rsp)
+ movd %xmm3,4*12(%rsp)
+
+ mov @x[0],4*0($out) # write output
+ mov @x[1],4*1($out)
+ mov @x[2],4*2($out)
+ mov @x[3],4*3($out)
+ mov @x[4],4*4($out)
+ mov @x[5],4*5($out)
+ mov @x[6],4*6($out)
+ mov @x[7],4*7($out)
+ movdqu %xmm0,4*8($out)
+ mov @x[12],4*12($out)
+ mov @x[13],4*13($out)
+ mov @x[14],4*14($out)
+ mov @x[15],4*15($out)
+ lea 4*16($out),$out # out+=64
+
+ sub \$64,%rbp
+ jnz .Loop_outer
+
+ jmp .Ldone
+
+.align 16
+.Ltail:
+ mov @x[0],4*0(%rsp)
+ mov @x[1],4*1(%rsp)
+ xor %rbx,%rbx
+ mov @x[2],4*2(%rsp)
+ mov @x[3],4*3(%rsp)
+ mov @x[4],4*4(%rsp)
+ mov @x[5],4*5(%rsp)
+ mov @x[6],4*6(%rsp)
+ mov @x[7],4*7(%rsp)
+ movdqa %xmm1,4*8(%rsp)
+ mov @x[12],4*12(%rsp)
+ mov @x[13],4*13(%rsp)
+ mov @x[14],4*14(%rsp)
+ mov @x[15],4*15(%rsp)
+
+.Loop_tail:
+ movzb ($inp,%rbx),%eax
+ movzb (%rsp,%rbx),%edx
+ lea 1(%rbx),%rbx
+ xor %edx,%eax
+ mov %al,-1($out,%rbx)
+ dec %rbp
+ jnz .Loop_tail
+
+.Ldone:
+ add \$64+24,%rsp
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+.Lno_data:
+ ret
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+########################################################################
+# SSSE3 code path that handles shorter lengths
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7));
+
+sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot16);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,20);
+ &pslld ($t,12);
+ &por ($b,$t);
+
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot24);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,25);
+ &pslld ($t,7);
+ &por ($b,$t);
+}
+
+my $xframe = $win64 ? 32+32+8 : 24;
+
+$code.=<<___;
+.type ChaCha20_ssse3,\@function,5
+.align 32
+ChaCha20_ssse3:
+.LChaCha20_ssse3:
+___
+$code.=<<___;
+ cmp \$128,$len # we might throw away some data,
+ ja .LChaCha20_4x # but overall it won't be slower
+
+.Ldo_sse3_after_all:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ sub \$64+$xframe,%rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,64+32(%rsp)
+ movaps %xmm7,64+48(%rsp)
+___
+$code.=<<___;
+ movdqa .Lsigma(%rip),$a
+ movdqu ($key),$b
+ movdqu 16($key),$c
+ movdqu ($counter),$d
+ movdqa .Lrot16(%rip),$rot16
+ movdqa .Lrot24(%rip),$rot24
+
+ movdqa $a,0x00(%rsp)
+ movdqa $b,0x10(%rsp)
+ movdqa $c,0x20(%rsp)
+ movdqa $d,0x30(%rsp)
+ mov \$10,%ebp
+ jmp .Loop_ssse3
+
+.align 32
+.Loop_outer_ssse3:
+ movdqa .Lone(%rip),$d
+ movdqa 0x00(%rsp),$a
+ movdqa 0x10(%rsp),$b
+ movdqa 0x20(%rsp),$c
+ paddd 0x30(%rsp),$d
+ mov \$10,%ebp
+ movdqa $d,0x30(%rsp)
+ jmp .Loop_ssse3
+
+.align 32
+.Loop_ssse3:
+___
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b00111001);
+ &pshufd ($d,$d,0b10010011);
+ &nop ();
+
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b10010011);
+ &pshufd ($d,$d,0b00111001);
+
+ &dec ("%ebp");
+ &jnz (".Loop_ssse3");
+
+$code.=<<___;
+ paddd 0x00(%rsp),$a
+ paddd 0x10(%rsp),$b
+ paddd 0x20(%rsp),$c
+ paddd 0x30(%rsp),$d
+
+ cmp \$64,$len
+ jb .Ltail_ssse3
+
+ movdqu 0x00($inp),$t
+ movdqu 0x10($inp),$t1
+ pxor $t,$a # xor with input
+ movdqu 0x20($inp),$t
+ pxor $t1,$b
+ movdqu 0x30($inp),$t1
+ lea 0x40($inp),$inp # inp+=64
+ pxor $t,$c
+ pxor $t1,$d
+
+ movdqu $a,0x00($out) # write output
+ movdqu $b,0x10($out)
+ movdqu $c,0x20($out)
+ movdqu $d,0x30($out)
+ lea 0x40($out),$out # out+=64
+
+ sub \$64,$len
+ jnz .Loop_outer_ssse3
+
+ jmp .Ldone_ssse3
+
+.align 16
+.Ltail_ssse3:
+ movdqa $a,0x00(%rsp)
+ movdqa $b,0x10(%rsp)
+ movdqa $c,0x20(%rsp)
+ movdqa $d,0x30(%rsp)
+ xor %rbx,%rbx
+
+.Loop_tail_ssse3:
+ movzb ($inp,%rbx),%eax
+ movzb (%rsp,%rbx),%ecx
+ lea 1(%rbx),%rbx
+ xor %ecx,%eax
+ mov %al,-1($out,%rbx)
+ dec $len
+ jnz .Loop_tail_ssse3
+
+.Ldone_ssse3:
+___
+$code.=<<___ if ($win64);
+ movaps 64+32(%rsp),%xmm6
+ movaps 64+48(%rsp),%xmm7
+___
+$code.=<<___;
+ add \$64+$xframe,%rsp
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ ret
+.size ChaCha20_ssse3,.-ChaCha20_ssse3
+___
+}
+
+########################################################################
+# SSSE3 code path that handles longer messages.
+{
+# assign variables to favor Atom front-end
+my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3,
+ $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15));
+my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub SSSE3_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ (
+ "&paddd (@x[$a0],@x[$b0])", # Q1
+ "&paddd (@x[$a1],@x[$b1])", # Q2
+ "&pxor (@x[$d0],@x[$a0])",
+ "&pxor (@x[$d1],@x[$a1])",
+ "&pshufb (@x[$d0],$t1)",
+ "&pshufb (@x[$d1],$t1)",
+
+ "&paddd ($xc,@x[$d0])",
+ "&paddd ($xc_,@x[$d1])",
+ "&pxor (@x[$b0],$xc)",
+ "&pxor (@x[$b1],$xc_)",
+ "&movdqa ($t0,@x[$b0])",
+ "&pslld (@x[$b0],12)",
+ "&psrld ($t0,20)",
+ "&movdqa ($t1,@x[$b1])",
+ "&pslld (@x[$b1],12)",
+ "&por (@x[$b0],$t0)",
+ "&psrld ($t1,20)",
+ "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip)
+ "&por (@x[$b1],$t1)",
+
+ "&paddd (@x[$a0],@x[$b0])",
+ "&paddd (@x[$a1],@x[$b1])",
+ "&pxor (@x[$d0],@x[$a0])",
+ "&pxor (@x[$d1],@x[$a1])",
+ "&pshufb (@x[$d0],$t0)",
+ "&pshufb (@x[$d1],$t0)",
+
+ "&paddd ($xc,@x[$d0])",
+ "&paddd ($xc_,@x[$d1])",
+ "&pxor (@x[$b0],$xc)",
+ "&pxor (@x[$b1],$xc_)",
+ "&movdqa ($t1,@x[$b0])",
+ "&pslld (@x[$b0],7)",
+ "&psrld ($t1,25)",
+ "&movdqa ($t0,@x[$b1])",
+ "&pslld (@x[$b1],7)",
+ "&por (@x[$b0],$t1)",
+ "&psrld ($t0,25)",
+ "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip)
+ "&por (@x[$b1],$t0)",
+
+ "&movdqa (\"`16*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's
+ "&movdqa (\"`16*($c1-8)`(%rsp)\",$xc_)",
+ "&movdqa ($xc,\"`16*($c2-8)`(%rsp)\")",
+ "&movdqa ($xc_,\"`16*($c3-8)`(%rsp)\")",
+
+ "&paddd (@x[$a2],@x[$b2])", # Q3
+ "&paddd (@x[$a3],@x[$b3])", # Q4
+ "&pxor (@x[$d2],@x[$a2])",
+ "&pxor (@x[$d3],@x[$a3])",
+ "&pshufb (@x[$d2],$t1)",
+ "&pshufb (@x[$d3],$t1)",
+
+ "&paddd ($xc,@x[$d2])",
+ "&paddd ($xc_,@x[$d3])",
+ "&pxor (@x[$b2],$xc)",
+ "&pxor (@x[$b3],$xc_)",
+ "&movdqa ($t0,@x[$b2])",
+ "&pslld (@x[$b2],12)",
+ "&psrld ($t0,20)",
+ "&movdqa ($t1,@x[$b3])",
+ "&pslld (@x[$b3],12)",
+ "&por (@x[$b2],$t0)",
+ "&psrld ($t1,20)",
+ "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip)
+ "&por (@x[$b3],$t1)",
+
+ "&paddd (@x[$a2],@x[$b2])",
+ "&paddd (@x[$a3],@x[$b3])",
+ "&pxor (@x[$d2],@x[$a2])",
+ "&pxor (@x[$d3],@x[$a3])",
+ "&pshufb (@x[$d2],$t0)",
+ "&pshufb (@x[$d3],$t0)",
+
+ "&paddd ($xc,@x[$d2])",
+ "&paddd ($xc_,@x[$d3])",
+ "&pxor (@x[$b2],$xc)",
+ "&pxor (@x[$b3],$xc_)",
+ "&movdqa ($t1,@x[$b2])",
+ "&pslld (@x[$b2],7)",
+ "&psrld ($t1,25)",
+ "&movdqa ($t0,@x[$b3])",
+ "&pslld (@x[$b3],7)",
+ "&por (@x[$b2],$t1)",
+ "&psrld ($t0,25)",
+ "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip)
+ "&por (@x[$b3],$t0)"
+ );
+}
+
+my $xframe = $win64 ? 0xa0 : 0;
+
+$code.=<<___;
+.type ChaCha20_4x,\@function,5
+.align 32
+ChaCha20_4x:
+.LChaCha20_4x:
+ mov %r10,%r11
+___
+$code.=<<___ if ($avx>1);
+ shr \$32,%r10 # OPENSSL_ia32cap_P+8
+ test \$`1<<5`,%r10 # test AVX2
+ jnz .LChaCha20_8x
+___
+$code.=<<___;
+ cmp \$192,$len
+ ja .Lproceed4x
+
+ and \$`1<<26|1<<22`,%r11 # isolate XSAVE+MOVBE
+ cmp \$`1<<22`,%r11 # check for MOVBE without XSAVE
+ je .Ldo_sse3_after_all # to detect Atom
+
+.Lproceed4x:
+ lea -0x78(%rsp),%r11
+ sub \$0x148+$xframe,%rsp
+___
+ ################ stack layout
+ # +0x00 SIMD equivalent of @x[8-12]
+ # ...
+ # +0x40 constant copy of key[0-2] smashed by lanes
+ # ...
+ # +0x100 SIMD counters (with nonce smashed by lanes)
+ # ...
+ # +0x140
+$code.=<<___ if ($win64);
+ movaps %xmm6,-0x30(%r11)
+ movaps %xmm7,-0x20(%r11)
+ movaps %xmm8,-0x10(%r11)
+ movaps %xmm9,0x00(%r11)
+ movaps %xmm10,0x10(%r11)
+ movaps %xmm11,0x20(%r11)
+ movaps %xmm12,0x30(%r11)
+ movaps %xmm13,0x40(%r11)
+ movaps %xmm14,0x50(%r11)
+ movaps %xmm15,0x60(%r11)
+___
+$code.=<<___;
+ movdqa .Lsigma(%rip),$xa3 # key[0]
+ movdqu ($key),$xb3 # key[1]
+ movdqu 16($key),$xt3 # key[2]
+ movdqu ($counter),$xd3 # key[3]
+ lea 0x100(%rsp),%rcx # size optimization
+ lea .Lrot16(%rip),%r10
+ lea .Lrot24(%rip),%r11
+
+ pshufd \$0x00,$xa3,$xa0 # smash key by lanes...
+ pshufd \$0x55,$xa3,$xa1
+ movdqa $xa0,0x40(%rsp) # ... and offload
+ pshufd \$0xaa,$xa3,$xa2
+ movdqa $xa1,0x50(%rsp)
+ pshufd \$0xff,$xa3,$xa3
+ movdqa $xa2,0x60(%rsp)
+ movdqa $xa3,0x70(%rsp)
+
+ pshufd \$0x00,$xb3,$xb0
+ pshufd \$0x55,$xb3,$xb1
+ movdqa $xb0,0x80-0x100(%rcx)
+ pshufd \$0xaa,$xb3,$xb2
+ movdqa $xb1,0x90-0x100(%rcx)
+ pshufd \$0xff,$xb3,$xb3
+ movdqa $xb2,0xa0-0x100(%rcx)
+ movdqa $xb3,0xb0-0x100(%rcx)
+
+ pshufd \$0x00,$xt3,$xt0 # "$xc0"
+ pshufd \$0x55,$xt3,$xt1 # "$xc1"
+ movdqa $xt0,0xc0-0x100(%rcx)
+ pshufd \$0xaa,$xt3,$xt2 # "$xc2"
+ movdqa $xt1,0xd0-0x100(%rcx)
+ pshufd \$0xff,$xt3,$xt3 # "$xc3"
+ movdqa $xt2,0xe0-0x100(%rcx)
+ movdqa $xt3,0xf0-0x100(%rcx)
+
+ pshufd \$0x00,$xd3,$xd0
+ pshufd \$0x55,$xd3,$xd1
+ paddd .Linc(%rip),$xd0 # don't save counters yet
+ pshufd \$0xaa,$xd3,$xd2
+ movdqa $xd1,0x110-0x100(%rcx)
+ pshufd \$0xff,$xd3,$xd3
+ movdqa $xd2,0x120-0x100(%rcx)
+ movdqa $xd3,0x130-0x100(%rcx)
+
+ jmp .Loop_enter4x
+
+.align 32
+.Loop_outer4x:
+ movdqa 0x40(%rsp),$xa0 # re-load smashed key
+ movdqa 0x50(%rsp),$xa1
+ movdqa 0x60(%rsp),$xa2
+ movdqa 0x70(%rsp),$xa3
+ movdqa 0x80-0x100(%rcx),$xb0
+ movdqa 0x90-0x100(%rcx),$xb1
+ movdqa 0xa0-0x100(%rcx),$xb2
+ movdqa 0xb0-0x100(%rcx),$xb3
+ movdqa 0xc0-0x100(%rcx),$xt0 # "$xc0"
+ movdqa 0xd0-0x100(%rcx),$xt1 # "$xc1"
+ movdqa 0xe0-0x100(%rcx),$xt2 # "$xc2"
+ movdqa 0xf0-0x100(%rcx),$xt3 # "$xc3"
+ movdqa 0x100-0x100(%rcx),$xd0
+ movdqa 0x110-0x100(%rcx),$xd1
+ movdqa 0x120-0x100(%rcx),$xd2
+ movdqa 0x130-0x100(%rcx),$xd3
+ paddd .Lfour(%rip),$xd0 # next SIMD counters
+
+.Loop_enter4x:
+ movdqa $xt2,0x20(%rsp) # SIMD equivalent of "@x[10]"
+ movdqa $xt3,0x30(%rsp) # SIMD equivalent of "@x[11]"
+ movdqa (%r10),$xt3 # .Lrot16(%rip)
+ mov \$10,%eax
+ movdqa $xd0,0x100-0x100(%rcx) # save SIMD counters
+ jmp .Loop4x
+
+.align 32
+.Loop4x:
+___
+ foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; }
+ foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ dec %eax
+ jnz .Loop4x
+
+ paddd 0x40(%rsp),$xa0 # accumulate key material
+ paddd 0x50(%rsp),$xa1
+ paddd 0x60(%rsp),$xa2
+ paddd 0x70(%rsp),$xa3
+
+ movdqa $xa0,$xt2 # "de-interlace" data
+ punpckldq $xa1,$xa0
+ movdqa $xa2,$xt3
+ punpckldq $xa3,$xa2
+ punpckhdq $xa1,$xt2
+ punpckhdq $xa3,$xt3
+ movdqa $xa0,$xa1
+ punpcklqdq $xa2,$xa0 # "a0"
+ movdqa $xt2,$xa3
+ punpcklqdq $xt3,$xt2 # "a2"
+ punpckhqdq $xa2,$xa1 # "a1"
+ punpckhqdq $xt3,$xa3 # "a3"
+___
+ ($xa2,$xt2)=($xt2,$xa2);
+$code.=<<___;
+ paddd 0x80-0x100(%rcx),$xb0
+ paddd 0x90-0x100(%rcx),$xb1
+ paddd 0xa0-0x100(%rcx),$xb2
+ paddd 0xb0-0x100(%rcx),$xb3
+
+ movdqa $xa0,0x00(%rsp) # offload $xaN
+ movdqa $xa1,0x10(%rsp)
+ movdqa 0x20(%rsp),$xa0 # "xc2"
+ movdqa 0x30(%rsp),$xa1 # "xc3"
+
+ movdqa $xb0,$xt2
+ punpckldq $xb1,$xb0
+ movdqa $xb2,$xt3
+ punpckldq $xb3,$xb2
+ punpckhdq $xb1,$xt2
+ punpckhdq $xb3,$xt3
+ movdqa $xb0,$xb1
+ punpcklqdq $xb2,$xb0 # "b0"
+ movdqa $xt2,$xb3
+ punpcklqdq $xt3,$xt2 # "b2"
+ punpckhqdq $xb2,$xb1 # "b1"
+ punpckhqdq $xt3,$xb3 # "b3"
+___
+ ($xb2,$xt2)=($xt2,$xb2);
+ my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+ paddd 0xc0-0x100(%rcx),$xc0
+ paddd 0xd0-0x100(%rcx),$xc1
+ paddd 0xe0-0x100(%rcx),$xc2
+ paddd 0xf0-0x100(%rcx),$xc3
+
+ movdqa $xa2,0x20(%rsp) # keep offloading $xaN
+ movdqa $xa3,0x30(%rsp)
+
+ movdqa $xc0,$xt2
+ punpckldq $xc1,$xc0
+ movdqa $xc2,$xt3
+ punpckldq $xc3,$xc2
+ punpckhdq $xc1,$xt2
+ punpckhdq $xc3,$xt3
+ movdqa $xc0,$xc1
+ punpcklqdq $xc2,$xc0 # "c0"
+ movdqa $xt2,$xc3
+ punpcklqdq $xt3,$xt2 # "c2"
+ punpckhqdq $xc2,$xc1 # "c1"
+ punpckhqdq $xt3,$xc3 # "c3"
+___
+ ($xc2,$xt2)=($xt2,$xc2);
+ ($xt0,$xt1)=($xa2,$xa3); # use $xaN as temporary
+$code.=<<___;
+ paddd 0x100-0x100(%rcx),$xd0
+ paddd 0x110-0x100(%rcx),$xd1
+ paddd 0x120-0x100(%rcx),$xd2
+ paddd 0x130-0x100(%rcx),$xd3
+
+ movdqa $xd0,$xt2
+ punpckldq $xd1,$xd0
+ movdqa $xd2,$xt3
+ punpckldq $xd3,$xd2
+ punpckhdq $xd1,$xt2
+ punpckhdq $xd3,$xt3
+ movdqa $xd0,$xd1
+ punpcklqdq $xd2,$xd0 # "d0"
+ movdqa $xt2,$xd3
+ punpcklqdq $xt3,$xt2 # "d2"
+ punpckhqdq $xd2,$xd1 # "d1"
+ punpckhqdq $xt3,$xd3 # "d3"
+___
+ ($xd2,$xt2)=($xt2,$xd2);
+$code.=<<___;
+ cmp \$64*4,$len
+ jb .Ltail4x
+
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # size optimization
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+
+ movdqu $xt0,0x40($out)
+ movdqu 0x00($inp),$xt0
+ movdqu $xt1,0x50($out)
+ movdqu 0x10($inp),$xt1
+ movdqu $xt2,0x60($out)
+ movdqu 0x20($inp),$xt2
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # size optimization
+ movdqu 0x30($inp),$xt3
+ pxor 0x20(%rsp),$xt0
+ pxor $xb2,$xt1
+ pxor $xc2,$xt2
+ pxor $xd2,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # inp+=64*4
+ pxor 0x30(%rsp),$xt0
+ pxor $xb3,$xt1
+ pxor $xc3,$xt2
+ pxor $xd3,$xt3
+ movdqu $xt0,0x40($out)
+ movdqu $xt1,0x50($out)
+ movdqu $xt2,0x60($out)
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # out+=64*4
+
+ sub \$64*4,$len
+ jnz .Loop_outer4x
+
+ jmp .Ldone4x
+
+.Ltail4x:
+ cmp \$192,$len
+ jae .L192_or_more4x
+ cmp \$128,$len
+ jae .L128_or_more4x
+ cmp \$64,$len
+ jae .L64_or_more4x
+
+ #movdqa 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ xor %r10,%r10
+ #movdqa $xt0,0x00(%rsp)
+ movdqa $xb0,0x10(%rsp)
+ movdqa $xc0,0x20(%rsp)
+ movdqa $xd0,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L64_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaxN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+ movdqu $xt0,0x00($out)
+ movdqu $xt1,0x10($out)
+ movdqu $xt2,0x20($out)
+ movdqu $xt3,0x30($out)
+ je .Ldone4x
+
+ movdqa 0x10(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x40($inp),$inp # inp+=64*1
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb1,0x10(%rsp)
+ lea 0x40($out),$out # out+=64*1
+ movdqa $xc1,0x20(%rsp)
+ sub \$64,$len # len-=64*1
+ movdqa $xd1,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L128_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+ movdqu $xt0,0x40($out)
+ movdqu $xt1,0x50($out)
+ movdqu $xt2,0x60($out)
+ movdqu $xt3,0x70($out)
+ je .Ldone4x
+
+ movdqa 0x20(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x80($inp),$inp # inp+=64*2
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb2,0x10(%rsp)
+ lea 0x80($out),$out # out+=64*2
+ movdqa $xc2,0x20(%rsp)
+ sub \$128,$len # len-=64*2
+ movdqa $xd2,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L192_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # size optimization
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+
+ movdqu $xt0,0x40($out)
+ movdqu 0x00($inp),$xt0
+ movdqu $xt1,0x50($out)
+ movdqu 0x10($inp),$xt1
+ movdqu $xt2,0x60($out)
+ movdqu 0x20($inp),$xt2
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # size optimization
+ movdqu 0x30($inp),$xt3
+ pxor 0x20(%rsp),$xt0
+ pxor $xb2,$xt1
+ pxor $xc2,$xt2
+ pxor $xd2,$xt3
+ movdqu $xt0,0x00($out)
+ movdqu $xt1,0x10($out)
+ movdqu $xt2,0x20($out)
+ movdqu $xt3,0x30($out)
+ je .Ldone4x
+
+ movdqa 0x30(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x40($inp),$inp # inp+=64*3
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb3,0x10(%rsp)
+ lea 0x40($out),$out # out+=64*3
+ movdqa $xc3,0x20(%rsp)
+ sub \$192,$len # len-=64*3
+ movdqa $xd3,0x30(%rsp)
+
+.Loop_tail4x:
+ movzb ($inp,%r10),%eax
+ movzb (%rsp,%r10),%ecx
+ lea 1(%r10),%r10
+ xor %ecx,%eax
+ mov %al,-1($out,%r10)
+ dec $len
+ jnz .Loop_tail4x
+
+.Ldone4x:
+___
+$code.=<<___ if ($win64);
+ lea 0x140+0x30(%rsp),%r11
+ movaps -0x30(%r11),%xmm6
+ movaps -0x20(%r11),%xmm7
+ movaps -0x10(%r11),%xmm8
+ movaps 0x00(%r11),%xmm9
+ movaps 0x10(%r11),%xmm10
+ movaps 0x20(%r11),%xmm11
+ movaps 0x30(%r11),%xmm12
+ movaps 0x40(%r11),%xmm13
+ movaps 0x50(%r11),%xmm14
+ movaps 0x60(%r11),%xmm15
+___
+$code.=<<___;
+ add \$0x148+$xframe,%rsp
+ ret
+.size ChaCha20_4x,.-ChaCha20_4x
+___
+}
+
+########################################################################
+# AVX2 code path
+if ($avx>1) {
+my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3,
+ $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15));
+my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub AVX2_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ (
+ "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1
+ "&vpxor (@x[$d0],@x[$a0],@x[$d0])",
+ "&vpshufb (@x[$d0],@x[$d0],$t1)",
+ "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2
+ "&vpxor (@x[$d1],@x[$a1],@x[$d1])",
+ "&vpshufb (@x[$d1],@x[$d1],$t1)",
+
+ "&vpaddd ($xc,$xc,@x[$d0])",
+ "&vpxor (@x[$b0],$xc,@x[$b0])",
+ "&vpslld ($t0,@x[$b0],12)",
+ "&vpsrld (@x[$b0],@x[$b0],20)",
+ "&vpor (@x[$b0],$t0,@x[$b0])",
+ "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d1])",
+ "&vpxor (@x[$b1],$xc_,@x[$b1])",
+ "&vpslld ($t1,@x[$b1],12)",
+ "&vpsrld (@x[$b1],@x[$b1],20)",
+ "&vpor (@x[$b1],$t1,@x[$b1])",
+
+ "&vpaddd (@x[$a0],@x[$a0],@x[$b0])",
+ "&vpxor (@x[$d0],@x[$a0],@x[$d0])",
+ "&vpshufb (@x[$d0],@x[$d0],$t0)",
+ "&vpaddd (@x[$a1],@x[$a1],@x[$b1])",
+ "&vpxor (@x[$d1],@x[$a1],@x[$d1])",
+ "&vpshufb (@x[$d1],@x[$d1],$t0)",
+
+ "&vpaddd ($xc,$xc,@x[$d0])",
+ "&vpxor (@x[$b0],$xc,@x[$b0])",
+ "&vpslld ($t1,@x[$b0],7)",
+ "&vpsrld (@x[$b0],@x[$b0],25)",
+ "&vpor (@x[$b0],$t1,@x[$b0])",
+ "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d1])",
+ "&vpxor (@x[$b1],$xc_,@x[$b1])",
+ "&vpslld ($t0,@x[$b1],7)",
+ "&vpsrld (@x[$b1],@x[$b1],25)",
+ "&vpor (@x[$b1],$t0,@x[$b1])",
+
+ "&vmovdqa (\"`32*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's
+ "&vmovdqa (\"`32*($c1-8)`(%rsp)\",$xc_)",
+ "&vmovdqa ($xc,\"`32*($c2-8)`(%rsp)\")",
+ "&vmovdqa ($xc_,\"`32*($c3-8)`(%rsp)\")",
+
+ "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3
+ "&vpxor (@x[$d2],@x[$a2],@x[$d2])",
+ "&vpshufb (@x[$d2],@x[$d2],$t1)",
+ "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4
+ "&vpxor (@x[$d3],@x[$a3],@x[$d3])",
+ "&vpshufb (@x[$d3],@x[$d3],$t1)",
+
+ "&vpaddd ($xc,$xc,@x[$d2])",
+ "&vpxor (@x[$b2],$xc,@x[$b2])",
+ "&vpslld ($t0,@x[$b2],12)",
+ "&vpsrld (@x[$b2],@x[$b2],20)",
+ "&vpor (@x[$b2],$t0,@x[$b2])",
+ "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d3])",
+ "&vpxor (@x[$b3],$xc_,@x[$b3])",
+ "&vpslld ($t1,@x[$b3],12)",
+ "&vpsrld (@x[$b3],@x[$b3],20)",
+ "&vpor (@x[$b3],$t1,@x[$b3])",
+
+ "&vpaddd (@x[$a2],@x[$a2],@x[$b2])",
+ "&vpxor (@x[$d2],@x[$a2],@x[$d2])",
+ "&vpshufb (@x[$d2],@x[$d2],$t0)",
+ "&vpaddd (@x[$a3],@x[$a3],@x[$b3])",
+ "&vpxor (@x[$d3],@x[$a3],@x[$d3])",
+ "&vpshufb (@x[$d3],@x[$d3],$t0)",
+
+ "&vpaddd ($xc,$xc,@x[$d2])",
+ "&vpxor (@x[$b2],$xc,@x[$b2])",
+ "&vpslld ($t1,@x[$b2],7)",
+ "&vpsrld (@x[$b2],@x[$b2],25)",
+ "&vpor (@x[$b2],$t1,@x[$b2])",
+ "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d3])",
+ "&vpxor (@x[$b3],$xc_,@x[$b3])",
+ "&vpslld ($t0,@x[$b3],7)",
+ "&vpsrld (@x[$b3],@x[$b3],25)",
+ "&vpor (@x[$b3],$t0,@x[$b3])"
+ );
+}
+
+my $xframe = $win64 ? 0xb0 : 8;
+
+$code.=<<___;
+.type ChaCha20_8x,\@function,5
+.align 32
+ChaCha20_8x:
+.LChaCha20_8x:
+ mov %rsp,%r10
+ sub \$0x280+$xframe,%rsp
+ and \$-32,%rsp
+___
+$code.=<<___ if ($win64);
+ lea 0x290+0x30(%rsp),%r11
+ movaps %xmm6,-0x30(%r11)
+ movaps %xmm7,-0x20(%r11)
+ movaps %xmm8,-0x10(%r11)
+ movaps %xmm9,0x00(%r11)
+ movaps %xmm10,0x10(%r11)
+ movaps %xmm11,0x20(%r11)
+ movaps %xmm12,0x30(%r11)
+ movaps %xmm13,0x40(%r11)
+ movaps %xmm14,0x50(%r11)
+ movaps %xmm15,0x60(%r11)
+___
+$code.=<<___;
+ vzeroupper
+ mov %r10,0x280(%rsp)
+
+ ################ stack layout
+ # +0x00 SIMD equivalent of @x[8-12]
+ # ...
+ # +0x80 constant copy of key[0-2] smashed by lanes
+ # ...
+ # +0x200 SIMD counters (with nonce smashed by lanes)
+ # ...
+ # +0x280 saved %rsp
+
+ vbroadcasti128 .Lsigma(%rip),$xa3 # key[0]
+ vbroadcasti128 ($key),$xb3 # key[1]
+ vbroadcasti128 16($key),$xt3 # key[2]
+ vbroadcasti128 ($counter),$xd3 # key[3]
+ lea 0x100(%rsp),%rcx # size optimization
+ lea 0x200(%rsp),%rax # size optimization
+ lea .Lrot16(%rip),%r10
+ lea .Lrot24(%rip),%r11
+
+ vpshufd \$0x00,$xa3,$xa0 # smash key by lanes...
+ vpshufd \$0x55,$xa3,$xa1
+ vmovdqa $xa0,0x80-0x100(%rcx) # ... and offload
+ vpshufd \$0xaa,$xa3,$xa2
+ vmovdqa $xa1,0xa0-0x100(%rcx)
+ vpshufd \$0xff,$xa3,$xa3
+ vmovdqa $xa2,0xc0-0x100(%rcx)
+ vmovdqa $xa3,0xe0-0x100(%rcx)
+
+ vpshufd \$0x00,$xb3,$xb0
+ vpshufd \$0x55,$xb3,$xb1
+ vmovdqa $xb0,0x100-0x100(%rcx)
+ vpshufd \$0xaa,$xb3,$xb2
+ vmovdqa $xb1,0x120-0x100(%rcx)
+ vpshufd \$0xff,$xb3,$xb3
+ vmovdqa $xb2,0x140-0x100(%rcx)
+ vmovdqa $xb3,0x160-0x100(%rcx)
+
+ vpshufd \$0x00,$xt3,$xt0 # "xc0"
+ vpshufd \$0x55,$xt3,$xt1 # "xc1"
+ vmovdqa $xt0,0x180-0x200(%rax)
+ vpshufd \$0xaa,$xt3,$xt2 # "xc2"
+ vmovdqa $xt1,0x1a0-0x200(%rax)
+ vpshufd \$0xff,$xt3,$xt3 # "xc3"
+ vmovdqa $xt2,0x1c0-0x200(%rax)
+ vmovdqa $xt3,0x1e0-0x200(%rax)
+
+ vpshufd \$0x00,$xd3,$xd0
+ vpshufd \$0x55,$xd3,$xd1
+ vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet
+ vpshufd \$0xaa,$xd3,$xd2
+ vmovdqa $xd1,0x220-0x200(%rax)
+ vpshufd \$0xff,$xd3,$xd3
+ vmovdqa $xd2,0x240-0x200(%rax)
+ vmovdqa $xd3,0x260-0x200(%rax)
+
+ jmp .Loop_enter8x
+
+.align 32
+.Loop_outer8x:
+ vmovdqa 0x80-0x100(%rcx),$xa0 # re-load smashed key
+ vmovdqa 0xa0-0x100(%rcx),$xa1
+ vmovdqa 0xc0-0x100(%rcx),$xa2
+ vmovdqa 0xe0-0x100(%rcx),$xa3
+ vmovdqa 0x100-0x100(%rcx),$xb0
+ vmovdqa 0x120-0x100(%rcx),$xb1
+ vmovdqa 0x140-0x100(%rcx),$xb2
+ vmovdqa 0x160-0x100(%rcx),$xb3
+ vmovdqa 0x180-0x200(%rax),$xt0 # "xc0"
+ vmovdqa 0x1a0-0x200(%rax),$xt1 # "xc1"
+ vmovdqa 0x1c0-0x200(%rax),$xt2 # "xc2"
+ vmovdqa 0x1e0-0x200(%rax),$xt3 # "xc3"
+ vmovdqa 0x200-0x200(%rax),$xd0
+ vmovdqa 0x220-0x200(%rax),$xd1
+ vmovdqa 0x240-0x200(%rax),$xd2
+ vmovdqa 0x260-0x200(%rax),$xd3
+ vpaddd .Leight(%rip),$xd0,$xd0 # next SIMD counters
+
+.Loop_enter8x:
+ vmovdqa $xt2,0x40(%rsp) # SIMD equivalent of "@x[10]"
+ vmovdqa $xt3,0x60(%rsp) # SIMD equivalent of "@x[11]"
+ vbroadcasti128 (%r10),$xt3
+ vmovdqa $xd0,0x200-0x200(%rax) # save SIMD counters
+ mov \$10,%eax
+ jmp .Loop8x
+
+.align 32
+.Loop8x:
+___
+ foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; }
+ foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ dec %eax
+ jnz .Loop8x
+
+ lea 0x200(%rsp),%rax # size optimization
+ vpaddd 0x80-0x100(%rcx),$xa0,$xa0 # accumulate key
+ vpaddd 0xa0-0x100(%rcx),$xa1,$xa1
+ vpaddd 0xc0-0x100(%rcx),$xa2,$xa2
+ vpaddd 0xe0-0x100(%rcx),$xa3,$xa3
+
+ vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data
+ vpunpckldq $xa3,$xa2,$xt3
+ vpunpckhdq $xa1,$xa0,$xa0
+ vpunpckhdq $xa3,$xa2,$xa2
+ vpunpcklqdq $xt3,$xt2,$xa1 # "a0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "a1"
+ vpunpcklqdq $xa2,$xa0,$xa3 # "a2"
+ vpunpckhqdq $xa2,$xa0,$xa0 # "a3"
+___
+ ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2);
+$code.=<<___;
+ vpaddd 0x100-0x100(%rcx),$xb0,$xb0
+ vpaddd 0x120-0x100(%rcx),$xb1,$xb1
+ vpaddd 0x140-0x100(%rcx),$xb2,$xb2
+ vpaddd 0x160-0x100(%rcx),$xb3,$xb3
+
+ vpunpckldq $xb1,$xb0,$xt2
+ vpunpckldq $xb3,$xb2,$xt3
+ vpunpckhdq $xb1,$xb0,$xb0
+ vpunpckhdq $xb3,$xb2,$xb2
+ vpunpcklqdq $xt3,$xt2,$xb1 # "b0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "b1"
+ vpunpcklqdq $xb2,$xb0,$xb3 # "b2"
+ vpunpckhqdq $xb2,$xb0,$xb0 # "b3"
+___
+ ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2);
+$code.=<<___;
+ vperm2i128 \$0x20,$xb0,$xa0,$xt3 # "de-interlace" further
+ vperm2i128 \$0x31,$xb0,$xa0,$xb0
+ vperm2i128 \$0x20,$xb1,$xa1,$xa0
+ vperm2i128 \$0x31,$xb1,$xa1,$xb1
+ vperm2i128 \$0x20,$xb2,$xa2,$xa1
+ vperm2i128 \$0x31,$xb2,$xa2,$xb2
+ vperm2i128 \$0x20,$xb3,$xa3,$xa2
+ vperm2i128 \$0x31,$xb3,$xa3,$xb3
+___
+ ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3);
+ my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+ vmovdqa $xa0,0x00(%rsp) # offload $xaN
+ vmovdqa $xa1,0x20(%rsp)
+ vmovdqa 0x40(%rsp),$xc2 # $xa0
+ vmovdqa 0x60(%rsp),$xc3 # $xa1
+
+ vpaddd 0x180-0x200(%rax),$xc0,$xc0
+ vpaddd 0x1a0-0x200(%rax),$xc1,$xc1
+ vpaddd 0x1c0-0x200(%rax),$xc2,$xc2
+ vpaddd 0x1e0-0x200(%rax),$xc3,$xc3
+
+ vpunpckldq $xc1,$xc0,$xt2
+ vpunpckldq $xc3,$xc2,$xt3
+ vpunpckhdq $xc1,$xc0,$xc0
+ vpunpckhdq $xc3,$xc2,$xc2
+ vpunpcklqdq $xt3,$xt2,$xc1 # "c0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "c1"
+ vpunpcklqdq $xc2,$xc0,$xc3 # "c2"
+ vpunpckhqdq $xc2,$xc0,$xc0 # "c3"
+___
+ ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2);
+$code.=<<___;
+ vpaddd 0x200-0x200(%rax),$xd0,$xd0
+ vpaddd 0x220-0x200(%rax),$xd1,$xd1
+ vpaddd 0x240-0x200(%rax),$xd2,$xd2
+ vpaddd 0x260-0x200(%rax),$xd3,$xd3
+
+ vpunpckldq $xd1,$xd0,$xt2
+ vpunpckldq $xd3,$xd2,$xt3
+ vpunpckhdq $xd1,$xd0,$xd0
+ vpunpckhdq $xd3,$xd2,$xd2
+ vpunpcklqdq $xt3,$xt2,$xd1 # "d0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "d1"
+ vpunpcklqdq $xd2,$xd0,$xd3 # "d2"
+ vpunpckhqdq $xd2,$xd0,$xd0 # "d3"
+___
+ ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2);
+$code.=<<___;
+ vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further
+ vperm2i128 \$0x31,$xd0,$xc0,$xd0
+ vperm2i128 \$0x20,$xd1,$xc1,$xc0
+ vperm2i128 \$0x31,$xd1,$xc1,$xd1
+ vperm2i128 \$0x20,$xd2,$xc2,$xc1
+ vperm2i128 \$0x31,$xd2,$xc2,$xd2
+ vperm2i128 \$0x20,$xd3,$xc3,$xc2
+ vperm2i128 \$0x31,$xd3,$xc3,$xd3
+___
+ ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3);
+ ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)=
+ ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3);
+ ($xa0,$xa1)=($xt2,$xt3);
+$code.=<<___;
+ vmovdqa 0x00(%rsp),$xa0 # $xaN was offloaded, remember?
+ vmovdqa 0x20(%rsp),$xa1
+
+ cmp \$64*8,$len
+ jb .Ltail8x
+
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa1,$xa1
+ vpxor 0x20($inp),$xb1,$xb1
+ vpxor 0x40($inp),$xc1,$xc1
+ vpxor 0x60($inp),$xd1,$xd1
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa1,0x00($out)
+ vmovdqu $xb1,0x20($out)
+ vmovdqu $xc1,0x40($out)
+ vmovdqu $xd1,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa2,$xa2
+ vpxor 0x20($inp),$xb2,$xb2
+ vpxor 0x40($inp),$xc2,$xc2
+ vpxor 0x60($inp),$xd2,$xd2
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa2,0x00($out)
+ vmovdqu $xb2,0x20($out)
+ vmovdqu $xc2,0x40($out)
+ vmovdqu $xd2,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa3,$xa3
+ vpxor 0x20($inp),$xb3,$xb3
+ vpxor 0x40($inp),$xc3,$xc3
+ vpxor 0x60($inp),$xd3,$xd3
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa3,0x00($out)
+ vmovdqu $xb3,0x20($out)
+ vmovdqu $xc3,0x40($out)
+ vmovdqu $xd3,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ sub \$64*8,$len
+ jnz .Loop_outer8x
+
+ jmp .Ldone8x
+
+.Ltail8x:
+ cmp \$448,$len
+ jae .L448_or_more8x
+ cmp \$384,$len
+ jae .L384_or_more8x
+ cmp \$320,$len
+ jae .L320_or_more8x
+ cmp \$256,$len
+ jae .L256_or_more8x
+ cmp \$192,$len
+ jae .L192_or_more8x
+ cmp \$128,$len
+ jae .L128_or_more8x
+ cmp \$64,$len
+ jae .L64_or_more8x
+
+ xor %r10,%r10
+ vmovdqa $xa0,0x00(%rsp)
+ vmovdqa $xb0,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L64_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ je .Ldone8x
+
+ lea 0x40($inp),$inp # inp+=64*1
+ xor %r10,%r10
+ vmovdqa $xc0,0x00(%rsp)
+ lea 0x40($out),$out # out+=64*1
+ sub \$64,$len # len-=64*1
+ vmovdqa $xd0,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L128_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ je .Ldone8x
+
+ lea 0x80($inp),$inp # inp+=64*2
+ xor %r10,%r10
+ vmovdqa $xa1,0x00(%rsp)
+ lea 0x80($out),$out # out+=64*2
+ sub \$128,$len # len-=64*2
+ vmovdqa $xb1,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L192_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ je .Ldone8x
+
+ lea 0xc0($inp),$inp # inp+=64*3
+ xor %r10,%r10
+ vmovdqa $xc1,0x00(%rsp)
+ lea 0xc0($out),$out # out+=64*3
+ sub \$192,$len # len-=64*3
+ vmovdqa $xd1,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L256_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ je .Ldone8x
+
+ lea 0x100($inp),$inp # inp+=64*4
+ xor %r10,%r10
+ vmovdqa $xa2,0x00(%rsp)
+ lea 0x100($out),$out # out+=64*4
+ sub \$256,$len # len-=64*4
+ vmovdqa $xb2,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L320_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ je .Ldone8x
+
+ lea 0x140($inp),$inp # inp+=64*5
+ xor %r10,%r10
+ vmovdqa $xc2,0x00(%rsp)
+ lea 0x140($out),$out # out+=64*5
+ sub \$320,$len # len-=64*5
+ vmovdqa $xd2,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L384_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vpxor 0x140($inp),$xc2,$xc2
+ vpxor 0x160($inp),$xd2,$xd2
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ vmovdqu $xc2,0x140($out)
+ vmovdqu $xd2,0x160($out)
+ je .Ldone8x
+
+ lea 0x180($inp),$inp # inp+=64*6
+ xor %r10,%r10
+ vmovdqa $xa3,0x00(%rsp)
+ lea 0x180($out),$out # out+=64*6
+ sub \$384,$len # len-=64*6
+ vmovdqa $xb3,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L448_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vpxor 0x140($inp),$xc2,$xc2
+ vpxor 0x160($inp),$xd2,$xd2
+ vpxor 0x180($inp),$xa3,$xa3
+ vpxor 0x1a0($inp),$xb3,$xb3
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ vmovdqu $xc2,0x140($out)
+ vmovdqu $xd2,0x160($out)
+ vmovdqu $xa3,0x180($out)
+ vmovdqu $xb3,0x1a0($out)
+ je .Ldone8x
+
+ lea 0x1c0($inp),$inp # inp+=64*7
+ xor %r10,%r10
+ vmovdqa $xc3,0x00(%rsp)
+ lea 0x1c0($out),$out # out+=64*7
+ sub \$448,$len # len-=64*7
+ vmovdqa $xd3,0x20(%rsp)
+
+.Loop_tail8x:
+ movzb ($inp,%r10),%eax
+ movzb (%rsp,%r10),%ecx
+ lea 1(%r10),%r10
+ xor %ecx,%eax
+ mov %al,-1($out,%r10)
+ dec $len
+ jnz .Loop_tail8x
+
+.Ldone8x:
+ vzeroall
+___
+$code.=<<___ if ($win64);
+ lea 0x290+0x30(%rsp),%r11
+ movaps -0x30(%r11),%xmm6
+ movaps -0x20(%r11),%xmm7
+ movaps -0x10(%r11),%xmm8
+ movaps 0x00(%r11),%xmm9
+ movaps 0x10(%r11),%xmm10
+ movaps 0x20(%r11),%xmm11
+ movaps 0x30(%r11),%xmm12
+ movaps 0x40(%r11),%xmm13
+ movaps 0x50(%r11),%xmm14
+ movaps 0x60(%r11),%xmm15
+___
+$code.=<<___;
+ mov 0x280(%rsp),%rsp
+ ret
+.size ChaCha20_8x,.-ChaCha20_8x
+___
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/%x#%y/%x/go;
+
+ print $_,"\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/chacha/chacha_generic.c b/src/crypto/chacha/chacha.c
index f262033c..afe1b2ad 100644
--- a/src/crypto/chacha/chacha_generic.c
+++ b/src/crypto/chacha/chacha.c
@@ -21,7 +21,49 @@
#include <openssl/cpu.h>
-#if defined(OPENSSL_WINDOWS) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || !defined(__SSE2__)
+#define U8TO32_LITTLE(p) \
+ (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
+ ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+
+/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */
+void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint32_t key[8], const uint32_t counter[4]);
+
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[12],
+ uint32_t counter) {
+ uint32_t counter_nonce[4];
+ counter_nonce[0] = counter;
+ counter_nonce[1] = U8TO32_LITTLE(nonce + 0);
+ counter_nonce[2] = U8TO32_LITTLE(nonce + 4);
+ counter_nonce[3] = U8TO32_LITTLE(nonce + 8);
+
+ const uint32_t *key_ptr = (const uint32_t *)key;
+#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
+ /* The assembly expects the key to be four-byte aligned. */
+ uint32_t key_u32[8];
+ if ((((uintptr_t)key) & 3) != 0) {
+ key_u32[0] = U8TO32_LITTLE(key + 0);
+ key_u32[1] = U8TO32_LITTLE(key + 4);
+ key_u32[2] = U8TO32_LITTLE(key + 8);
+ key_u32[3] = U8TO32_LITTLE(key + 12);
+ key_u32[4] = U8TO32_LITTLE(key + 16);
+ key_u32[5] = U8TO32_LITTLE(key + 20);
+ key_u32[6] = U8TO32_LITTLE(key + 24);
+ key_u32[7] = U8TO32_LITTLE(key + 28);
+
+ key_ptr = key_u32;
+ }
+#endif
+
+ ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
+}
+
+#else
/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
@@ -40,10 +82,6 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
(p)[3] = (v >> 24) & 0xff; \
}
-#define U8TO32_LITTLE(p) \
- (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
- ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
-
/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
#define QUARTERROUND(a,b,c,d) \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
@@ -51,13 +89,6 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-/* Defined in chacha_vec.c */
-void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
- const uint8_t key[32], const uint8_t nonce[12],
- uint32_t counter);
-#endif
-
/* chacha_core performs 20 rounds of ChaCha on the input words in
* |input| and writes the 64 output bytes to |output|. */
static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
@@ -91,13 +122,6 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
uint8_t buf[64];
size_t todo, i;
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_capable()) {
- CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
- return;
- }
-#endif
-
input[0] = U8TO32_LITTLE(sigma + 0);
input[1] = U8TO32_LITTLE(sigma + 4);
input[2] = U8TO32_LITTLE(sigma + 8);
@@ -137,4 +161,4 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
}
}
-#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 && !OPENSSL_X86 || !__SSE2__ */
+#endif
diff --git a/src/crypto/chacha/chacha_test.cc b/src/crypto/chacha/chacha_test.cc
new file mode 100644
index 00000000..f364f982
--- /dev/null
+++ b/src/crypto/chacha/chacha_test.cc
@@ -0,0 +1,257 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+
+#include <openssl/crypto.h>
+#include <openssl/chacha.h>
+
+
+static const uint8_t kKey[32] = {
+ 0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b,
+ 0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64,
+ 0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6,
+};
+
+static const uint8_t kNonce[12] = {
+ 0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53,
+};
+
+static uint32_t kCounter = 42;
+
+static const uint8_t kInput[] = {
+ 0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c,
+ 0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88,
+ 0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e,
+ 0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3,
+ 0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd,
+ 0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48,
+ 0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7,
+ 0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b,
+ 0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f,
+ 0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e,
+ 0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62,
+ 0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8,
+ 0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3,
+ 0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a,
+ 0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20,
+ 0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81,
+ 0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9,
+ 0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92,
+ 0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39,
+ 0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f,
+ 0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58,
+ 0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82,
+ 0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54,
+ 0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c,
+ 0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c,
+ 0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae,
+ 0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef,
+ 0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31,
+ 0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38,
+ 0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e,
+ 0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef,
+ 0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb,
+ 0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61,
+ 0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff,
+ 0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f,
+ 0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25,
+ 0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3,
+ 0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25,
+ 0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52,
+ 0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea,
+ 0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69,
+ 0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3,
+ 0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed,
+ 0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c,
+ 0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa,
+ 0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e,
+ 0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd,
+ 0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05,
+ 0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50,
+ 0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28,
+ 0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f,
+ 0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d,
+ 0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c,
+ 0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77,
+ 0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04,
+ 0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa,
+ 0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69,
+ 0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff,
+ 0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a,
+ 0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2,
+ 0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01,
+ 0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b,
+ 0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c,
+ 0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66,
+ 0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47,
+ 0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26,
+ 0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60,
+ 0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa,
+ 0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85,
+ 0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e,
+ 0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef,
+ 0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a,
+ 0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02,
+ 0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73,
+ 0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73,
+ 0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0,
+ 0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06,
+ 0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae,
+ 0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b,
+ 0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec,
+ 0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4,
+ 0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77,
+ 0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4,
+ 0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d,
+ 0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a,
+ 0xac, 0x09, 0x01, 0xca,
+};
+static const uint8_t kOutput[] = {
+ 0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5,
+ 0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8,
+ 0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd,
+ 0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68,
+ 0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa,
+ 0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66,
+ 0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46,
+ 0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a,
+ 0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc,
+ 0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1,
+ 0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf,
+ 0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb,
+ 0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3,
+ 0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd,
+ 0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b,
+ 0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5,
+ 0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88,
+ 0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2,
+ 0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96,
+ 0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe,
+ 0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18,
+ 0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c,
+ 0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0,
+ 0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00,
+ 0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74,
+ 0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60,
+ 0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8,
+ 0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81,
+ 0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f,
+ 0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f,
+ 0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b,
+ 0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8,
+ 0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe,
+ 0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31,
+ 0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09,
+ 0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6,
+ 0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb,
+ 0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18,
+ 0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a,
+ 0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72,
+ 0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22,
+ 0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15,
+ 0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a,
+ 0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33,
+ 0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b,
+ 0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34,
+ 0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd,
+ 0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15,
+ 0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58,
+ 0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7,
+ 0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea,
+ 0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99,
+ 0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9,
+ 0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60,
+ 0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a,
+ 0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e,
+ 0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8,
+ 0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6,
+ 0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99,
+ 0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66,
+ 0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77,
+ 0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0,
+ 0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c,
+ 0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9,
+ 0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3,
+ 0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43,
+ 0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd,
+ 0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90,
+ 0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c,
+ 0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94,
+ 0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7,
+ 0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27,
+ 0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61,
+ 0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0,
+ 0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50,
+ 0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67,
+ 0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30,
+ 0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54,
+ 0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88,
+ 0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0,
+ 0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49,
+ 0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4,
+ 0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95,
+ 0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc,
+ 0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50,
+ 0x8f, 0x40, 0xcf, 0x4a,
+};
+
+static_assert(sizeof(kInput) == sizeof(kOutput),
+ "Input and output lengths don't match.");
+
+static bool TestChaCha20(size_t len) {
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
+ CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
+ if (memcmp(buf.get(), kOutput, len) != 0) {
+ fprintf(stderr, "Mismatch at length %u.\n", static_cast<unsigned>(len));
+ return false;
+ }
+
+ // Test in-place at various offsets.
+ static const size_t kOffsets[] = {
+ 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
+ 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
+ };
+ for (size_t offset : kOffsets) {
+ buf.reset(new uint8_t[len + offset]);
+ memcpy(buf.get() + offset, kInput, len);
+ CRYPTO_chacha_20(buf.get(), buf.get() + offset, len, kKey, kNonce,
+ kCounter);
+ if (memcmp(buf.get(), kOutput, len) != 0) {
+ fprintf(stderr, "Mismatch at length %u with in-place offset %u.\n",
+ static_cast<unsigned>(len), static_cast<unsigned>(offset));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ // Run the test with the test vector at all lengths.
+ for (size_t len = 0; len <= sizeof(kInput); len++) {
+ if (!TestChaCha20(len)) {
+ return 1;
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/chacha/chacha_vec.c b/src/crypto/chacha/chacha_vec.c
deleted file mode 100644
index addbaa3d..00000000
--- a/src/crypto/chacha/chacha_vec.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* ====================================================================
- *
- * When updating this file, also update chacha_vec_arm.S
- *
- * ==================================================================== */
-
-
-/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
- * marked as public domain. It was been altered to allow for non-aligned inputs
- * and to allow the block counter to be passed in specifically. */
-
-#include <openssl/chacha.h>
-
-#if defined(ASM_GEN) || \
- !defined(OPENSSL_WINDOWS) && \
- (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
-
-#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
-
-/* Architecture-neutral way to specify 16-byte vector of ints */
-typedef unsigned vec __attribute__((vector_size(16)));
-
-/* This implementation is designed for Neon, SSE and AltiVec machines. The
- * following specify how to do certain vector operations efficiently on
- * each architecture, using intrinsics.
- * This implementation supports parallel processing of multiple blocks,
- * including potentially using general-purpose registers. */
-#if __ARM_NEON__
-#include <string.h>
-#include <arm_neon.h>
-#define GPR_TOO 1
-#define VBPI 2
-#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0)
-#define LOAD_ALIGNED(m) (vec)(*((vec *)(m)))
-#define LOAD(m) ({ \
- memcpy(alignment_buffer, m, 16); \
- LOAD_ALIGNED(alignment_buffer); \
- })
-#define STORE(m, r) ({ \
- (*((vec *)(alignment_buffer))) = (r); \
- memcpy(m, alignment_buffer, 16); \
- })
-#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1)
-#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2)
-#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3)
-#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x)
-#if __clang__
-#define ROTW7(x) (x << ((vec) {7, 7, 7, 7})) ^ (x >> ((vec) {25, 25, 25, 25}))
-#define ROTW8(x) (x << ((vec) {8, 8, 8, 8})) ^ (x >> ((vec) {24, 24, 24, 24}))
-#define ROTW12(x) \
- (x << ((vec) {12, 12, 12, 12})) ^ (x >> ((vec) {20, 20, 20, 20}))
-#else
-#define ROTW7(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25)
-#define ROTW8(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24)
-#define ROTW12(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20)
-#endif
-#elif __SSE2__
-#include <emmintrin.h>
-#define GPR_TOO 0
-#if __clang__
-#define VBPI 4
-#else
-#define VBPI 3
-#endif
-#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
-#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m))
-#define LOAD_ALIGNED(m) (vec) _mm_load_si128((__m128i *)(m))
-#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
-#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
-#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
-#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3))
-#define ROTW7(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25))
-#define ROTW12(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20))
-#if __SSSE3__
-#include <tmmintrin.h>
-#define ROTW8(x) \
- (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, \
- 11, 6, 5, 4, 7, 2, 1, 0, 3))
-#define ROTW16(x) \
- (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, \
- 10, 5, 4, 7, 6, 1, 0, 3, 2))
-#else
-#define ROTW8(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24))
-#define ROTW16(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16))
-#endif
-#else
-#error-- Implementation supports only machines with neon or SSE2
-#endif
-
-#ifndef REVV_BE
-#define REVV_BE(x) (x)
-#endif
-
-#ifndef REVW_BE
-#define REVW_BE(x) (x)
-#endif
-
-#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */
-
-#define DQROUND_VECTORS(a,b,c,d) \
- a += b; d ^= a; d = ROTW16(d); \
- c += d; b ^= c; b = ROTW12(b); \
- a += b; d ^= a; d = ROTW8(d); \
- c += d; b ^= c; b = ROTW7(b); \
- b = ROTV1(b); c = ROTV2(c); d = ROTV3(d); \
- a += b; d ^= a; d = ROTW16(d); \
- c += d; b ^= c; b = ROTW12(b); \
- a += b; d ^= a; d = ROTW8(d); \
- c += d; b ^= c; b = ROTW7(b); \
- b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
-
-#define QROUND_WORDS(a,b,c,d) \
- a = a+b; d ^= a; d = d<<16 | d>>16; \
- c = c+d; b ^= c; b = b<<12 | b>>20; \
- a = a+b; d ^= a; d = d<< 8 | d>>24; \
- c = c+d; b ^= c; b = b<< 7 | b>>25;
-
-#define WRITE_XOR(in, op, d, v0, v1, v2, v3) \
- STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \
- STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \
- STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \
- STORE(op + d +12, LOAD(in + d +12) ^ REVV_BE(v3));
-
-#if __ARM_NEON__
-/* For ARM, we can't depend on NEON support, so this function is compiled with
- * a different name, along with the generic code, and can be enabled at
- * run-time. */
-void CRYPTO_chacha_20_neon(
-#else
-void CRYPTO_chacha_20(
-#endif
- uint8_t *out,
- const uint8_t *in,
- size_t inlen,
- const uint8_t key[32],
- const uint8_t nonce[12],
- uint32_t counter)
- {
- unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
-#if defined(__ARM_NEON__)
- uint32_t np[3];
- uint8_t alignment_buffer[16] __attribute__((aligned(16)));
-#endif
- vec s0, s1, s2, s3;
- __attribute__ ((aligned (16))) unsigned chacha_const[] =
- {0x61707865,0x3320646E,0x79622D32,0x6B206574};
- kp = (unsigned *)key;
-#if defined(__ARM_NEON__)
- memcpy(np, nonce, 12);
-#endif
- s0 = LOAD_ALIGNED(chacha_const);
- s1 = LOAD(&((vec*)kp)[0]);
- s2 = LOAD(&((vec*)kp)[1]);
- s3 = (vec){
- counter,
- ((uint32_t*)nonce)[0],
- ((uint32_t*)nonce)[1],
- ((uint32_t*)nonce)[2]
- };
-
- for (iters = 0; iters < inlen/(BPI*64); iters++)
- {
-#if GPR_TOO
- register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
- x9, x10, x11, x12, x13, x14, x15;
-#endif
-#if VBPI > 2
- vec v8,v9,v10,v11;
-#endif
-#if VBPI > 3
- vec v12,v13,v14,v15;
-#endif
-
- vec v0,v1,v2,v3,v4,v5,v6,v7;
- v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
- v7 = v3 + ONE;
-#if VBPI > 2
- v8 = v4; v9 = v5; v10 = v6;
- v11 = v7 + ONE;
-#endif
-#if VBPI > 3
- v12 = v8; v13 = v9; v14 = v10;
- v15 = v11 + ONE;
-#endif
-#if GPR_TOO
- x0 = chacha_const[0]; x1 = chacha_const[1];
- x2 = chacha_const[2]; x3 = chacha_const[3];
- x4 = kp[0]; x5 = kp[1]; x6 = kp[2]; x7 = kp[3];
- x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
- x12 = counter+BPI*iters+(BPI-1); x13 = np[0];
- x14 = np[1]; x15 = np[2];
-#endif
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3)
- DQROUND_VECTORS(v4,v5,v6,v7)
-#if VBPI > 2
- DQROUND_VECTORS(v8,v9,v10,v11)
-#endif
-#if VBPI > 3
- DQROUND_VECTORS(v12,v13,v14,v15)
-#endif
-#if GPR_TOO
- QROUND_WORDS( x0, x4, x8,x12)
- QROUND_WORDS( x1, x5, x9,x13)
- QROUND_WORDS( x2, x6,x10,x14)
- QROUND_WORDS( x3, x7,x11,x15)
- QROUND_WORDS( x0, x5,x10,x15)
- QROUND_WORDS( x1, x6,x11,x12)
- QROUND_WORDS( x2, x7, x8,x13)
- QROUND_WORDS( x3, x4, x9,x14)
-#endif
- }
-
- WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
- s3 += ONE;
- WRITE_XOR(ip, op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
- s3 += ONE;
-#if VBPI > 2
- WRITE_XOR(ip, op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
- s3 += ONE;
-#endif
-#if VBPI > 3
- WRITE_XOR(ip, op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
- s3 += ONE;
-#endif
- ip += VBPI*16;
- op += VBPI*16;
-#if GPR_TOO
- op[0] = REVW_BE(REVW_BE(ip[0]) ^ (x0 + chacha_const[0]));
- op[1] = REVW_BE(REVW_BE(ip[1]) ^ (x1 + chacha_const[1]));
- op[2] = REVW_BE(REVW_BE(ip[2]) ^ (x2 + chacha_const[2]));
- op[3] = REVW_BE(REVW_BE(ip[3]) ^ (x3 + chacha_const[3]));
- op[4] = REVW_BE(REVW_BE(ip[4]) ^ (x4 + kp[0]));
- op[5] = REVW_BE(REVW_BE(ip[5]) ^ (x5 + kp[1]));
- op[6] = REVW_BE(REVW_BE(ip[6]) ^ (x6 + kp[2]));
- op[7] = REVW_BE(REVW_BE(ip[7]) ^ (x7 + kp[3]));
- op[8] = REVW_BE(REVW_BE(ip[8]) ^ (x8 + kp[4]));
- op[9] = REVW_BE(REVW_BE(ip[9]) ^ (x9 + kp[5]));
- op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6]));
- op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7]));
- op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter+BPI*iters+(BPI-1)));
- op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13 + np[0]));
- op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[1]));
- op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[2]));
- s3 += ONE;
- ip += 16;
- op += 16;
-#endif
- }
-
- for (iters = inlen%(BPI*64)/64; iters != 0; iters--)
- {
- vec v0 = s0, v1 = s1, v2 = s2, v3 = s3;
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3);
- }
- WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
- s3 += ONE;
- ip += 16;
- op += 16;
- }
-
- inlen = inlen % 64;
- if (inlen)
- {
- __attribute__ ((aligned (16))) vec buf[4];
- vec v0,v1,v2,v3;
- v0 = s0; v1 = s1; v2 = s2; v3 = s3;
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3);
- }
-
- if (inlen >= 16)
- {
- STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0));
- if (inlen >= 32)
- {
- STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1));
- if (inlen >= 48)
- {
- STORE(op + 8, LOAD(ip + 8) ^
- REVV_BE(v2 + s2));
- buf[3] = REVV_BE(v3 + s3);
- }
- else
- buf[2] = REVV_BE(v2 + s2);
- }
- else
- buf[1] = REVV_BE(v1 + s1);
- }
- else
- buf[0] = REVV_BE(v0 + s0);
-
- for (i=inlen & ~15; i<inlen; i++)
- ((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
- }
- }
-
-#endif /* ASM_GEN || !OPENSSL_WINDOWS && (OPENSSL_X86_64 || OPENSSL_X86) && SSE2 */
diff --git a/src/crypto/chacha/chacha_vec_arm.S b/src/crypto/chacha/chacha_vec_arm.S
deleted file mode 100644
index f18c867e..00000000
--- a/src/crypto/chacha/chacha_vec_arm.S
+++ /dev/null
@@ -1,1447 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-# /opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -O3 -mcpu=cortex-a8 -mfpu=neon -fpic -DASM_GEN -I ../../include -S chacha_vec.c -o -
-
-#if !defined(OPENSSL_NO_ASM)
-#if defined(__arm__)
-
- .syntax unified
- .cpu cortex-a8
- .eabi_attribute 27, 3
-
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
- .eabi_attribute 28, 1
-#else
- .eabi_attribute 28, 0
-#endif
-
- .fpu neon
- .eabi_attribute 20, 1
- .eabi_attribute 21, 1
- .eabi_attribute 23, 3
- .eabi_attribute 24, 1
- .eabi_attribute 25, 1
- .eabi_attribute 26, 2
- .eabi_attribute 30, 2
- .eabi_attribute 34, 1
- .eabi_attribute 18, 4
- .thumb
- .file "chacha_vec.c"
- .text
- .align 2
- .global CRYPTO_chacha_20_neon
- .hidden CRYPTO_chacha_20_neon
- .thumb
- .thumb_func
- .type CRYPTO_chacha_20_neon, %function
-CRYPTO_chacha_20_neon:
- @ args = 8, pretend = 0, frame = 160
- @ frame_needed = 1, uses_anonymous_args = 0
- push {r4, r5, r6, r7, r8, r9, r10, fp, lr}
- mov r9, r3
- vpush.64 {d8, d9, d10, d11, d12, d13, d14, d15}
- mov r10, r2
- ldr r4, .L91+16
- mov fp, r1
- mov r8, r9
-.LPIC16:
- add r4, pc
- sub sp, sp, #164
- add r7, sp, #0
- sub sp, sp, #112
- add lr, r7, #148
- str r0, [r7, #80]
- str r1, [r7, #12]
- str r2, [r7, #8]
- ldmia r4, {r0, r1, r2, r3}
- add r4, sp, #15
- bic r4, r4, #15
- ldr r6, [r7, #264]
- str r4, [r7, #88]
- mov r5, r4
- adds r4, r4, #64
- add ip, r5, #80
- str r9, [r7, #56]
- stmia r4, {r0, r1, r2, r3}
- movw r4, #43691
- ldr r0, [r6] @ unaligned
- movt r4, 43690
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- str ip, [r7, #84]
- stmia lr!, {r0, r1, r2}
- mov lr, ip
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r0, [r9] @ unaligned
- vldr d24, [r5, #64]
- vldr d25, [r5, #72]
- umull r4, r5, r10, r4
- stmia ip!, {r0, r1, r2, r3}
- ldr r0, [r8, #16]! @ unaligned
- ldr r2, [r7, #88]
- ldr r4, [r7, #268]
- ldr r1, [r8, #4] @ unaligned
- vldr d26, [r2, #80]
- vldr d27, [r2, #88]
- ldr r3, [r8, #12] @ unaligned
- ldr r2, [r8, #8] @ unaligned
- stmia lr!, {r0, r1, r2, r3}
- ldr r3, [r6]
- ldr r1, [r6, #4]
- ldr r6, [r6, #8]
- str r3, [r7, #68]
- str r3, [r7, #132]
- lsrs r3, r5, #7
- str r6, [r7, #140]
- str r6, [r7, #60]
- ldr r6, [r7, #88]
- str r4, [r7, #128]
- str r1, [r7, #136]
- str r1, [r7, #64]
- vldr d28, [r6, #80]
- vldr d29, [r6, #88]
- vldr d22, [r7, #128]
- vldr d23, [r7, #136]
- beq .L26
- mov r5, r6
- lsls r2, r3, #8
- sub r3, r2, r3, lsl #6
- ldr r2, [r5, #68]
- ldr r6, [r6, #64]
- vldr d0, .L91
- vldr d1, .L91+8
- str r2, [r7, #48]
- ldr r2, [r5, #72]
- str r3, [r7, #4]
- str r6, [r7, #52]
- str r2, [r7, #44]
- adds r2, r4, #2
- str r2, [r7, #72]
- ldr r2, [r5, #76]
- str fp, [r7, #76]
- str r2, [r7, #40]
- ldr r2, [r7, #80]
- adds r3, r2, r3
- str r3, [r7, #16]
-.L4:
- ldr r5, [r7, #56]
- add r8, r7, #40
- ldr r4, [r7, #68]
- vadd.i32 q3, q11, q0
- ldmia r8, {r8, r9, r10, fp}
- mov r1, r5
- ldr r2, [r5, #4]
- vmov q8, q14 @ v4si
- ldr r3, [r5]
- vmov q1, q13 @ v4si
- ldr r6, [r1, #28]
- vmov q9, q12 @ v4si
- mov r0, r2
- ldr r2, [r5, #8]
- str r4, [r7, #112]
- movs r1, #10
- ldr r4, [r7, #72]
- vmov q2, q11 @ v4si
- ldr lr, [r5, #20]
- vmov q15, q14 @ v4si
- str r3, [r7, #108]
- vmov q5, q13 @ v4si
- str r2, [r7, #116]
- vmov q10, q12 @ v4si
- ldr r2, [r5, #12]
- ldr ip, [r5, #16]
- ldr r3, [r7, #64]
- ldr r5, [r5, #24]
- str r6, [r7, #120]
- str r1, [r7, #92]
- ldr r6, [r7, #60]
- str r4, [r7, #100]
- ldr r1, [r7, #116]
- ldr r4, [r7, #108]
- str r8, [r7, #96]
- mov r8, r10
- str lr, [r7, #104]
- mov r10, r9
- mov lr, r3
- mov r9, r5
- str r6, [r7, #124]
- b .L92
-.L93:
- .align 3
-.L91:
- .word 1
- .word 0
- .word 0
- .word 0
- .word .LANCHOR0-(.LPIC16+4)
-.L92:
-.L3:
- vadd.i32 q9, q9, q1
- add r3, r8, r0
- vadd.i32 q10, q10, q5
- add r5, fp, r4
- veor q3, q3, q9
- mov r6, r3
- veor q2, q2, q10
- ldr r3, [r7, #96]
- str r5, [r7, #116]
- add r10, r10, r1
- vrev32.16 q3, q3
- str r6, [r7, #108]
- vadd.i32 q8, q8, q3
- vrev32.16 q2, q2
- vadd.i32 q15, q15, q2
- mov fp, r3
- ldr r3, [r7, #100]
- veor q4, q8, q1
- veor q6, q15, q5
- add fp, fp, r2
- eors r3, r3, r5
- mov r5, r6
- ldr r6, [r7, #112]
- vshl.i32 q1, q4, #12
- vshl.i32 q5, q6, #12
- ror r3, r3, #16
- eors r6, r6, r5
- eor lr, lr, r10
- vsri.32 q1, q4, #20
- mov r5, r6
- ldr r6, [r7, #124]
- vsri.32 q5, q6, #20
- str r3, [r7, #124]
- eor r6, r6, fp
- ror r5, r5, #16
- vadd.i32 q9, q9, q1
- ror lr, lr, #16
- ror r3, r6, #16
- ldr r6, [r7, #124]
- vadd.i32 q10, q10, q5
- add r9, r9, lr
- veor q4, q9, q3
- add ip, ip, r6
- ldr r6, [r7, #104]
- veor q6, q10, q2
- eor r4, ip, r4
- str r3, [r7, #104]
- vshl.i32 q3, q4, #8
- eor r1, r9, r1
- mov r8, r6
- ldr r6, [r7, #120]
- vshl.i32 q2, q6, #8
- ror r4, r4, #20
- add r6, r6, r3
- vsri.32 q3, q4, #24
- str r6, [r7, #100]
- eors r2, r2, r6
- ldr r6, [r7, #116]
- vsri.32 q2, q6, #24
- add r8, r8, r5
- ror r2, r2, #20
- adds r6, r4, r6
- vadd.i32 q4, q8, q3
- eor r0, r8, r0
- vadd.i32 q15, q15, q2
- mov r3, r6
- ldr r6, [r7, #108]
- veor q6, q4, q1
- ror r0, r0, #20
- str r3, [r7, #112]
- veor q5, q15, q5
- adds r6, r0, r6
- str r6, [r7, #120]
- mov r6, r3
- ldr r3, [r7, #124]
- vshl.i32 q8, q6, #7
- add fp, fp, r2
- eors r3, r3, r6
- ldr r6, [r7, #120]
- vshl.i32 q1, q5, #7
- ror r1, r1, #20
- eors r5, r5, r6
- vsri.32 q8, q6, #25
- ldr r6, [r7, #104]
- ror r3, r3, #24
- ror r5, r5, #24
- vsri.32 q1, q5, #25
- str r5, [r7, #116]
- eor r6, fp, r6
- ldr r5, [r7, #116]
- add r10, r10, r1
- add ip, r3, ip
- vext.32 q8, q8, q8, #1
- str ip, [r7, #124]
- add ip, r5, r8
- ldr r5, [r7, #100]
- eor lr, r10, lr
- ror r6, r6, #24
- vext.32 q1, q1, q1, #1
- add r8, r6, r5
- vadd.i32 q9, q9, q8
- ldr r5, [r7, #124]
- vext.32 q3, q3, q3, #3
- vadd.i32 q10, q10, q1
- ror lr, lr, #24
- eor r0, ip, r0
- vext.32 q2, q2, q2, #3
- add r9, r9, lr
- eors r4, r4, r5
- veor q3, q9, q3
- ldr r5, [r7, #112]
- eor r1, r9, r1
- ror r0, r0, #25
- veor q2, q10, q2
- adds r5, r0, r5
- vext.32 q4, q4, q4, #2
- str r5, [r7, #112]
- ldr r5, [r7, #120]
- ror r1, r1, #25
- vrev32.16 q3, q3
- eor r2, r8, r2
- vext.32 q15, q15, q15, #2
- adds r5, r1, r5
- vadd.i32 q4, q4, q3
- ror r4, r4, #25
- vrev32.16 q2, q2
- str r5, [r7, #100]
- vadd.i32 q15, q15, q2
- eors r3, r3, r5
- ldr r5, [r7, #112]
- add fp, fp, r4
- veor q8, q4, q8
- ror r2, r2, #25
- veor q1, q15, q1
- eor lr, fp, lr
- eors r6, r6, r5
- ror r3, r3, #16
- ldr r5, [r7, #116]
- add r10, r10, r2
- str r3, [r7, #120]
- ror lr, lr, #16
- ldr r3, [r7, #120]
- eor r5, r10, r5
- vshl.i32 q5, q8, #12
- add ip, lr, ip
- vshl.i32 q6, q1, #12
- str ip, [r7, #104]
- add ip, r3, r8
- str ip, [r7, #116]
- ldr r3, [r7, #124]
- ror r5, r5, #16
- vsri.32 q5, q8, #20
- ror r6, r6, #16
- add ip, r5, r3
- ldr r3, [r7, #104]
- vsri.32 q6, q1, #20
- add r9, r9, r6
- eor r2, ip, r2
- eors r4, r4, r3
- ldr r3, [r7, #116]
- eor r0, r9, r0
- vadd.i32 q9, q9, q5
- ror r4, r4, #20
- eors r1, r1, r3
- vadd.i32 q10, q10, q6
- ror r3, r2, #20
- str r3, [r7, #108]
- ldr r3, [r7, #112]
- veor q3, q9, q3
- ror r0, r0, #20
- add r8, r4, fp
- veor q2, q10, q2
- add fp, r0, r3
- ldr r3, [r7, #100]
- ror r1, r1, #20
- mov r2, r8
- vshl.i32 q8, q3, #8
- str r8, [r7, #96]
- add r8, r1, r3
- ldr r3, [r7, #108]
- vmov q1, q6 @ v4si
- vshl.i32 q6, q2, #8
- eor r6, fp, r6
- add r10, r10, r3
- ldr r3, [r7, #120]
- vsri.32 q8, q3, #24
- eor lr, r2, lr
- eor r3, r8, r3
- ror r2, r6, #24
- vsri.32 q6, q2, #24
- eor r5, r10, r5
- str r2, [r7, #124]
- ror r2, r3, #24
- ldr r3, [r7, #104]
- vmov q3, q8 @ v4si
- vadd.i32 q15, q15, q6
- ror lr, lr, #24
- vadd.i32 q8, q4, q8
- ror r6, r5, #24
- add r5, lr, r3
- ldr r3, [r7, #124]
- veor q4, q8, q5
- add ip, ip, r6
- vmov q2, q6 @ v4si
- add r9, r9, r3
- veor q6, q15, q1
- ldr r3, [r7, #116]
- vshl.i32 q1, q4, #7
- str r2, [r7, #100]
- add r3, r3, r2
- str r3, [r7, #120]
- vshl.i32 q5, q6, #7
- eors r1, r1, r3
- ldr r3, [r7, #108]
- vsri.32 q1, q4, #25
- eors r4, r4, r5
- eor r0, r9, r0
- eor r2, ip, r3
- vsri.32 q5, q6, #25
- ldr r3, [r7, #92]
- ror r4, r4, #25
- str r6, [r7, #112]
- ror r0, r0, #25
- subs r3, r3, #1
- str r5, [r7, #104]
- ror r1, r1, #25
- ror r2, r2, #25
- vext.32 q15, q15, q15, #2
- str r3, [r7, #92]
- vext.32 q2, q2, q2, #1
- vext.32 q8, q8, q8, #2
- vext.32 q3, q3, q3, #1
- vext.32 q5, q5, q5, #3
- vext.32 q1, q1, q1, #3
- bne .L3
- ldr r3, [r7, #84]
- vadd.i32 q4, q12, q10
- str r9, [r7, #92]
- mov r9, r10
- mov r10, r8
- ldr r8, [r7, #96]
- str lr, [r7, #96]
- mov lr, r5
- ldr r5, [r7, #52]
- vadd.i32 q5, q13, q5
- ldr r6, [r7, #76]
- vadd.i32 q15, q14, q15
- add fp, fp, r5
- ldr r5, [r7, #48]
- str r3, [r7, #104]
- vadd.i32 q7, q14, q8
- ldr r3, [r6, #12] @ unaligned
- add r10, r10, r5
- str r0, [r7, #36]
- vadd.i32 q2, q11, q2
- ldr r0, [r6] @ unaligned
- vadd.i32 q6, q12, q9
- ldr r5, [r7, #104]
- vadd.i32 q1, q13, q1
- str r1, [r7, #116]
- vadd.i32 q11, q11, q0
- ldr r1, [r6, #4] @ unaligned
- str r2, [r7, #32]
- vadd.i32 q3, q11, q3
- ldr r2, [r6, #8] @ unaligned
- vadd.i32 q11, q11, q0
- str r4, [r7, #108]
- ldr r4, [r7, #100]
- vadd.i32 q11, q11, q0
- stmia r5!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- ldr r3, [r7, #44]
- ldr r5, [r7, #84]
- vldr d20, [r2, #80]
- vldr d21, [r2, #88]
- add r3, r9, r3
- str r3, [r7, #104]
- veor q10, q10, q4
- ldr r3, [r7, #40]
- add r3, r8, r3
- str r3, [r7, #100]
- ldr r3, [r7, #72]
- vstr d20, [r2, #80]
- vstr d21, [r2, #88]
- adds r1, r4, r3
- str r1, [r7, #28]
- ldmia r5!, {r0, r1, r2, r3}
- ldr r4, [r7, #68]
- ldr r5, [r7, #112]
- ldr r8, [r7, #84]
- add r5, r5, r4
- ldr r4, [r7, #96]
- str r5, [r7, #24]
- ldr r5, [r7, #64]
- add r4, r4, r5
- ldr r5, [r7, #60]
- str r4, [r7, #96]
- ldr r4, [r7, #124]
- add r4, r4, r5
- str r4, [r7, #20]
- ldr r4, [r7, #80]
- mov r5, r8
- str r0, [r4] @ unaligned
- mov r0, r4
- str r1, [r4, #4] @ unaligned
- mov r4, r8
- str r2, [r0, #8] @ unaligned
- mov r8, r0
- str r3, [r0, #12] @ unaligned
- mov r9, r4
- ldr r0, [r6, #16]! @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r6, [r7, #76]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r3, [r7, #88]
- vldr d20, [r3, #80]
- vldr d21, [r3, #88]
- veor q10, q10, q5
- vstr d20, [r3, #80]
- vstr d21, [r3, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #16] @ unaligned
- str r1, [r8, #20] @ unaligned
- str r2, [r8, #24] @ unaligned
- str r3, [r8, #28] @ unaligned
- mov r8, r5
- ldr r0, [r6, #32]! @ unaligned
- mov r5, r9
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r1, [r7, #88]
- vldr d16, [r1, #80]
- vldr d17, [r1, #88]
- veor q15, q8, q15
- vstr d30, [r1, #80]
- vstr d31, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #32] @ unaligned
- str r1, [r8, #36] @ unaligned
- str r2, [r8, #40] @ unaligned
- str r3, [r8, #44] @ unaligned
- mov r8, r5
- ldr r0, [r6, #48]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- stmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- ldr r1, [r7, #88]
- str r9, [r7, #112]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q9, q9, q2
- vstr d18, [r1, #80]
- vstr d19, [r1, #88]
- ldmia r9!, {r0, r1, r2, r3}
- str r0, [r5, #48] @ unaligned
- str r1, [r5, #52] @ unaligned
- str r2, [r5, #56] @ unaligned
- str r3, [r5, #60] @ unaligned
- ldr r0, [r6, #64]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- mov r9, r6
- mov r6, r4
- stmia r6!, {r0, r1, r2, r3}
- mov r6, r4
- ldr r1, [r7, #88]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q9, q9, q6
- vstr d18, [r1, #80]
- vstr d19, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r6
- str r3, [r5, #76] @ unaligned
- mov r3, r9
- str r2, [r5, #72] @ unaligned
- str r0, [r5, #64] @ unaligned
- str r1, [r5, #68] @ unaligned
- mov r5, r4
- ldr r0, [r3, #80]! @ unaligned
- mov r9, r3
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- mov r9, r4
- ldr r6, [r7, #76]
- str r9, [r7, #124]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r1, [r7, #88]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q1, q9, q1
- vstr d2, [r1, #80]
- vstr d3, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #80] @ unaligned
- str r1, [r8, #84] @ unaligned
- str r2, [r8, #88] @ unaligned
- str r3, [r8, #92] @ unaligned
- ldr r0, [r6, #96]! @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r6, [r7, #76]
- stmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- ldr r3, [r7, #88]
- vldr d16, [r3, #80]
- vldr d17, [r3, #88]
- veor q8, q8, q7
- vstr d16, [r3, #80]
- vstr d17, [r3, #88]
- ldmia r9!, {r0, r1, r2, r3}
- str r0, [r5, #96] @ unaligned
- str r1, [r5, #100] @ unaligned
- str r2, [r5, #104] @ unaligned
- str r3, [r5, #108] @ unaligned
- ldr r0, [r6, #112]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- mov r6, r4
- stmia r6!, {r0, r1, r2, r3}
- mov r6, r5
- ldr r3, [r7, #88]
- vldr d16, [r3, #80]
- vldr d17, [r3, #88]
- veor q8, q8, q3
- vstr d16, [r3, #80]
- vstr d17, [r3, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r5
- mov r8, r4
- str r2, [r5, #120] @ unaligned
- ldr r2, [r7, #76]
- str r0, [r5, #112] @ unaligned
- str r1, [r5, #116] @ unaligned
- str r3, [r5, #124] @ unaligned
- ldr r3, [r2, #128]
- ldr r1, [r7, #104]
- eor r3, fp, r3
- str r3, [r5, #128]
- ldr r3, [r2, #132]
- mov r5, r2
- eor r3, r10, r3
- str r3, [r6, #132]
- ldr r3, [r2, #136]
- mov r6, r5
- eors r1, r1, r3
- str r1, [r8, #136]
- ldr r1, [r7, #56]
- ldr r3, [r2, #140]
- ldr r2, [r7, #100]
- ldr r0, [r7, #108]
- eors r3, r3, r2
- str r3, [r4, #140]
- ldr r3, [r1]
- ldr r2, [r5, #144]
- mov r8, r0
- add r8, r8, r3
- mov r5, r6
- mov r3, r8
- eors r2, r2, r3
- str r2, [r4, #144]
- ldr r3, [r6, #148]
- ldr r2, [r1, #4]
- ldr r6, [r7, #36]
- add r6, r6, r2
- eors r3, r3, r6
- mov r6, r1
- str r3, [r4, #148]
- ldr r2, [r1, #8]
- ldr r1, [r7, #116]
- ldr r3, [r5, #152]
- mov r8, r1
- add r8, r8, r2
- ldr r1, [r7, #32]
- mov r2, r8
- eors r3, r3, r2
- str r3, [r4, #152]
- mov r8, r4
- ldr r2, [r6, #12]
- ldr r3, [r5, #156]
- add r1, r1, r2
- eors r3, r3, r1
- str r3, [r4, #156]
- ldr r2, [r6, #16]
- mov r1, r4
- ldr r3, [r5, #160]
- mov r4, r5
- add ip, ip, r2
- mov r5, r6
- eor r3, ip, r3
- str r3, [r1, #160]
- ldr r2, [r6, #20]
- ldr r3, [r4, #164]
- add lr, lr, r2
- ldr r2, [r7, #92]
- eor r3, lr, r3
- str r3, [r1, #164]
- ldr r6, [r5, #24]
- mov lr, r4
- ldr r3, [r4, #168]
- add r2, r2, r6
- ldr r6, [r7, #120]
- eors r3, r3, r2
- str r3, [r1, #168]
- ldr r5, [r5, #28]
- ldr r3, [r4, #172]
- add r6, r6, r5
- eors r3, r3, r6
- str r3, [r1, #172]
- ldr r4, [r4, #176]
- ldr r0, [r7, #28]
- ldr r5, [r7, #24]
- eors r4, r4, r0
- str r4, [r8, #176]
- ldr r0, [lr, #180]
- ldr r2, [r7, #96]
- eors r0, r0, r5
- str r0, [r8, #180]
- ldr r1, [lr, #184]
- ldr r4, [r7, #20]
- eors r1, r1, r2
- str r1, [r8, #184]
- ldr r2, [lr, #188]
- add r1, lr, #192
- ldr r3, [r7, #72]
- eors r2, r2, r4
- str r2, [r8, #188]
- ldr r2, [r7, #16]
- adds r3, r3, #3
- str r3, [r7, #72]
- mov r3, r8
- adds r3, r3, #192
- str r1, [r7, #76]
- cmp r2, r3
- str r3, [r7, #80]
- bne .L4
- ldr r3, [r7, #12]
- ldr r2, [r7, #4]
- add r3, r3, r2
- str r3, [r7, #12]
-.L2:
- ldr r1, [r7, #8]
- movw r2, #43691
- movt r2, 43690
- umull r2, r3, r1, r2
- lsr fp, r3, #7
- lsl r3, fp, #8
- sub fp, r3, fp, lsl #6
- rsb fp, fp, r1
- lsrs fp, fp, #6
- beq .L6
- ldr r5, [r7, #12]
- ldr r4, [r7, #16]
- ldr r6, [r7, #88]
- ldr lr, [r7, #84]
- vldr d30, .L94
- vldr d31, .L94+8
- str fp, [r7, #120]
- str fp, [r7, #124]
-.L8:
- vmov q2, q11 @ v4si
- movs r3, #10
- vmov q8, q14 @ v4si
- vmov q9, q13 @ v4si
- vmov q10, q12 @ v4si
-.L7:
- vadd.i32 q10, q10, q9
- subs r3, r3, #1
- veor q3, q2, q10
- vrev32.16 q3, q3
- vadd.i32 q8, q8, q3
- veor q9, q8, q9
- vshl.i32 q2, q9, #12
- vsri.32 q2, q9, #20
- vadd.i32 q10, q10, q2
- veor q3, q10, q3
- vshl.i32 q9, q3, #8
- vsri.32 q9, q3, #24
- vadd.i32 q8, q8, q9
- vext.32 q9, q9, q9, #3
- veor q2, q8, q2
- vext.32 q8, q8, q8, #2
- vshl.i32 q3, q2, #7
- vsri.32 q3, q2, #25
- vext.32 q3, q3, q3, #1
- vadd.i32 q10, q10, q3
- veor q9, q10, q9
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q3, q8, q3
- vshl.i32 q2, q3, #12
- vsri.32 q2, q3, #20
- vadd.i32 q10, q10, q2
- vmov q3, q2 @ v4si
- veor q9, q10, q9
- vshl.i32 q2, q9, #8
- vsri.32 q2, q9, #24
- vadd.i32 q8, q8, q2
- vext.32 q2, q2, q2, #1
- veor q3, q8, q3
- vext.32 q8, q8, q8, #2
- vshl.i32 q9, q3, #7
- vsri.32 q9, q3, #25
- vext.32 q9, q9, q9, #3
- bne .L7
- ldr r0, [r5] @ unaligned
- vadd.i32 q1, q12, q10
- ldr r1, [r5, #4] @ unaligned
- mov ip, lr
- ldr r2, [r5, #8] @ unaligned
- mov r9, lr
- ldr r3, [r5, #12] @ unaligned
- mov r10, r5
- vadd.i32 q9, q13, q9
- mov r8, lr
- vadd.i32 q8, q14, q8
- stmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- vldr d20, [r6, #80]
- vldr d21, [r6, #88]
- vadd.i32 q3, q11, q2
- veor q10, q10, q1
- vadd.i32 q11, q11, q15
- vstr d20, [r6, #80]
- vstr d21, [r6, #88]
- ldmia r9!, {r0, r1, r2, r3}
- mov r9, r5
- str r0, [r4] @ unaligned
- str r1, [r4, #4] @ unaligned
- str r2, [r4, #8] @ unaligned
- str r3, [r4, #12] @ unaligned
- ldr r0, [r10, #16]! @ unaligned
- ldr r1, [r10, #4] @ unaligned
- ldr r2, [r10, #8] @ unaligned
- ldr r3, [r10, #12] @ unaligned
- add r10, r4, #48
- adds r4, r4, #64
- stmia r8!, {r0, r1, r2, r3}
- mov r8, lr
- vldr d20, [r6, #80]
- vldr d21, [r6, #88]
- veor q10, q10, q9
- vstr d20, [r6, #80]
- vstr d21, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- str r0, [r4, #-48] @ unaligned
- str r1, [r4, #-44] @ unaligned
- str r2, [r4, #-40] @ unaligned
- str r3, [r4, #-36] @ unaligned
- ldr r0, [r9, #32]! @ unaligned
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- mov r9, r5
- adds r5, r5, #64
- stmia r8!, {r0, r1, r2, r3}
- mov r8, lr
- vldr d18, [r6, #80]
- vldr d19, [r6, #88]
- veor q9, q9, q8
- vstr d18, [r6, #80]
- vstr d19, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- str r0, [r4, #-32] @ unaligned
- str r1, [r4, #-28] @ unaligned
- str r2, [r4, #-24] @ unaligned
- str r3, [r4, #-20] @ unaligned
- ldr r0, [r9, #48]! @ unaligned
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- stmia r8!, {r0, r1, r2, r3}
- vldr d16, [r6, #80]
- vldr d17, [r6, #88]
- veor q8, q8, q3
- vstr d16, [r6, #80]
- vstr d17, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- str r0, [r4, #-16] @ unaligned
- str r1, [r4, #-12] @ unaligned
- str r3, [r10, #12] @ unaligned
- ldr r3, [r7, #124]
- str r2, [r10, #8] @ unaligned
- cmp r3, #1
- beq .L87
- movs r3, #1
- str r3, [r7, #124]
- b .L8
-.L95:
- .align 3
-.L94:
- .word 1
- .word 0
- .word 0
- .word 0
-.L87:
- ldr fp, [r7, #120]
- ldr r3, [r7, #12]
- lsl fp, fp, #6
- add r3, r3, fp
- str r3, [r7, #12]
- ldr r3, [r7, #16]
- add r3, r3, fp
- str r3, [r7, #16]
-.L6:
- ldr r3, [r7, #8]
- ands r9, r3, #63
- beq .L1
- vmov q3, q11 @ v4si
- movs r3, #10
- vmov q8, q14 @ v4si
- mov r5, r9
- vmov q15, q13 @ v4si
- vmov q10, q12 @ v4si
-.L10:
- vadd.i32 q10, q10, q15
- subs r3, r3, #1
- veor q9, q3, q10
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q15, q8, q15
- vshl.i32 q3, q15, #12
- vsri.32 q3, q15, #20
- vadd.i32 q10, q10, q3
- veor q15, q10, q9
- vshl.i32 q9, q15, #8
- vsri.32 q9, q15, #24
- vadd.i32 q8, q8, q9
- vext.32 q9, q9, q9, #3
- veor q3, q8, q3
- vext.32 q8, q8, q8, #2
- vshl.i32 q15, q3, #7
- vsri.32 q15, q3, #25
- vext.32 q15, q15, q15, #1
- vadd.i32 q10, q10, q15
- veor q9, q10, q9
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q15, q8, q15
- vshl.i32 q3, q15, #12
- vsri.32 q3, q15, #20
- vadd.i32 q10, q10, q3
- vmov q15, q3 @ v4si
- veor q9, q10, q9
- vshl.i32 q3, q9, #8
- vsri.32 q3, q9, #24
- vadd.i32 q8, q8, q3
- vext.32 q3, q3, q3, #1
- veor q9, q8, q15
- vext.32 q8, q8, q8, #2
- vshl.i32 q15, q9, #7
- vsri.32 q15, q9, #25
- vext.32 q15, q15, q15, #3
- bne .L10
- cmp r5, #15
- mov r9, r5
- bhi .L88
- vadd.i32 q12, q12, q10
- ldr r3, [r7, #88]
- vst1.64 {d24-d25}, [r3:128]
-.L14:
- ldr r3, [r7, #8]
- and r2, r3, #48
- cmp r9, r2
- bls .L1
- ldr r6, [r7, #16]
- add r3, r2, #16
- ldr r1, [r7, #12]
- rsb ip, r2, r9
- adds r0, r1, r2
- mov r4, r6
- add r1, r1, r3
- add r4, r4, r2
- add r3, r3, r6
- cmp r0, r3
- it cc
- cmpcc r4, r1
- ite cs
- movcs r3, #1
- movcc r3, #0
- cmp ip, #18
- ite ls
- movls r3, #0
- andhi r3, r3, #1
- cmp r3, #0
- beq .L16
- and r1, r0, #7
- mov r3, r2
- negs r1, r1
- and r1, r1, #15
- cmp r1, ip
- it cs
- movcs r1, ip
- cmp r1, #0
- beq .L17
- ldr r5, [r7, #88]
- cmp r1, #1
- ldrb r0, [r0] @ zero_extendqisi2
- add r3, r2, #1
- ldrb lr, [r5, r2] @ zero_extendqisi2
- mov r6, r5
- eor r0, lr, r0
- strb r0, [r4]
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #2
- ldrb r4, [r5, r3] @ zero_extendqisi2
- ldr r5, [r7, #16]
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #2
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #3
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #3
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #4
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #4
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #5
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #5
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #6
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #6
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #7
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #7
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #8
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #8
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #9
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #9
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #10
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #10
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #11
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #11
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #12
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #12
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #13
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #13
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #15
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #14
- bne .L17
- ldr r0, [r7, #12]
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eors r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #15
-.L17:
- rsb r4, r1, ip
- add r0, ip, #-1
- sub r6, r4, #16
- subs r0, r0, r1
- cmp r0, #14
- lsr r6, r6, #4
- add r6, r6, #1
- lsl lr, r6, #4
- bls .L19
- add r2, r2, r1
- ldr r1, [r7, #12]
- ldr r5, [r7, #16]
- cmp r6, #1
- add r0, r1, r2
- ldr r1, [r7, #88]
- add r1, r1, r2
- vld1.64 {d18-d19}, [r0:64]
- add r2, r2, r5
- vld1.8 {q8}, [r1]
- veor q8, q8, q9
- vst1.8 {q8}, [r2]
- beq .L20
- add r8, r1, #16
- add ip, r2, #16
- vldr d18, [r0, #16]
- vldr d19, [r0, #24]
- cmp r6, #2
- vld1.8 {q8}, [r8]
- veor q8, q8, q9
- vst1.8 {q8}, [ip]
- beq .L20
- add r8, r1, #32
- add ip, r2, #32
- vldr d18, [r0, #32]
- vldr d19, [r0, #40]
- cmp r6, #3
- vld1.8 {q8}, [r8]
- veor q8, q8, q9
- vst1.8 {q8}, [ip]
- beq .L20
- adds r1, r1, #48
- adds r2, r2, #48
- vldr d18, [r0, #48]
- vldr d19, [r0, #56]
- vld1.8 {q8}, [r1]
- veor q8, q8, q9
- vst1.8 {q8}, [r2]
-.L20:
- cmp lr, r4
- add r3, r3, lr
- beq .L1
-.L19:
- ldr r4, [r7, #88]
- adds r2, r3, #1
- ldr r1, [r7, #12]
- cmp r2, r9
- ldr r5, [r7, #16]
- ldrb r0, [r4, r3] @ zero_extendqisi2
- ldrb r1, [r1, r3] @ zero_extendqisi2
- eor r1, r1, r0
- strb r1, [r5, r3]
- bcs .L1
- ldr r0, [r7, #12]
- adds r1, r3, #2
- mov r6, r4
- cmp r9, r1
- ldrb r4, [r4, r2] @ zero_extendqisi2
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #3
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- adds r1, r3, #4
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #5
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- adds r1, r3, #6
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #7
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #8
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #9
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #10
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #11
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #12
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #13
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r1, [r7, #12]
- adds r3, r3, #14
- ldrb r0, [r6, r2] @ zero_extendqisi2
- cmp r9, r3
- ldrb r1, [r1, r2] @ zero_extendqisi2
- eor r1, r1, r0
- strb r1, [r5, r2]
- bls .L1
- ldr r2, [r7, #88]
- ldrb r1, [r2, r3] @ zero_extendqisi2
- ldr r2, [r7, #12]
- ldrb r2, [r2, r3] @ zero_extendqisi2
- eors r2, r2, r1
- ldr r1, [r7, #16]
- strb r2, [r1, r3]
-.L1:
- adds r7, r7, #164
- mov sp, r7
- @ sp needed
- vldm sp!, {d8-d15}
- pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L88:
- ldr r5, [r7, #12]
- vadd.i32 q12, q12, q10
- ldr r4, [r7, #84]
- cmp r9, #31
- ldr r0, [r5] @ unaligned
- ldr r1, [r5, #4] @ unaligned
- mov r6, r4
- ldr r2, [r5, #8] @ unaligned
- ldr r3, [r5, #12] @ unaligned
- stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- ldr r6, [r7, #16]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
- veor q9, q9, q12
- vstr d18, [r2, #80]
- vstr d19, [r2, #88]
- ldmia r4!, {r0, r1, r2, r3}
- str r1, [r6, #4] @ unaligned
- mov r1, r6
- str r0, [r6] @ unaligned
- str r2, [r6, #8] @ unaligned
- str r3, [r6, #12] @ unaligned
- bhi .L89
- vadd.i32 q13, q13, q15
- ldr r3, [r7, #88]
- vstr d26, [r3, #16]
- vstr d27, [r3, #24]
- b .L14
-.L16:
- subs r3, r2, #1
- ldr r2, [r7, #12]
- add r2, r2, r9
- mov r5, r2
- ldr r2, [r7, #88]
- add r2, r2, r3
- mov r3, r2
-.L24:
- ldrb r1, [r0], #1 @ zero_extendqisi2
- ldrb r2, [r3, #1]! @ zero_extendqisi2
- cmp r0, r5
- eor r2, r2, r1
- strb r2, [r4], #1
- bne .L24
- adds r7, r7, #164
- mov sp, r7
- @ sp needed
- vldm sp!, {d8-d15}
- pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L26:
- ldr r3, [r7, #80]
- str r3, [r7, #16]
- b .L2
-.L89:
- mov r3, r5
- ldr r4, [r7, #84]
- ldr r0, [r3, #16]! @ unaligned
- add lr, r1, #16
- mov r5, r1
- vadd.i32 q13, q13, q15
- mov r6, r4
- cmp r9, #47
- ldr r1, [r3, #4] @ unaligned
- ldr r2, [r3, #8] @ unaligned
- ldr r3, [r3, #12] @ unaligned
- stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
- veor q13, q9, q13
- vstr d26, [r2, #80]
- vstr d27, [r2, #88]
- ldmia r4!, {r0, r1, r2, r3}
- str r0, [r5, #16] @ unaligned
- str r1, [lr, #4] @ unaligned
- str r2, [lr, #8] @ unaligned
- str r3, [lr, #12] @ unaligned
- bhi .L90
- vadd.i32 q8, q14, q8
- ldr r3, [r7, #88]
- vstr d16, [r3, #32]
- vstr d17, [r3, #40]
- b .L14
-.L90:
- ldr r3, [r7, #12]
- add lr, r5, #32
- ldr r4, [r7, #84]
- vadd.i32 q8, q14, q8
- ldr r5, [r7, #88]
- vadd.i32 q11, q11, q3
- ldr r0, [r3, #32]! @ unaligned
- mov r6, r4
- vstr d22, [r5, #48]
- vstr d23, [r5, #56]
- ldr r1, [r3, #4] @ unaligned
- ldr r2, [r3, #8] @ unaligned
- ldr r3, [r3, #12] @ unaligned
- stmia r4!, {r0, r1, r2, r3}
- vldr d18, [r5, #80]
- vldr d19, [r5, #88]
- veor q9, q9, q8
- ldr r4, [r7, #16]
- vstr d18, [r5, #80]
- vstr d19, [r5, #88]
- ldmia r6!, {r0, r1, r2, r3}
- str r0, [r4, #32] @ unaligned
- str r1, [lr, #4] @ unaligned
- str r2, [lr, #8] @ unaligned
- str r3, [lr, #12] @ unaligned
- b .L14
- .size CRYPTO_chacha_20_neon, .-CRYPTO_chacha_20_neon
- .section .rodata
- .align 2
-.LANCHOR0 = . + 0
-.LC0:
- .word 1634760805
- .word 857760878
- .word 2036477234
- .word 1797285236
- .ident "GCC: (Linaro GCC 2014.11) 4.9.3 20141031 (prerelease)"
- .section .note.GNU-stack,"",%progbits
-
-#endif /* __arm__ */
-#endif /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/chacha/chacha_vec_arm_generate.go b/src/crypto/chacha/chacha_vec_arm_generate.go
deleted file mode 100644
index 82aa847f..00000000
--- a/src/crypto/chacha/chacha_vec_arm_generate.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2014, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// This package generates chacha_vec_arm.S from chacha_vec.c. Install the
-// arm-linux-gnueabihf-gcc compiler as described in BUILDING.md. Then:
-// `(cd crypto/chacha && go run chacha_vec_arm_generate.go)`.
-
-package main
-
-import (
- "bufio"
- "bytes"
- "os"
- "os/exec"
- "strings"
-)
-
-const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
-
-func main() {
- compiler := defaultCompiler
- if len(os.Args) > 1 {
- compiler = os.Args[1]
- }
-
- args := []string{
- "-O3",
- "-mcpu=cortex-a8",
- "-mfpu=neon",
- "-fpic",
- "-DASM_GEN",
- "-I", "../../include",
- "-S", "chacha_vec.c",
- "-o", "-",
- }
-
- output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
- if err != nil {
- panic(err)
- }
- defer output.Close()
-
- output.WriteString(preamble)
- output.WriteString(compiler)
- output.WriteString(" ")
- output.WriteString(strings.Join(args, " "))
- output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n")
- output.WriteString("#if defined(__arm__)\n\n")
-
- cmd := exec.Command(compiler, args...)
- cmd.Stderr = os.Stderr
- asm, err := cmd.StdoutPipe()
- if err != nil {
- panic(err)
- }
- if err := cmd.Start(); err != nil {
- panic(err)
- }
-
- attr28 := []byte(".eabi_attribute 28,")
- globalDirective := []byte(".global\t")
- newLine := []byte("\n")
- attr28Handled := false
-
- scanner := bufio.NewScanner(asm)
- for scanner.Scan() {
- line := scanner.Bytes()
-
- if bytes.Contains(line, attr28) {
- output.WriteString(attr28Block)
- attr28Handled = true
- continue
- }
-
- output.Write(line)
- output.Write(newLine)
-
- if i := bytes.Index(line, globalDirective); i >= 0 {
- output.Write(line[:i])
- output.WriteString(".hidden\t")
- output.Write(line[i+len(globalDirective):])
- output.Write(newLine)
- }
- }
-
- if err := scanner.Err(); err != nil {
- panic(err)
- }
-
- if !attr28Handled {
- panic("EABI attribute 28 not seen in processing")
- }
-
- if err := cmd.Wait(); err != nil {
- panic(err)
- }
-
- output.WriteString(trailer)
-}
-
-const preamble = `# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-# `
-
-const attr28Block = `
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
- .eabi_attribute 28, 1
-#else
- .eabi_attribute 28, 0
-#endif
-
-`
-
-const trailer = `
-#endif /* __arm__ */
-#endif /* !OPENSSL_NO_ASM */
-`
diff --git a/src/crypto/cipher/aead_test.cc b/src/crypto/cipher/aead_test.cc
index 79d7110d..f21291e7 100644
--- a/src/crypto/cipher/aead_test.cc
+++ b/src/crypto/cipher/aead_test.cc
@@ -192,37 +192,158 @@ static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
return 1;
}
-struct AEADName {
+static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
+ const size_t key_len = EVP_AEAD_key_length(aead);
+ const size_t nonce_len = EVP_AEAD_nonce_length(aead);
+ const size_t max_overhead = EVP_AEAD_max_overhead(aead);
+
+ std::vector<uint8_t> key(key_len, 'a');
+ ScopedEVP_AEAD_CTX ctx;
+ if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
+ return false;
+ }
+
+ static const uint8_t kPlaintext[260] =
+ "testing123456testing123456testing123456testing123456testing123456testing"
+ "123456testing123456testing123456testing123456testing123456testing123456t"
+ "esting123456testing123456testing123456testing123456testing123456testing1"
+ "23456testing123456testing123456testing12345";
+ const std::vector<size_t> offsets = {
+ 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
+ 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
+ };
+
+ std::vector<uint8_t> nonce(nonce_len, 'b');
+ std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
+ size_t valid_encryption_len;
+ if (!EVP_AEAD_CTX_seal(
+ ctx.get(), valid_encryption.data(), &valid_encryption_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
+ kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
+ return false;
+ }
+
+ // First test with out > in, which we expect to fail.
+ for (auto offset : offsets) {
+ if (offset == 0) {
+ // Will be tested in the next loop.
+ continue;
+ }
+
+ std::vector<uint8_t> buffer(offset + valid_encryption_len);
+ memcpy(buffer.data(), kPlaintext, sizeof(kPlaintext));
+ uint8_t *out = buffer.data() + offset;
+
+ size_t out_len;
+ if (!EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(),
+ nonce_len, buffer.data(), sizeof(kPlaintext),
+ nullptr, 0)) {
+ // We expect offsets where the output is greater than the input to fail.
+ ERR_clear_error();
+ } else {
+ fprintf(stderr,
+ "EVP_AEAD_CTX_seal unexpectedly succeeded for offset %u.\n",
+ static_cast<unsigned>(offset));
+ return false;
+ }
+
+ memcpy(buffer.data(), valid_encryption.data(), valid_encryption_len);
+ if (!EVP_AEAD_CTX_open(ctx.get(), out, &out_len, valid_encryption_len,
+ nonce.data(), nonce_len, buffer.data(),
+ valid_encryption_len, nullptr, 0)) {
+ // We expect offsets where the output is greater than the input to fail.
+ ERR_clear_error();
+ } else {
+ fprintf(stderr,
+ "EVP_AEAD_CTX_open unexpectedly succeeded for offset %u.\n",
+ static_cast<unsigned>(offset));
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ }
+
+ // Test with out <= in, which we expect to work.
+ for (auto offset : offsets) {
+ std::vector<uint8_t> buffer(offset + valid_encryption_len);
+ uint8_t *const out = buffer.data();
+ uint8_t *const in = buffer.data() + offset;
+ memcpy(in, kPlaintext, sizeof(kPlaintext));
+
+ size_t out_len;
+ if (!EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(),
+ nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal failed for offset -%u.\n",
+ static_cast<unsigned>(offset));
+ return false;
+ }
+
+ if (out_len != valid_encryption_len ||
+ memcmp(out, valid_encryption.data(), out_len) != 0) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output for offset -%u.\n",
+ static_cast<unsigned>(offset));
+ return false;
+ }
+
+ memcpy(in, valid_encryption.data(), valid_encryption_len);
+ if (!EVP_AEAD_CTX_open(ctx.get(), out, &out_len,
+ offset + valid_encryption_len, nonce.data(),
+ nonce_len, in, valid_encryption_len, nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_open failed for offset -%u.\n",
+ static_cast<unsigned>(offset));
+ return false;
+ }
+
+ if (out_len != sizeof(kPlaintext) ||
+ memcmp(out, kPlaintext, out_len) != 0) {
+ fprintf(stderr, "EVP_AEAD_CTX_open produced bad output for offset -%u.\n",
+ static_cast<unsigned>(offset));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+struct KnownAEAD {
const char name[40];
const EVP_AEAD *(*func)(void);
+ // limited_implementation indicates that tests that assume a generic AEAD
+ // interface should not be performed. For example, the key-wrap AEADs only
+ // handle inputs that are a multiple of eight bytes in length and the
+ // SSLv3/TLS AEADs have the concept of “direction”.
+ bool limited_implementation;
};
-static const struct AEADName kAEADs[] = {
- { "aes-128-gcm", EVP_aead_aes_128_gcm },
- { "aes-256-gcm", EVP_aead_aes_256_gcm },
- { "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
- { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old },
- { "rc4-md5-tls", EVP_aead_rc4_md5_tls },
- { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
- { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls },
- { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv },
- { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls },
- { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls },
- { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv },
- { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls },
- { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls },
- { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls },
- { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv },
- { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3 },
- { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3 },
- { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3 },
- { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3 },
- { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3 },
- { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap },
- { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap },
- { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256 },
- { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256 },
- { "", NULL },
+static const struct KnownAEAD kAEADs[] = {
+ { "aes-128-gcm", EVP_aead_aes_128_gcm, false },
+ { "aes-256-gcm", EVP_aead_aes_256_gcm, false },
+ { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
+ { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
+ { "rc4-md5-tls", EVP_aead_rc4_md5_tls, true },
+ { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true },
+ { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
+ { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
+ { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
+ { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true },
+ { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true },
+ { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true },
+ { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true },
+ { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true },
+ { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true },
+ { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true },
+ { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, true },
+ { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
+ { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
+ { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
+ { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true },
+ { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true },
+ { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
+ { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
+ { "", NULL, false },
};
int main(int argc, char **argv) {
@@ -233,22 +354,28 @@ int main(int argc, char **argv) {
return 1;
}
- const EVP_AEAD *aead;
+ const struct KnownAEAD *known_aead;
for (unsigned i = 0;; i++) {
- const struct AEADName &aead_name = kAEADs[i];
- if (aead_name.func == NULL) {
+ known_aead = &kAEADs[i];
+ if (known_aead->func == NULL) {
fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
return 2;
}
- if (strcmp(aead_name.name, argv[1]) == 0) {
- aead = aead_name.func();
+ if (strcmp(known_aead->name, argv[1]) == 0) {
break;
}
}
+ const EVP_AEAD *const aead = known_aead->func();
+
if (!TestCleanupAfterInitFailure(aead)) {
return 1;
}
+ if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
+ fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
+ return 1;
+ }
+
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
}
diff --git a/src/crypto/cipher/cipher.c b/src/crypto/cipher/cipher.c
index 44018675..341516a7 100644
--- a/src/crypto/cipher/cipher.c
+++ b/src/crypto/cipher/cipher.c
@@ -61,7 +61,7 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/src/crypto/cipher/cipher_test.cc b/src/crypto/cipher/cipher_test.cc
index 1cbfae97..fa384c69 100644
--- a/src/crypto/cipher/cipher_test.cc
+++ b/src/crypto/cipher/cipher_test.cc
@@ -109,7 +109,7 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
static bool TestOperation(FileTest *t,
const EVP_CIPHER *cipher,
bool encrypt,
- bool streaming,
+ size_t chunk_size,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &plaintext,
@@ -138,7 +138,7 @@ static bool TestOperation(FileTest *t,
iv.size(), 0)) {
return false;
}
- } else if (iv.size() != (size_t)EVP_CIPHER_CTX_iv_length(ctx.get())) {
+ } else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
t->PrintLine("Bad IV length.");
return false;
}
@@ -170,16 +170,21 @@ static bool TestOperation(FileTest *t,
t->PrintLine("Operation failed.");
return false;
}
- if (streaming) {
- for (size_t i = 0; i < in->size(); i++) {
- uint8_t c = (*in)[i];
+ if (chunk_size != 0) {
+ for (size_t i = 0; i < in->size();) {
+ size_t todo = chunk_size;
+ if (i + todo > in->size()) {
+ todo = in->size() - i;
+ }
+
int len;
- if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, &c,
- 1)) {
+ if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
+ in->data() + i, todo)) {
t->PrintLine("Operation failed.");
return false;
}
result_len1 += len;
+ i += todo;
}
} else if (!in->empty() &&
!EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
@@ -258,20 +263,20 @@ static bool TestCipher(FileTest *t, void *arg) {
}
}
- // By default, both directions are run, unless overridden by the operation.
- if (operation != kDecrypt) {
- if (!TestOperation(t, cipher, true /* encrypt */, false /* single-shot */,
- key, iv, plaintext, ciphertext, aad, tag) ||
- !TestOperation(t, cipher, true /* encrypt */, true /* streaming */, key,
- iv, plaintext, ciphertext, aad, tag)) {
+ const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
+ 17, 31, 32, 33, 63, 64, 65, 512};
+
+ for (size_t chunk_size : chunk_sizes) {
+ // By default, both directions are run, unless overridden by the operation.
+ if (operation != kDecrypt &&
+ !TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
+ plaintext, ciphertext, aad, tag)) {
return false;
}
- }
- if (operation != kEncrypt) {
- if (!TestOperation(t, cipher, false /* decrypt */, false /* single-shot */,
- key, iv, plaintext, ciphertext, aad, tag) ||
- !TestOperation(t, cipher, false /* decrypt */, true /* streaming */,
- key, iv, plaintext, ciphertext, aad, tag)) {
+
+ if (operation != kEncrypt &&
+ !TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
+ plaintext, ciphertext, aad, tag)) {
return false;
}
}
diff --git a/src/crypto/cipher/e_aes.c b/src/crypto/cipher/e_aes.c
index e5104b47..d61d0482 100644
--- a/src/crypto/cipher/e_aes.c
+++ b/src/crypto/cipher/e_aes.c
@@ -54,7 +54,7 @@
#include <openssl/cpu.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
@@ -67,6 +67,10 @@
#endif
+#if defined(_MSC_VER)
+#pragma warning(disable: 4702) /* Unreachable code. */
+#endif
+
typedef struct {
union {
double align;
@@ -252,22 +256,6 @@ void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int enc);
-void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t *ivec);
-
-#if defined(OPENSSL_X86_64)
-size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_encrypt aesni_gcm_encrypt
-size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_decrypt aesni_gcm_decrypt
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
- size_t len);
-#define AES_GCM_ASM(gctx) \
- (gctx->ctr == aesni_ctr32_encrypt_blocks && gctx->gcm.ghash == gcm_ghash_avx)
-#endif /* OPENSSL_X86_64 */
-
#else
/* On other platforms, aesni_capable() will always return false and so the
@@ -288,8 +276,7 @@ static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
#endif
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
- const uint8_t *iv, int enc)
- OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ const uint8_t *iv, int enc) {
int ret, mode;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
@@ -384,17 +371,15 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t len) {
- unsigned int num = ctx->num;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.ctr) {
- CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
- dat->stream.ctr);
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
+ &ctx->num, dat->stream.ctr);
} else {
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
dat->block);
}
- ctx->num = (size_t)num;
return 1;
}
@@ -410,8 +395,7 @@ static char aesni_capable(void);
static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
block128_f *out_block, const uint8_t *key,
- size_t key_len)
- OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ size_t key_len) {
if (aesni_capable()) {
aesni_set_encrypt_key(key, key_len * 8, aes_key);
if (gcm_ctx != NULL) {
@@ -651,57 +635,23 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
}
} else if (ctx->encrypt) {
if (gctx->ctr) {
- size_t bulk = 0;
-#if defined(AES_GCM_ASM)
- if (len >= 32 && AES_GCM_ASM(gctx)) {
- size_t res = (16 - gctx->gcm.mres) % 16;
-
- if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
- return -1;
- }
-
- bulk = AES_gcm_encrypt(in + res, out + res, len - res, &gctx->ks.ks,
- gctx->gcm.Yi.c, gctx->gcm.Xi.u);
- gctx->gcm.len.u[1] += bulk;
- bulk += res;
- }
-#endif
- if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk, gctx->ctr)) {
+ if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+ gctx->ctr)) {
return -1;
}
} else {
- size_t bulk = 0;
- if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk)) {
+ if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
}
} else {
if (gctx->ctr) {
- size_t bulk = 0;
-#if defined(AES_GCM_ASM)
- if (len >= 16 && AES_GCM_ASM(gctx)) {
- size_t res = (16 - gctx->gcm.mres) % 16;
-
- if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
- return -1;
- }
-
- bulk = AES_gcm_decrypt(in + res, out + res, len - res, &gctx->ks.ks,
- gctx->gcm.Yi.c, gctx->gcm.Xi.u);
- gctx->gcm.len.u[1] += bulk;
- bulk += res;
- }
-#endif
- if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk, gctx->ctr)) {
+ if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+ gctx->ctr)) {
return -1;
}
} else {
- size_t bulk = 0;
- if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk)) {
+ if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
}
diff --git a/src/crypto/cipher/e_chacha20poly1305.c b/src/crypto/cipher/e_chacha20poly1305.c
index f3849500..852b2c64 100644
--- a/src/crypto/cipher/e_chacha20poly1305.c
+++ b/src/crypto/cipher/e_chacha20poly1305.c
@@ -23,6 +23,7 @@
#include <openssl/poly1305.h>
#include "internal.h"
+#include "../internal.h"
#define POLY1305_TAG_LEN 16
@@ -79,12 +80,6 @@ static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
}
-#if defined(__arm__)
-#define ALIGNED __attribute__((aligned(16)))
-#else
-#define ALIGNED
-#endif
-
typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len);
@@ -98,7 +93,7 @@ static void aead_poly1305(aead_poly1305_update update,
const uint8_t nonce[12], const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
- uint8_t poly1305_key[32] ALIGNED;
+ alignas(16) uint8_t poly1305_key[32];
memset(poly1305_key, 0, sizeof(poly1305_key));
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
c20_ctx->key, nonce, 0);
@@ -122,7 +117,7 @@ static int seal_impl(aead_poly1305_update poly1305_update,
* 32-bits and this produces a warning because it's always false.
* Casting to uint64_t inside the conditional is not sufficient to stop
* the warning. */
- if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
@@ -139,7 +134,7 @@ static int seal_impl(aead_poly1305_update poly1305_update,
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
- uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
+ alignas(16) uint8_t tag[POLY1305_TAG_LEN];
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
memcpy(out + in_len, tag, c20_ctx->tag_len);
@@ -167,13 +162,13 @@ static int open_impl(aead_poly1305_update poly1305_update,
* 32-bits and this produces a warning because it's always false.
* Casting to uint64_t inside the conditional is not sufficient to stop
* the warning. */
- if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
plaintext_len = in_len - c20_ctx->tag_len;
- uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
+ alignas(16) uint8_t tag[POLY1305_TAG_LEN];
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
plaintext_len);
if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
@@ -249,10 +244,6 @@ const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305;
}
-const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
- return EVP_aead_chacha20_poly1305();
-}
-
static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
diff --git a/src/crypto/cipher/e_des.c b/src/crypto/cipher/e_des.c
index b1d312c3..2ba2bed3 100644
--- a/src/crypto/cipher/e_des.c
+++ b/src/crypto/cipher/e_des.c
@@ -56,7 +56,7 @@
#include <openssl/cipher.h>
#include <openssl/des.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/src/crypto/cipher/e_null.c b/src/crypto/cipher/e_null.c
index cfe1d1b2..3d6a24c3 100644
--- a/src/crypto/cipher/e_null.c
+++ b/src/crypto/cipher/e_null.c
@@ -58,7 +58,7 @@
#include <string.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/src/crypto/cipher/e_rc2.c b/src/crypto/cipher/e_rc2.c
index 8ca7bba6..67418d54 100644
--- a/src/crypto/cipher/e_rc2.c
+++ b/src/crypto/cipher/e_rc2.c
@@ -55,7 +55,7 @@
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/src/crypto/cipher/e_rc4.c b/src/crypto/cipher/e_rc4.c
index 3a2c166a..e7c2ccaf 100644
--- a/src/crypto/cipher/e_rc4.c
+++ b/src/crypto/cipher/e_rc4.c
@@ -58,7 +58,7 @@
#include <string.h>
#include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rc4.h>
diff --git a/src/crypto/cipher/test/cipher_test.txt b/src/crypto/cipher/test/cipher_test.txt
index 21fffdb1..0a940f14 100644
--- a/src/crypto/cipher/test/cipher_test.txt
+++ b/src/crypto/cipher/test/cipher_test.txt
@@ -264,6 +264,14 @@ Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e
AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
Tag = 619cc5aefffe0bfa462af43c1699d050
+Cipher = AES-128-GCM
+Key = 3de7b368783bd7287f2b9b731814c876
+IV = 90dedcfff100eb1f1db9d935
+Plaintext = 8d766795cadc0961c0f448c62df3827eef3a8664599b3adbaab0cfd63875bceb8f992b4f7447dca10ddd716aa0bc4fe925e1aa3e3fd1d5c430c650fe3546d6b9a24d576a857c5f04e8c0a3b149df277aa19cfa64ee235891d3b8ec0e840d268b1e70dd8a4bf97628a0c7aea38aa21eeb8fb1a8437f2abfee05e0d2c30659e312ec03d30da51b7c19073a2341c17df806e27e796d581143d39e4de8d3f8d46aa6d6fc1a98d94fa69b92dab751d930cc12de21fb1a7468af09e3c12ff6c3db3967d10cf140bc46f17a16e24b010b6cba5ebf777341c52042596ee53008389c48d9690ab9f5625795c3e588f72f7a1670b2b25a9f4eee1c8845ac90f1bf47ae4ea4b607a50aca88ed304cbb700d02d5486139b0bc81ec042e574abf986972fa008b83ef22dbfe720c2f2f6355c87c975932cec545ebed657e5e7570c503e9aa7f0b87d0b2648e421ed1d34749637c95d1e931af8925236387e50454f0ba2e22ed05f90450fad46f4eb7ddb08656511dd065c0f852a7e42f618a961a6c6bec42226c6b6043580b009ec9837cf99844cb74794a82c269ff648e0bae9ae50256a0ad98ad9f5a35057b3004ac96f469f9ee966dadc16dc47616586cf242706df96bb2f7ee43d3bd1c65d2eac7b82ef242e77ab509afb9639e5f3995380e926305729ca762c487f4411ec2a9c688b8347e5287216dbb38c3fe2281a89fcb47ee2ee7ddf79bfa3ab61cd56a00981019bbcea8aa0444eb75958e5fa56ea0036d2de4950a7db886f4a318b433bd41e00905ab158171e0ef13172293bdf70064b9dc7b243bf9dc927589bf9e99468d1cb330639dbff1850cc51929b8971b0b2ede9d06bc5f6ba39d4551b587f09bf6f8206e8f1524f55714612581d6aa45d8fb83425f84a736576deeecafdcbfbb8670d14cd2ab2a7f8b7f374c07881b7bac2605fd5ff7ff7cf43e30cf49910961a9079c0343b8601be8c3e9fe38f49fdab0b7e1a8c1536cf84e4d80d26ae5ec37570839b5cda02929221898d611525c3a88fc444167ffc532b256cdd0a8f31ff08097d75b629fab99c9e1062d1d9962b211e15ec8709934029c4934e64db8d7a2f32e23dc541be306e9a57a3419115994cbc3a8f8d5ea2a6f45b9ea9ac0e51ed0c6680fa029f4552a6c8665aab00ab77928342e7284c321e9500ad4774ef1fed0f596d5aea371fe1793271aef38cde55547f34701a525526e83a72673385a85f44db511bc87ce1f831fc6ccf8204ca4f4a20eac09897aae93684f14ede21bcaf40a09c08012b92600d6a839ebdf8bdca7b34192c6c50bad8796b3be3c375dbae6217815d2c75cc878d39b4e842d4eaa5f5df2242cf230e44a240e18e47827f089b18bf880fd41a2516eac8e6ba3fc2db64a4bc28789860d7b18d9edeae8b3059f4d945b15d0ee27b1f74842dd1df117fe83a8fdade23a47c93902eedc4d33f2dbfcd1996e6dc1458409fde2302830e8d44c58c5ae67486b9950dd938f14c38bc4c9484fdc4ded93a0f90875773453fc14d428cd6e7beb0c705d61229d2b3df09632ebb30b325fefe2aebbf2a7aa8e4ad46277ca4b8b078818b63d04e7652057f6cbbab7c43ac355537e0d3918b4a73c00dbe6b30a27ee7a6fa213d3347ae478e8edc323404b8322b9c7b0173ed61c38ed25f3576a675d527d22edd51d6dfa5767560d3a50a91226338e8c4e6436eedbcd3d2efe9dc1e686b15d2f57d553abcfda57dc316ca453a690f20148f0dfa20c1c4a58240aaf7195095fedfa56d839d0230d55ce9a8ca1b9d1acd6fe98d583148ba0f4a4e3413c76e6ec57ddb79428d3a90079f64d3321c791f60d501c3fd02c8403f0f5e6c6836bbc96430c1b48e83350c3a3cfd017f15bee3e4bb1295d821dc98b85ab3145555cce2c34a8142fe50f8db19918b514a165d12ff6301fb2296788760ac0b6d9e3a57770ad5111cde5d24b6321918cb0b0887a282b827a8749733171914b000e7d3c0edad1d42ca60da37f0698554bb2a1749f73b3120dbeaa32951f8217a781a200467d5b569d16f56fc9b7dff0ac524f03fee0617f4c692d94613b1e13b18075dc9f0d32811d4a8949a95f6b5fa46aeb83597adb409e68b2a0177c36dcc95dcb2e7dd4fb7337ff97c013364fe139e185014948fa698741d822044fa3f6978b16afd18138c845587c405ebf7a6cd1c28610ce67e992ed49e406658a0a202feed9709500d064b6f53eecfca57dd4b38363ce3aae9d59126d8ae7e140a373851188ae28c909181d0ac64770df70dd2475809350cb367825b59d521d5e457b4e36aea6dedd90a2266898b753b57fa359d43cd388e7d6c7ed90bc4c2af34ceafe88a3af6ac376fec35f1240f08af4f3eb30bc53dd68e5762e6d39e6b16f63003fbe0bee828d0d7adc58c41e857c2c44702215b202701fc696eae021af19c79e59c3e32627cd571f5db99b17f1772b5d746196befabb0b7446687827f3315b391d5dff069b1c39c00bb143218ef458e3b397e1c99640d57fc8db2e0083d3d22ed4111a8fc9e0e6f55fe6a56e946dbee43909bdd7d516fdf756ed8099ba80b1e17a5e279119345104379a36962ca9c8b2a53c414d79eb09fe79862ca749a9eabd9185ad1df57215945882f5894868a134bfc35c835e040e77ecf077d6a98a73ee022963d70b036be3fe5718280ae52c5d751211b22950c0597aaedd35af41f7dd5999e5f7ee34a37edcf97df54a46742b0252b196eaee454ff0c30685b15f8de087de208906be1d971f0fd89f7cdff2af0bdc96759d6889fba9ef092ad1c8deab0404562a7f3977d211c28dfd1573aebd5427a8773f03986101703fa19cd4ab96a381c76a747f63b63f7a9a3a08e251cdc593a024f63b443b76d17dd9e151809da3c582fbd334fa6dd0221b6d410c6a78ba95bb0154bb8999f619f2e084a6b9755ceee4ca3c7e0481a47776c8814f13054e627e37630d593bd09d5f10a049c66c9999f4b0b037e81ef70615d674c7c7975972994a053c069675fad3fae5ae3e779233b70254fb87f25d44c104afc3d5911b8b695173f9337130e39a02cf97356cb817f6cd23f55ef74dd06bd24ce5887a7001ef576262ffaa99f9bb5e3f55bda2aa0f199115909af48bb4d6b1a0a0847774515302cafebe75aad1f63362b1f38141e8721851c3ef1a247931b3b450581eb5d09027b9e3ba60ae9801d629b74991b7fd65520eac561d47115a85141d9a757bc75710bedff1630561ae05254ea541a7ff1846ed5e164834417556dd562c45543c88d8030bb56451fd5b3cbf10fb0164c5288789d2aac7e7a836e79bc3dd401a8e3e05aa6714ffb2dfddb3037c35fa1ebed62a073b2da42133f2620ae88de5e3f46cc69f2b9b3c9b88e39b8b108059ac6bd493be5f7a39f6b53ee825f4593b77ec9238f5ab804d533f48803e7d8187291ee25cfac4da5d8c9279517adfb09c422f6d704711726c73828a5082b4c7b3d85611b8f496d3e0f78c5c4f1dd1c722b1b11d55861f232beee6aaef8a00fd2eeeb45f182af191ca6de8eaa25ceda5451416fbf6d1abc0670b8c10e2815076f271044c690bdcb64856b91265bac202043a28f6bbeb807535aad4bd89e572a9427c826b170d3862f4cca70ddffb4769d6593a1cc6c42fd06cf68642835fe474a23e6f63df316f8361bab959b768d78e20c03c2a99913c162a9662bd9981eee55922f36792de0af68da04ab49dca72e3d9b0de79df828b433bcf6be073f851a36418c03a717d54d48c1014ccb793577c8393b7cb53cad6bc7060a54cc6363734f6ad388763519ca09b533078d3cfa61d7bdd4c4dd0ffe64d68d501b55903d3f4a1f310a3826ac2ca700de01d656188dcf577fd1b63e305614b8d13471f6f84a5d4b12c5e119870a63d1e3dbd39d3b5c26b09f9d80f8a59ce836b20bc933496923d278a022c00f3aac204d07d2e5075bbcef1e4820d633a3a2b35974f72a033484a91a1d6a9913239c93e5783b01833073c98f358e3465efd5087af37ad60b7285550e776d67ea7019e788776c5a456102358c32eb4e7c28096af88b9a20d8ce379ba3928a10ffd539c106f4927e7ac0f382c74017d6e4438fb128c660affd45e9bb68452de72b574eeffe3ce239d0718908c3800bc7e8ecd2fc7d9754171506017fd7868594c9373a96579fed475a28811649ce5dc8a3107bd0d8578748878ce4998684620931dc3981a2499568c2f61174c3b3fc46a7010468e8ff75c08cd43ac764d95e2ad1659f9db62e9554f811e0f43bb74779d923c8c243d12a5314d3c0c6ec84fe60e1d2b2e2b20d3e64054d62049ef9233ff55223a319c285e4e3f4c98dc95b2ca81230d7fed9bb99fd7d97430eb32c9c11647992bd85dcb47cfd58ea3e221d095bcf9374a6baa7c8333581f62b9e489282483023fdd18451f09bec764146b587209160b3d1d7a3d2e145fdb640c4bc382541e0d84255122d51a710887ebe1ccf29d41b4dd7fd7368d68ada250d3968d6f0971f0849c13c09abadb9db8b08960a18f84f0346ea0aa71227afa55b90cabc062d549b616400d36450b19adb67d7358e48c043fa1135abfca89374c906f8d1a6a845debf6b37f055d390b029c7f4524958bdf8d7e2755dde3b957f0926f9d3b8821ba96044d3cad2d637b973bfb657fcc06ff44c17965acf572ab7a0c87604c7dd1cfd136a0ad02b22e8ef320e101ea09772588e8c5b4d88f40fe1be18d27146a2b9559491949671700cebff9a709f297c2621ca9d5d1749623abc20a326ff5be55cb9435c03bf49b147b1e0a4a918bfdc3642df90b396a474f81d75c953d87b3f3b4e31fced630bd7c481c63acbb84dd31249101ac5277a36dcdfc80d8d9a2e928e9b2d65bb257bce97ccda83b187da8a7886dc96eab93d0864d88c358105f9cfe1ad0f0a8508b5b3985ff95de652e684da970b57669aa3fdfbe590a631522abe8246393639709a9a6cd549e78e3c2d1acf84643e9f554c5e076f75a5c1dce1be20a66722d0b896837b7036509ab8d473d5d2b7a8374d6a575f69d54afe3e7e18f4faf4e917be8a74e55c271b96d966e0c0b883f84b3ef2e4f278daeda2efd3ce770801d2c4bda5eb9b646deeab9fa55324e917e63e4eb6aeb4176cb4e43af3db61aea1546fbf16e76a12fcdbe726b565710e3f9866551023e5fbac0038678717e6ab4d3e92dcc53049e8cb65c00216d31a8869ff4d3539313fe2fd7ce0f53b255e3659e7dfc5f92b7627dd9ba42972f0ba72b888932d870ab97226040c4c0f4826be131fe1d2cdc21005ec2addd7796f0927501251ab26b0e5f3f9d2a1cb346a774e18bc233cc89aa69f5f70e3d5c17098eed350ec419c82837153b5c7f5813bf5918defc8df143063f3fe45125deded2b15892d5cebce589b60f2ada0f9d608983e8d107d8e6482b5f542c6650b014445e8c055aac142f16cfc59229fc9626f7aaa40cefacef777e494e13dfa93d27c201788ca9f60e572af8d65ffb513473dade5fe494cbf7377bd1ed03db2571d65af3be4b0bf27c1f069797bfb67ef0bd8a88c6286af6712c106df9c418d88054e3b46c88296a2e63894d6bee0dda8833c373d6a1b27637e1510fea3eb2fb34ae27354571369653a282a8d19f2c34f9e5ec34555b4ed24327dc5d246df13736bd41021697104f80c85bd0ae920e9aeb4e628fb8aec269d55858df149af298b06d61250b043c8a14a15f0646d0aaa18109d031c449e66dd7336044dbdec912b1bb615fae2a3df480bd64cbed74be65c8f1acac247e80bbaeb6f9dab38c6addf4f3b094d5934ef5c9749053b9159e280034e601731a12d6688ff27ee3581ae289de424d16676fb750d2ccd5b3f964dd77bdefc15bb204e2350632822384cc194cf9130f1ee81bfc3887d3366ec0b48cbbe0fe674281ae7445f03791887873659825680448f162452cef57d783821a73047078a8cf94c416850092ac772ef0b2e48517ef101ee0681b5259aa27fd56edf3c01e6dba6298ccc91b09bb304b637eccf8c673b816e74bd7f8ceffa6b17ab03df7ee9ca4098d24d044015a07df782a309cb6761528272632a6e1323c4e18284b463dfcabed708e4fc95cef133865cdbec8bfdde100621c65a92762cc3141ff37b66dea8fa6e3aad61dcbf3b512467c4773d36e58989e12a636389c1678c191137a5f7f59668c8a527dddcdd0c3fbb14cf48b8f3ea306850a5eda76c57aad06312d7bbfc18969d7b611f512358a7bdf959cc2f41de1c408133ef02b1fb2cdf8efe9973c27536434e56fc1bb4880db7fe901087b53ef3c0de18aafa47c25f1cd62c362f2e5da41c2dbff0e13adaba26c1e0829f027dc0320442e851eaed9507b70ac17180725349f6ea7b59bf39c095a9d10790e87221c7c2d24b8bca184ee95a3ef7449aad6c1d905f688498ae7a0cd1b01f76dabc342fb2be0295ca1484bece3c9b8a1b91e53de2d2587f3607a7f348f5cbefaa7a6dcf61bbbcae9444e2d25a77b016cbd1508c8cd319e9812b43b0bbca52df155d418dacb6ab1360a9e605fb53c6e20588a10bef42d884989e836b2ff16fbcdd2c1704f75dc8c1ac2cc6aeb92726f5d46e4784c70e1e249c102be6da506e5e3c2cef6a8bc4a60dac7adf3cacca8679f8f792ddc27613e44a70fd849b7617e042da46d65a3e6cf425f59b83cbae5b6e911142abd13a0a8cdf06d041435ee20e2ca417e905d2dc49c15b863ae5920ff7f9380a86bb0c86b69a000c157cd35245bf71f9dfdefbd1760af90ec3e554ebc511aebf650633221ca9157226f613f41406872765f8d7b916ff3877266f017b8d840dca0697ec3dffce7912ea9eafb62cc2f2d0a112c9bc0727444b47b62766bddf5b5f26d391f653b6894b069069979d0cf8cc7fc4143626a8420bc0a3866db3860096cc128d620ceff059d1614487004adbdf6b0c4428ac8897dcf16e6b11a692a6b465a92b40010f3480b444d4d2e24b0af8467666905c2a6233bdd6502521b621d3cdd4a5e1f268d65bf6a1879608ffd3abf635c5f0948f3cec7e087485c72b00258ba69783cfe7d611bc41c27814ef5674185791dbe626e1f276cf2c399a4eb264f19c77ee95d94252f546528f629188318e9ede65a927aafd2f2af56ff32c0ef39862d2f92268bc9400afa8ddeff591f3ef99681263a33b873bd9e01a59c8b281da30875245cbffee5268563c7f6f20b9e22d998934131dd219624d3cef6df2f3d2d6401833f72c619d6f763837141dbf93179d0f01375581ebe227185166aa7988eb9fd453d510ca6616cc013d551d23a33a4241e85aac3201284344977d496d768f5d920c5670b1d8bb608efc1b99abd261afb0a4ebe191605cc5c2e20523a13b3b94dd1fb24a27009d9a5b6329336f3516a327642386ba64c8769da1324a8a3d1f304cf0700df2b3e38215a954523e1d40ae96d0046e2929a815bf70785e94bc9b89246ab6aded60d65170eeb49b0ee0a57ee2e57db92409105c25f2d0c1a17b5556d06511bd0991a426258372c7f2b402dd533a75aa175524eb5d6b9575300b81fdb2258bd74429add8aa477bd1182db57107d411d16147defc3582861c68f5ce82e0a0316edd5d0f3cf36825a2c79a33e376cce2e63274b3b41bcbdd755845ad9ed2a3bdacb6fa3fa9484b7b60edeb1d9ef84772e78e39adca14c9fa0bb3ad1f1c17fb9449270e9b4c97b5b320839947fc73853fc58304ee9c9e86f3775f5469554d5006eb7ce9d02d5f900c771806c275ee7022e2b55d111338dd93ad51d14008df4c13d8c03fd9bb3689607e5cbdd499c3a372b487af74cb140f6300cd2dc2acda07277ea3dab57ecf09f1a8f2d6abf7c44fcdaa6dcb1f6e791164004b20b3b4c860f409c1483c7044b6fa445f7224606894e386ba08057a387b48920d4de203b1acc4dbe2b0b4cbdc3f7d7bbb097abbf81e01db09e120eab83def925a059cdb513efe6bc93f0579ebf75638df3c3d7f9eba3c36a169e9d88495c452888853640d93ee70f254f86e2d2d3fbb5e8883b36fbd2da105cf3a75cfe998068203186bb37f1d1ebead8ce1f9383b816f1da2fd0a9e01377b6ebfed4f05bec08b4ff9b90e385736fd13a3af7980c21b0dab58decea8e9545af5d0fb11bb51aeda2c8616960e8f6f84e6c2fc4f50d7e413afe030f75475509fbcf49cbe14445d267994fd3f38f41a1339f2895c0b2969a9bf9c59b85e629486c7bb5107c7a6b069793be7690f7a7c96c93b09a9d610594a156ab27a32d5557a5b1ec8920761cd2f559ad808dff3da64717ea5f10fba87b8ff2712ce322eb3c288939e0007f779a3920f45fdd533369f6f85a8cce21f91552fe03702ef81a926af0e402b418fbb25a6a3dad0ec18ec663126b3f48c341e2725abfeae865352d5ad275a9e3ca20393c64d118968023daac84bdc724a3c522d97a5878ed788cf8e44f80f8803d57584d8c8688cff24dd8c0e881b62d16ea30104d62007a4bec051da7fdc95d1df8556ebdf607383a0825ae503e24661ceb8ba773b793360c3f4ed3b761bd372570cb17e7c2030f07b0b45a7974e45ee6fcf5bd7ae9e9abde5421b42cff6af0c6eb7fc73f4deb67bb4e0b3dc9b4008da30c67071243cda649091a14b89bdacf2ae98dd230e932d9b277d6968c65e0006a8ff63f283f2cd9c21615dfd82e0b24af6ff559c97922a3d112ff0ef4af9d6583bec1f84d1aa8bbae705b9bcf458f5d93059b90fc2217ab27d0072a38aec3229d13266beb3015ac2389a06dec3120c6c04e540886091597919da293a4a8c0812d6cd336d5c5faeb64162ec0459e252d219bed78c4b6bb61c1213939bb3cca12a625ce5a45001d7408f6d40fa9466377caa43afe961b5c1602679220258fae72a8de2ac69c0dc97c90c270e306dbd8eb681ba9c092896b19a8d42665b94ff4d5b8b188f19f7c44abc8f88d4ad7b5df1cce3465de377072c70dd20dbd6779336f05ce328ad741d1e4606dce7065347df111c7d3282c8a3fa4a9458561c04d1056cd53ec5a8ddd6bd4434ac910c69cea0443fd09ee32d1256da44ab7896867a0c97fe4faa4a53b6db5cbfe3812a6667f04cd318f3da127a0dd46170cfbaadfcca863e0d4240ebec1cb2a5952881fe89804892d36dc5bd6484cc78db41bed868ed1b321a680a293bc29c420cffb5305d15fba05c76c2138b986f799b6a3d061658e498204c2b641f2f2ba73d633538eef6b5a01117951eedb7611742c120ff24261bea605e94d21e452ddb9ad27af08ed972b7d5e1eae010ec5d83e4505f6a2b7d9a0bb32a1fbba32a2a8c7823e736a69f516b781fb5354be4b0a67343c009a09b8f656c34ab895f9213531fdeee911d677d1cbc5e72c0fd1ad1f3b4b8bc735e14c3f75f1828ea28c90cda40e0cbdc40dec37031ff3d50305d5a8bba1d53d2f176895e53faa3067129a5c97505799967e55e4e9d87faf5920d71055009fd060ad06691b78583f63881b566d4a06b639c55796b23531ea79c6de24092c0e6fb4d3dc739f6d82ee3ee39f229de4c844aba36432d6119be0d2f02e5f72ef1d95fb2494522a7221e18e92cf22e00010ffd93b89fe60b6895a37fca91aa2fefa8debdae3147fe4f01a6adbfa0a59a5203516b2cc7de5faf821a2e72d43beafa30ac379791ad1e5da3286abecfc7a546b80191b7b892cdd01c25e95506471f5eb74568257439aea03300e80699909cc06db2fd607f3279651f7392f80bf4fc61d66f0dfed7b7db09744139d7374d3cdd18d153dede2a65f26130506acc51d5c721a7989485a145dac9565ef6d3cc938c5a51f31ccc88bb0739920ef8f0a01145f4ddccc74790a22a3099a4b57e31b3a01b4118c9e6c393c1304cc51ca1784db5633eb96ccdc88f8b732815b92c9072dbeb61a2cc1e6b2e7098d883e6174f5af7bd4f129389250926e041ba94d1ac543aab6525f151294060791fd26b668d09302c3482c78e5f3271c0150c437b4e78b1cff6f2b8660dc310965f2df14a1f2ad45cd2759433c4f3952402fefd79fff00dd309c3f09a58600223441c11693cdeeaf0a6100d38d612a759a8e01f753982803af30c7470f7bfd1ccf2c08aa0b187382d25868a9fdf729da10bb0aa0e1cd9c6e695eb2c80c6b6ce62737c3e655246edbce5b8f7ae21c473762db0969dc216a93d4db239f67dea74a1de21d50336793d1ae45e931d975bc706ea718a2ab10d66a59d9d23f76969d870ac279611246ed3aab0f79e11611b312624d78b88a9d1a49dc68d6968f7428c33f0a7a65675826422f7ac058101d2f85663de331345b3a25cf76b7c8fe0988a13278be9599b8e4708526b44a70bc31ac5c278ab739e3e6f0927b72507f34b0034e7fdf43364c466bb75b559e03d4d18c864714eb6061f83a6331b3f59dd62f39bfc2529d5cc68bb6ce63db1075105cbd7d7c4d4ab68c9e65a32092e34e76c3178382a965f49386bd4aae307128242a2ffe3022fd7dc1a824b330b9f032d55573c2f004a6905178a2479ba8a2d5b3140ed5f3e10d986265d8b4cf262295658f301b4d36281611d9c61624928da9abc51ff9a6eb481310511772fcb1c1786203d25295e4a319b9c6d65ccc966b4c5795e6e30b2b3ae8246c38b4a911d1904145de63dbd4470fac47f8ee3eeb3f58b5e665c26a316362382ccc6bf8db7699fa3334cb2ce61c746a7d3af24d8030df6759835f5890b7dd1de538cac1dfe843ad06eba2e887f08d9a49b39246fb26eff5cacc937d63c8d0136f7a8ed2af4cf473f3f0d9064f97fb4fe9938d631f7cea3c617c38771553eddd606ab80bf792f34b44111933796fe1fb8bb104223a4de9e16e17321ea7f8de3306e75a2bc79aa5e9c0ec8dde9b3dd1f2ae42a6a278410afa8fb62c16282f1e3dc1e2f8c28d4538a75b5da7645101253dd43aaa150b273f73e505d490490314606264c737bb344b616a80a4931825043a740ea4f75847e98cc99c6880d3085787903e54c63e90b60f03192234ab20cb41c70c6e82b00e0575a1bb0b0f435831c9ceb9dacd1fab8a7328eb3e28533d5bfbeace430e21758cac204631bf033752f947f78ac2bbd9423c2baf4dea22fcc65c96c332ece9abb20fed504643e82f3ba0fff213635910789a2fe1f2cedef68799fcf4a86d63ab0ccd395d6d4f393f7ee8905eb77df32d97592fb34ac86dcf20cbe5afbf9e9cff37bc34d75af046a09a1781cbf51ee2e0b0f40096d85413a30de974c4d1d16ec06c0fad00716c4e10f8dae46ef3cf27ccde74502b657d3dd26b5481d9787f5c6034083ff88807896da55fd2c951a28f15c8c9e6c86ab50c369e5ba4f6311de505c07c7b85573b5a539785820c672557cee4b58dcda948fb51c95674c23f1275b423ee5bf3a646df19bb5dfa22747857fb5c605669f334d116710bd9f1495e242bf47d6b607c1c9d9c706ee770808484ba552c978ef64daabb642a7caddf5a55facba474b8a63577ac817dc57e48ab072bc6a2cc5f5ae96edc45af41c896cecd8acfc36604db3b7fed9d2d17d429f94bd2542b194a3d3405f46c1021ecf6bb907fdfb4b53fe445d5adb18501aa772c9ba75619214384260306ab68a5ab59161b
+Ciphertext = 66c03198b3422cf3fd8291080f6fb3ebd9ad863e41cdff169becde726946a342ffa0ee547a27bae28cc782d95a90b0a618f717e3beb577354bd91e00a7a57485588265ad2dd0ab946926fea7c754c42751ec7247ee84c17262c0ed092186ec57d6044f0ac9deb21da6714ec7452e441e687e138ff144ea95636286263685419afd35f002830765d810b6f60e8dee0e6879995e9272c798b067d5f99f49e460b86d67c641f48240b61a16dc7cc27b048e8b8e8e80016470ecd2fc4225e29bb127ab48dfe7e7d5a65542176dd7ad40c07ac8b92891d595bbd7afb63fb6f9e1c2aa2fc659aa101f9b6a5c346625acec86fccf17f0d45809f3b9ee81572e5627f1afeed4ba96c6d3ed7e9232358dec01a1231ae7b94ad4675239f3b456adccec439b3cdd45504c5475bbc77dfd242e5e9671d103ba71a4601a7322e0e295357f335fa8d5651d528dda66575d106308338993e615b1c5bd7e95bf3f755ff726b4ac6dd5a43ef061ac9783f8f2804c68f66486f5844969103a36278ee0d10798bf8a802d3fee3a31294bf00ee74f087749ab3325c027d42b55b197469a5312bdc5c9b316b20093154e66605941d58f4db8d46a815c06f209c1dce2363771b5a794dd8d17e93a2fa7b194c6a0b79793c06f002638e5e3052365221232cc4b30adf161cc6e7865cf02911e2ac9b0a75f000e7ef3aa4f3c7438433513da7246d421f208b179763651f18e22a793961e5976a74744696912f22915244fcfbefdc472baee0be1e591d6503f2d9511ee1eededd9f5547c95eb94de134d0c2186109935207a23b2b8420a5858d831ed78202be855cc6b98d6663c1c52e1a0022ed7ebe0eea6b107da4cf50c1c7fced9744a914a66d4604a081587ce4b7e0f96ed408b8a9a2964314b1334a123d5184889958e6467a6d16e7615e5364e09aab75994e2758345511113321a3436db79351c63a282095ec6b99b6d775a5c09ea3f3225716e39e14df260bdefb2ecfe9a65c73ab4b3712ec842e43ccdfb535e3685fa39b4912719e67bbe195e5f0fe6c3aaada2d81b669c4565921f6c183d708b50c3f7172ba841815e9351fe5fbfe2fb1fabeb7cec9bd1dcf2d6332372f1b972b5144aa7ed6c5a985132f9a54469097e2e981b9e75a7df48fa79d0736c6f8a201c7c7d0ac8ac6512a7089514bf58442dbae0529135a7f2455e0ee5716c6610bd7600b3159197bcb20ca055695a36597bf7d3b18ecd08031b4ce3a643951e231c7ad15481e32ed7a3edd2b379c8e96d3288d5b93b562972a04f1b7e0abcc5090cb8655422cf5e9dac0b49678138faec81c78f113255eaa6110e95406a7e7417a6e221a8ec7fb9d55643bd589ace2da70fcb41722e66e0efce932cd7a34218375b6dfa3df1747953b24a41f94e50b84bad4d130d5dab4194665338e06f102f46badc5dad7aa06edb01f8a31244dceebe5e2006d6ab4a31582ff46731b19071c08ad1db79ba018687f3e6afbe703b1de26c11bc8b62fd6b2fa3219fa7190379504820abc97ff6c034f7850e2c7fd335462725db6748fe45920c213c539356b691f22eb490faca24e99f0a044a9f727d0786566ad00635983692ef324bbf1f80c42b269e9d5a8df3249873c51521c81400c729ed7a5e73995928abe94d189cddf2774f1735bc2060bb2240e558699c365dee45fa68801e6a1745e03736ced1b89fc2755565e3b36c2102594d43c451122d94f4a263664bd26b2fb5bc7700319f6b08796864f92d0fdb41710910bbc13aa9cc7baac3b48a24e4f3573f315448c317c149ddb433d9ddd2a2f0cfc81c22d3dab31f184975355b41e4b36fd8f22e8efa01d61a5cbb0e4fcdd273cdf68ac73fee745faff44d44d93c5a111aefe4a5ca8e8e7c075ffdb738cc5b6466dff78ddd837c72c54941707b04d60bc126a3a2fae9540ec2e4672ae13de0d927a7bd363f8abb5a56364d6d564df90a46df9fd59e2c54d5bcb8280415257a6976d8fb24c33330af32600cd1559e0eb05d55b34be456d434bca98252fa531486ce2a24c8bdea1d57d93a550ec586920903a39ca61cbfbce79b8f3a5b1653794872b2c614458177e748f8dfd43840e5bb0d608c26389347673fd0b005f60f52c56731ee5faec6c8d0617fb53d5f2415c2e7906ea0e6d0066354b213b3e94f4dfc311e4ec6afa7e8d1c69a63cccf8326741456a5e0bd0a359b7a37c117f7892969ad7b70cba9bea0a975ada7cf67e0d7255be8d2c6e7b8788b9ff14c5d1449d6173e07b5f9d94560d46f474ab2a67056fe9f4a9fd617a617d23143adb4e7ea35f2d5cc1398fb9ed43ddcd10f28debb27eb13533110005e6c78ca4a874db68c65081ecb8bff1b64eb1e2d7b76a1da3b375dce8a92d32a6277ed847879345717b9649f27e846a701549311c7e69a96d61df616157a114bdf1663ad93a26c28e1a62ee4a7c72bccb9785639eaf1e569decf777bb0548ad9ee36788cfa1150eee3ca3c96f09052ba2300cfb7526b9424b6f7418c27a1e9bc13e4d9868e5c330c051c3885e44714bddf7cb090fbd0f36b826aacbe191dc8c35c219e19fe736198c29dc4fa1a98b5fb1805dc29ecd02f74d4510a3928448b5ee61b5991e46644850a4885bb1ee272883faf27962430de1922d0883e7e80215cf5fe7e8f3fd0e2a49bd50727af793cb7e5b40860e80a1fbb9d5b5696bdf2f741909ab5a713de47716332df6c4f78288edcd6ea130d895fdb2f29f94635bbf2061de55f1801bd6a24294aa199d78021a1ba771c651de4bc08f032fe6ad7a5caf6a6afc6de649b901f783a0ee0fea9b803beeb0f431400d0707f159d7dc29c0c334a918fa08a653137a4a8bc86066c8800e1d171f1dbddf1fab8a3eff6b5023da96f002e7e217e826fa378b15dc8a376db30228f5d6b629f331a162d63e53e5b5bd7ff9ec098b4314285908281930ff0a8aa86a6d89411e6b5bc6b9c9e931623ccca6741fd6d36311e6a8e323a37ad40b7a2797b84694e736d9c135e52d149c760e727598726378cd674b0f4df1c361de0a12a2b8232e611d789bfbea699e8e77b99f3449609caff3d6ef7233df8cfc624376c905eea46c6f77c0b01d288868a19db77e227dbb5bfea5cc3f49d219c7477f7f2b3447b0b8efe08eab8f69579d727555e547c13ec7ae13b83386f2adf634140c311b6e2759cfb9c8aca1c32bb7c002d0f46ecc526916589a29e328ded9679c2163838f071b5b85b35e5e7d99c3c45d25bb9d37d7bafb8350ad4695a6e0cb7ea7d93868c30bb54e301e21147696b7dda156226a5ef8c62121e6b2cad0c4e192116192012468eaad46bea69a140aa3cb9056dec87c911636a1e55695b9e5a27c63cd8c03f31570d4b7507d13731ea31f082b33c6db8dd6e22282f9790be41350a96abfc4dc3de78e0a698930f540dbda3fee923a463a4c4a66bf00bb2cdd6d22b62a47af96b78b1f0f0a174e4ec5b785b3820f47d3c8cc1691d4751ce4e4ab78a4551956158a36717dc35488e890d0631241906db565603205e054815aaaaf17945c3372dfc7193369871e2e88fb84c15a2b9071101e1208177fc18397e6af17b5843e1fa75392d8d3ed214975d50f2b19c24e83f010f8c394ec1edbb1cb912e61627d2760b0e630b986bba2ae113b8f3b51ba00ddc495520274a85e6f6fa7573ac4ec6e2a86a1da9199ceb007aa6f132e5ab8ab8fdca7c829f452ff17524fec475b8f485b29fc6f0d972eea4ce98e242b5d58f6ddc1b3a71256de1c584c9914a3cf1e469f0033165d934fae68a7559011dac7a4e0c72e3b398fab8f8cc2fb67963b0f9220f410e5ba13026a27288a1d49edfaa51e8f220503fb5ec476147cbea975994fffde3ddc51bb189c470078978d238f5287fb2629d23989875d74b006a4122f6a342c996d4a244e8c5e4b804a44c301ac4d6054181a07964b279e0a44c158364395a2ead40053d2f3350ea0529a57552ed835513f533ee0c4b94ef674f31851616a4fa2d0302d13cd4aabf5f96ce28219c0b5bc0e5410fe0fa387ba1009a6f2280f9e7bbe20c33be5eb411a5f6327714b3443b4152cbc54c4012473237dd98b0490fc4228ded74afc81be2a58a22e03ca987faef5310e474f4f5a183f6b7ebede5a8df8a0f94a87a41852826b29466fd761f40b416ad0f263dd34e5497867766a361af1654c3fcd6ee7e6bb3f72d64cc980f04305b63bd574f116d1aa35b4bd642cab0cde6a29139aaa163805c6c40384313d4ec6027c891023083988c1b0d2edbdd9b1afe102fbda285a6f897efff72a0d7fc19a3cb6756cfaa2371e13be3cd167cddb90d525cba7da69608b9995cef92a6424a14df6b860ef0f09830fd7189497a432347680de0f463c0aff82df8098cc4f7753f7680c8c7374d01046b05c63be73f3a1623be778fdb0bdb90d4fb4b458af2890d15f108b0927304c91c8d62cb148c35cc93797db3ef9bba1014d89859a91da0c0a971f330600d71565d30e9c9ea8c07e7f629e1a6d578da04d37e597261cae8ab7d9a952bbf71573f1bf70e064f36c032cc624e3c980e5ea46d36232d61a57fa598347b7fb6b28401e34628b051d6ca3dea190d1d3c343fcc83175f70f77a8fc5e8791b9788989df1e37cc4881648f4fc673772003079adae55c83cf02a894b98561e4a6e4416bea3df18d6f702ad5c4f40faedec6b53cfdb5b3a52d7d43b97ee23ccfa2d30c7264ec555b15f1d9e7e19cd9890a7e8e01ff21d3b8b451e50932f189a420d18e7c7e2f103332c78c84600e5e8fdedd84f055a8b39be9a52782d47c6205c0de41644b09c0931f2da269a7e58e669f3b61ebda28ab8e3f9b83ff3d2bce37864af494860b2f01b000abeb737fbeaf8f9fa6378366606dcd0fc33031b94f9a7a0e562c08ea720a671ff92520047f69b138b4e032c3828874ec4c29e49aab302089956566372b20c0216b601c3958ed9691bbd89f1df45c6613d469e3b9758a70c860fddf768b10a6bf70237a454a2c0b70dd5d02da612a91fc5731513012a4a6fbc16d01550bdfdccaeca22bba104ccf6aeb19f21d4cdd3da231af8ec5bf2a726ee9cc7c85b8ed46d2f6fa4f1b010b2561fb69690d5a9df76d729450a6e139962bdaa2bec0254c5a252b97e7ce7eab1817f454c6121130952b8c40628065dc9b77b0f953552f5aa3ff983b6a51a51dd87c2b51a18e14adb8c80e002d0b47c61cb357babbbe3ed51d371941a8f111837ecf0e45020cb941de170c4a1b5e61bb928b1b11a8d902febd2ba016771f171b8a7ae825fcc4642d95649d53675d0027822e4ff79ffd302bfab1a0ff26f3648c7ab00c10f8d95f21e40ca2b40691bd4be79bb9ccc0bf760a05be4728bbc0a64e585207d1d09393a80d5f574442d6a933966777ab05f699c4e84aabbf753059287e7261d972745906a4fd8967bfc80ae9b6ec2ee1b22a81775f4f24999987365ae2dfb6739902ed51b9a4394fdf29f216c34567102d9db301661b09b728a79e377cf4bdfcf5c83b110a2e267abf6d40947e643ae2ff0c244af168c9f33e7685474ac30611ef95f218e0dd280899a92a41e7a759d03ce3709c2a140ebd35e199f1dbb96f7351cbe1f3de8da8c49758a49b9e724ebd3220ed6f51112944f70c0d1e9178f68a2c9476a913de00abbd1f5bcffa646f926da77a9e9fbdf81cdeaf7f9b13e843afefbca81c93614f8f1675325965b5836b8a77620a5ff162e25366718d8da7781e1a7e01fe2e9e56cf958c6273473abf5c2c8c7fb209307544e1c0726d5571e521621b18b6da3064b473423536b1b76ed75b21b4ee205d7ab5f081bada63062706bd155672dccf84614210d72660095437c6bc2213d9c904a4ba1bfda14d350fa3dce7141e817a50859b1a74aa64560b2ebc67add9f945b6e85577589817078c8ae54a9fc311593d2cbdb6692b089ee6264cebcc7719753f80e30dbe48b64fcfd1037fb9ddab69a5ff9e5898bd8aa947d9ad827c26df67c6786edcacb3478a20bded1ad8c48018ae0d439bb5afad5d39bb8fbaf22d72ffd759c4fa2e94a5a89f41358ebdc4c3aea5110f1965a049fdadff9cf703eabe9628e2680fa4e70320d304ecaed13f513f27220db1916ca1500f1c2e091671fb71329dec0bd6e310c83e67af61b8ab60ee1a8d559a508d174648b1bca451ef0ab0ee2ef74f4fcfaad1cc5ea6cadb8f1bffcb1f2c05122011ebbf6abc16838e452fc47653821589da4cb5bbac10deeea3ba0e0a6241338e64cc78d7a923d018e8b5b51c4442070e5b0e6f1e8c2b83791e930899c5897a602c401c1b85827962ff56d19c06f5af033059bc7fb1bd29b65f66aa5b4397834e846935e523b16438a42c1f990ebe4f83182163ca5fc60a4c6d77fc182e81fcda943a962e9e7f00f6399728b48bbe38d8178fae3582c8d9998e49df5f28e32d541636df3cdc8ac00df45db12da2e5e76f366c1ea8667ba5f3542d21f58ead7c55d06a4b35251b8f77dd34d3de262947379107a06d2f4891ffa0ad3a3e5bb2bbbb978af4953310d4cbe5525ab344ebb98ed24d003600de8f3af36ff3d0a7efeada963845d573685bec2221403b994f97b1e714fd7dccc300b62c2a516e9c6780983062eddde0178e93fcbb2ed4f06f60767356a11d22ca37078fda1ddb3cb907d1020f62ba85d09044574ba28aa3df36988eb8a41e4305e5b0687abe43a90e4f68f0374b6b05049aff5b065d7688cbbfb0e96ab03df38903bfa1c269f43a114085eb4596aec87ced88701b42f0b7426389727308bf10aee9d8f15ebdc411ce1e764a290a12faa2d7c1126dc7b5076f219b826ac8d380b69af7f95d69fc3929a97f5c7da1db6270e9ee1f2a5f7fa3a1b6bfcca00463655121f681d3a627d03efdf0b5fd045fb153bc4488a9a8b7264373c710ebfdb1c267fdca37723b21d5c3eaef48e784bd76e27c133cbc24d114f610c79f2a1f2c30d87ddba395887030b65097ca5566eb0361e70615b46d4b86c2759f1cc2efa3915b4cebdf51a745fb3c6cec69a1fda2ec5e884dce228e30af362815d2d8b59a14f89606bc77439042109369a9648db7d71024ed6df06c8ebd22e8623f48feea77f48b5e88827fafa84b0564151a5997b7f29c4d3d18068e34f2690a293d54003d0ea8f3bab9387ca72212cedb5f4602ad047dbffae2ab3a4cd2865bf896cd96f78b90e4017eb7e3c7092320c0a37f81dd65a5c4817a4e7053e6d2bcb23b11e09f681587f3a9361e974ad54b88c72c296629b1ab754d25be15e87c414cff975fafb3d7cb68167b21f1889685a48966705222b525fa47143b00041df94817c275d93c2550fdd82471cb3cc1b5644338060b767e807bca902c180b3e535c77be2651b3962287b6d1f6403033de4e0aa3a20615ab59d290f4b167325959c1524ef216dda2ffce86b50cb6b56b62a20a043d9d78c704479c22340151df5a1907670f8d4f8c90d93f7b5d94d04a4d383914867aa3c0e5ac85fc299a4d2801a3f80f4b0f046fb62c1c8c539a83b21c7549df0afe200537b52c80ebdbad8a438e430cf876cbbfee9ceb1bc5270577c27d53b40ac153cab377a565b1a9fbdee8bf8e94839c0fc04f7f664383bc90d56ccd1cc01b465c250b158b5e6f321c20db245602d10aab80c553d52f17282b095b5e2234c6c689a84b096112100359816cef7e92029fdfc048058f847cd2f2369ceec9fd171a0487bd7acfed6b0319832df6d59affbfd460ce8d12e4171da0f094e872a2888fe74925c5ef0621c4edad337f7006086748913b24d4d48ce36e662fefbe672b6d476456b1fbac6d80030ab93da93acb4a7e10f955547e7e20a0abcdbf909f05a2ee2e0b7485fa16be652b9d9fbfbf01f082488a81022bdb69af9e6fbe753e9eb92a1762afbb4df49f83ffc0cf03db563aa96fc5ba1af6d4d7eede6067749e8ecec79b63e09742e29e99e1c960dfb0688b0222c49ed919379ac66e3fa1c72645122d1664721e78fefdd1224c0b886f6e214e37d268ca9acab76ab3adc9f5549e5dcdbb3d31ac34ac472894d004eed71f88ca2377fcfa48d3ae43805dc612891dadd06c263ed8617194f890bcbb964f010d277ddce1f6682e661577ecd51a4d5421f00935a5b24fef0ea1809fa5c4fe9cf8c453046f61136ec8872915d2462157d73a205d56d77bb83cf16b88cadf6430c0e5397fae1f91a6a11b177bf04b065a2e55df81d5c086ec8dc8a0a660eed37d41fe4d8b3e3f22238e2a63b6e4feee1fe9a140ed37b2be4193f75c2d038aac7f6b7dad2a3b37e5b9b660615ec1db77a9b7ab416f43e66c872b71cb67c9245c757dc87723ab3b9544fdd8a16c9486e8ec3c4a44cefd98535d6e5683426c1cc8c888b8e0c2e7528bd7eb89b80d9e00969efd2f0a0fb09845426edf0d1d9a0809648e7e46ea0a8c9988bf9df475be12a72c7326c1f2bf01afafb190cf6f649133c7dc14ecf9b8c971135bd303c8894bac637e08257d45e1b68edf550d896c41682c002396e8f1eb7c1e2f4e0ed9b8b7010fc7847e6fb1c5907c17b2d2b7cd24c96f47406bd04cfcb2099d82dc2902d6f91e2f8f3a05bc62019af536309e7847fc06c10dbf7272a1509079fd16bb16a85ae2e078f97f9ce66bba66d6329c7ee70f9688f6d91aa38b25c7f4884658a72ad8cbf96d7d7a9652673273ee1b3d4d17780dfe9ca865416e318bdcbe9efd8e071fcb15ceb0743df5af4f7d598b31e38677e65af61c1109fdbb11fb11e3952e6c3ae8abc3f894ccdf205ae55dafce1dd05dca6b899877f57d712223dde4e7fdec7e0ed4f0a29ad359e318eb36ddb42fb205adca400f5b2615947c4f0ede95788093a1152d88acbbbb272750823151e245354e658452a95f21fef05bbfd98a10c1c975ad1a08c59fa3efa9fc73588407a83d0b26a53f1b4115f83780bc70ee2619d7374ca45b9e200055df1b93977e17aca89a009110a6e74caec7f86114f91975bc6e8bcdc7267ed2920cf12cd7137840628e1b8a0ea181dfef18dc5f74e752f842ea91bdce4b420ee709bca72c4514e92bcff55902e5529d77fd95f5837c8f4fffce80c813630550a0dde24092a25f65eba90790a06f4d4c3e739aaa8194a147fb32e81c71d3e8def79251c33637661b0a621a2a6b302dea00d34a9dbe9b621c1dabd0464e85241aa6712d90b4287cb23c17bf1e4d0e6dbed372e6b49c4a843305b3b0e5cab0b0964a93ad0bbc99ee711afa7f2d0a296a375fdb3176c65a957ddd9b88e9d57df736acdeb02a71b924cc2e972f51ba68a597215678573bede9ca5b3a0a2461b2d3b9ea57a5af8c91d40779bf917ded32f14a66d96e28e1415fea1e9306654c6b84d8a64243a5271c1f11590423c718961aecf5f659b49f67efa78e02ef2524d0966ebcc446d73d49ab7ec31f0c009069d14ccd63f926169291b83a3e37610054b0b964741e2ed8771d20bfa225eac0280b4d5af0c09d3218bd497a035536f5af0816884d606f1a872b8161a266466b56e0be8b80a7bde65ac706eea8cacf1749e5e71ff9fa3e69ce878427a0728d44e666eff977026abfe18cf3ad156a943b917e72ad65725a9a8d60b7b5740494fa63143a7f2a94fe6d8b319be55d6fe1a988244deb798f345f30dcafdb6af9e9cee9e35733274bdf3896750897371563ed2516c4ca6c3c3c994b48cc94b67e8129d234a0e19dabe39e500214c0ed5f0e5d61b2f58d7355d147102d93b2689bc5185dd4c0a18efd11a307b887d4d0fa84fd992731b3a80dbd027dd36cd6933766c537e8e9e27d35d5187e8276b0f59fbe7b6d629d3416b782e7981d85e1e890853c3aa94a93c1667a55044ae42badefab979fe7d525c6a180307c5ee3a9c3933038028c3e1d15d1e78fbf53b6ea61ac5e02db0161719398a31570c55f73cb47ddec8f99e3e14af5adb8d5cd179f4204d080331e75bd391b19d38eb81f148c36af3e8a3ebe76209bb75c9741a89b5d0708bb0fbb0945fc6fcd6ce142d19faf0947c338dbc8d976963281866b5216421c00cbd77c0907d1e16f5e925319cf6c62f8c6e8eff0c2f831c504e7a1c0df09a54e2af708ceef39ed7d0f63d83429e9b0920c03cf85c2244f2fbac3958847113bed577dbde8992cd91be5833c75faedd5e2005d4f7b66fab8fa9305927406f863d1795dfe04028940b765bd79de6972dc7094fe1c2503a73d7b50208835216c23aab3e47094587549fdd74bb50ae21cd1354daab632fd0907e63f4c2b2d39d7fdc4fc216bfa742b4608238623cb7fa01bd851c1e7ad5ef5215173a71f363fbb7dae8092486f4a1549e32ae53b14c1343ff7fb5e2b1487d9c594a1b56e22625d275e41535534d225b7b2c9deeb0d30dba7188cf75d680d4545ed05044a0661c690a37fa14a73ba8c68357e2c948e290b5d9a4b51822824614ef2938d19ea4b650041f59f3b548f0a305b86f55e69760f37f09dfdad62651aa5fd84eef28a4431136b34a49c9bf1f2891364f86b0aae70b0414e821e3db1533b0f1db5fd232308bf118f858aab5ae974c10583f61b283a3870eb82aaa8ea3c4e2ee3c3a3d7169aa8e975ddee7f620f6c5bcf3eaaef0101b62cd54495cb8809052c9e3151690cff7c1efcc4f63b22472111a7c5d9d7d2a2be951510f60dec8c426f14700c8630f8a14dfd359addf5d9b7ae031a745ecb4e17321b385799c90f924c4780287ac187530a40b064064b9036cc46e3f87c4d23aeeed1bc22a5411c7c503594d5d1261eb9fc4da242493beee9f671485a978a32e965faf9b0e2c13f78e31e1630b72d35b4be691e90b3798e18223c1b514b39a8e1eeb7897c22fdee1e33fc76e2b2f9298ad4fd89f44163aaab23d754d98c7890e58708b81b3832aee31aeca85e76416133710aeba0e5d9f17695e607d09ae3f94be191553bc39c6df03cefb4ee05516fc02d66c9866e4eb0d89a662e309379a347159db2e070abceee226f2b8b62847ef7c51d69c5f12eb567fa13af4b4f90b3f3d9d4b6a3f68bc4dd77075081e2e99833c18b154d0d6ac360141de2a25af61d551f10a34e03e1419a37409b4c177c51a8d248157b411868eb607c34d2daaa453a0954fade5eac45d5f21f50efba8bbc9c87ff0435c70f064b42cb2d158384fe0a4d9c90030ace7723af0a6c8faecd8f97f9850e2a489a94ebcc655301e2e14711de9eb08726638a9ddb57160c5545c152a26860a17dd18172bfac138a300f60431fc49eff18c93f71400e887f878f4dd637cf5df8c1e2b12c0f87e31ba2754ac1748479eda0c4184b528554106128320dcce349939e5e6cd3434f86dc7adfee28c008a21ddf9d0dbc87ceb14cc3afbef1e06fb3f9908a4b14f5e6c43b23ba783b75a6cbfa2ebac6533661b8c1143a34e8e2a9723389c4b7087dc07701c53b169894551084aedbb423bcce2f470881fdc7240c26b3b76fd6cfeebf8eb2828b4741e5e8698b19fa0a44703cb4e4c8ed6a7e4d6063f5fab724e08a159f4f04a2f351dcfb6335ae6697dbeca25c76b55e6ec9045eaaa8706902df492b8c8cfbf68c4cc1be5d1e5a173262e38bde051656ea85ffe35d97f1b25f6a47381bc327a946f7cbf6210adfd957b2921
+AAD = 85ddde4720659e80e25168585a354eb1e021c0b5d2ee289f2314dd5aae52bdf1fd44755bb56a6e659111a1d4b4da73315bde01c7d2c15a4f7114aefd68c141049fac27acfdca24e65c51fb1c27d307cd948e13af2963166bbc9411401d124f1ddf20f890db5611385257f52aa05c09b467e3ae886decf5744ec3749e5879f2a60017f601bbee11a66604d5f3d521d2c48cea1794f77366f29c7bd12a8aa51d34a4f3fb52809561b527016bc6badf9d136156c330e1d69d1aab98c7caa9cb46e782a898b4c66e4ee3e2445fbfacaadf9a8f73c4cbcb2a1ceb604ba5637b51337fcbe0fc366da98e805ceeb29feaf05420113b16e1005079c0e88af33f5970b3d7a8b51d0d9f5120a0795063db508171b75ed07705ac6d6bfe4ecc59243091d48865536515e036860affa880bfc91aae2fd1700de15994792aefc4a176e5d49d0f9135c7d670f3cb8798bfbe83fe73de7427e0f3e6a2df561cfa15ffe6ae80d5016096c8875b0beac8cee8fb530fb421b9a8ada4d551a528d0a0b521086f5a2db371a3bf12a2ef861f831fcb44cb2baede907a9306d3e5a3af796e0a50ba2c8dd61fb03727df5f0654d837dabee2fd90eecb7b2e8f303b0d57f97dc6a52d8281574d8457c89c6a9f5d80e0bd86c90ed39b1db4253affee614e8cf1ff05166c66e7d2a2aa2fe8a81c4741339683debe189c126e7f553a5f2dc16fc16672f74aebf94c7e3041c758fbc6d0c7f71c192cfd0fb2ec52d0a0705b05815d567f3d19f9b5d553a2adce9a79159b0e38980851bf64e97f896c028a6df8363cf1f13f4654265a7b0c0b24198efcf4418c32772bafd3980dbc689fab12e85b3ef4a491e2e5ffaa2fadaaf3deb392105a42380797d3b41ef61303a6016b269ec9a9f6e3f26070ff33cb467435ecb325dc7e18728a5c2e882e720c8f876fef10f5bffd5a925cdc9689d934272019e90e3a3bbf63a295f207faa5c014e1517c7d5c18c3ed70e92304d51944dcd3604c999d4aa8d8dbf2a4c69cbbc08635c968a20dcb80f438d43c57851c4cafec0b9568dd6c19932fd3f1294afd16f019f20e40ec87f6f5dffc7717470614b2de6e9000969e6b7e561cf91c06dd379a09c6c25c7841330dc78fc5be1d9b86581a81f55c0289531128638441fc98a1ad9472d74e2be2f874aff2fcf9c941502f59f716185a4c39289ca368c6dbf5257b5dc5e57a420792c26e602e4ecbc4f17c8787004eb88ea091d6b6ddc3c85dc110b5d1f46f6e1d872723176f4c73664ecb4219258fedce19ae22360354fa4894fe51d69434c2e58e1ec665b5cc33bb295053c591b474b6ae178c8834667bef971604279440170ebf3e739a4ff19704e5886767f81edce95a3dd93d1147995e7eb6c794b7be136658ed23cec7c374705ec0d8479dfb44cc7213076668e5fbe6a508537a9157815c6e5187b89f
+Tag = 469e3ef168a64945f76d7a2013f27b68
+
Cipher = AES-256-GCM
Key = 0000000000000000000000000000000000000000000000000000000000000000
IV = 000000000000000000000000
@@ -384,6 +392,14 @@ Ciphertext = cec189d0e8419b90fb16d555
Tag = 32893832a8d609224d77c2e56a922282
AAD =
+Cipher = AES-256-GCM
+Key = 53a6f0d9b8a81818f2fd7525acd65acbaac82684cda4fd357b1ceb6146b31ee4
+IV = 05d8a92b5a510c3a3dacbbc0
+Plaintext = ac0ae17d3d0ee5935e18675c36d9e43967f6da38dddec14c7ec574ff8473e11ae5019e638232323c175b7672a7462df6709f5014bbe12a1370a1ffb570177927106f995dc8f35bd6e6228de7c16acb71e583c87477dcc7b17a908ce01543496c2cab8a14a21c43b18fab52d8a882dd1d999b4275db34c7f32bcba624d128580d7566a2da4bcfcc4136d58816c437d21e90456fc86381b946b8955f0448e83564165a629cb2edb978e5941010ee9153b054ee429b315058334ad7899aacedbc0bf423de69f57c633b56033c6531dde29258694045c46a797987471ae6af8fee8ad0c1be4149605064aaebafd1c5592e61beca9b5c7771410a276c3ae517490735ddd6af499ff705b9fa68d50650e60c19f5ae2c88dbb6d612afc7be28a5f55556a2163b6f66609f7d9ba7e97c074ea39a618727421fbfbb6453ffeefa643decf11404764515d28fce8ba66b8c85d077c47a54125a38bcb6b0adf6d248ba0a9ea129c887c66ef537c45e9fd3c17ce352e3936cf139e13a5946a7dc9dcb6423ca6a051bf560cfc572ef366940e71c81aa302cb9701f9a5206e9eacfe9835bdacb6425d058022a27fe73e5edeeba98c7a3edb761578ab2ad5a442c2dc1cb3c143c6f18dbe525fedd2a9cee0ada3b2c116465c5cca9a7e5d4374b29aa4ad8adaff8d6b0d1ac3990685240ce022faaa07241f9ff445566b9e0463350792cadcafd5fdf5c37706c0025b3c627185b356d39dcb2244b15566e6e3f8942f730fd6d855daa1456fe294f9156c4b5131e5bde7f2d938ceb6c7f5deb0f847a98b7fd11a3f5d0163eef9bbeb83cfc96dd8eedd447901ff4d3a35c0ea1f691b01385eb39fd265f756bbd77bb61b1741db0502947b4b985382a08a5916da809a8afd3fb1d78d9e16f8e37f51aba100d031d9da8613e9cd2cc621025b47150b3e76775ab23412d74334bcd79746cf601407481310a923047ac68a4e6a7f7b96bcd85bb6f24e38f03c80ad41a0a581b4246ea4715ee561cdc5384a51a6fc9ed8569ba6b12bcd95e6202ecf834dd9062ec539cc8cc4ed64ab9ff85998da0e63161e7391b14de47dfde41523b6c614618bf2fd1edd68a5de1c03c4181569b6c361d955c637abbf4efdb5dbf2f0dd2544329c44b77081a48f53231fa9d4cf6f2186427e469d0cfbcd698f7e7cf773240dd2b807a2fe699f0ceb4a2339e9cde01114b2aa5c3591a82a3a27b308e1e7f092af8ad97bbe7b28d78ecd80c0c0a28372193d66bdbadc0b58e4d5408acace53bd5e12101fcb25754f8c545340fbbd1328287044a29d18f40a24b4084febebe228b67cefd970df6d44ffdc033a50534e5977bda660c589c6e3c3a28b4c500b29ff4a1c3eaefb068784a29914ecab7868a43999833b0b37ae79afe58875a0425262e0ec7e10ee8a6bc1c97d332bc2a6195de239a166486a3c1ad8de3a026e5b1757f9a778a511024a260c9809ae3b22d78f18ac483281a796b1ccbfe7a9b9f357d12d340e20bdf2037e8bb91ef858cdf2eb9d7161a756d8c244c55524f8f5be2e4f18641bc4c2409c14816846c4655be716276d8356e516640da49e8412fcfc7ac0e084a079129b23e54952d8030e1f8ceaafcd322dfb4bd189bb5d940ac83231de0585783387d0642a245183f7a251779bdb12c63e9edbf3d0c94281140598fea9e73e951ce650c984cfb1398f8813abf8f8827af5eb64a65dfd1305bccc45086438ac439a9265790fb225c509ce3c9d39e25d2276d7f3c06d7cc28d33b2c21bb38b50dca5b10afc09da83ba12ee878e0f6054e8d3e78d731671de4f9d5a7b97298b01f37c7e78e5fcf5188554bcf5d42559d3b15153bb3cd5a0d1cc4a96d02ae8b1b115d1ff617b6ad894ce0585f46a2a5f4cc1b83065c1d7b5d2f25f3f4bf9966b4c7d7156931861d5edd199c126f1ee4ff6345023419d0a4c87f3388fcfbecbb6c1e2f4745922b88085d21d4551e4c127eb423db87a51c9f9a140f8a7415dbd70c4b0173e687a40f895404f2203e14ccd61e0e5b0d5aa3fbd1c8affb5807d787d840916ece24c56c50d3d9ed9f19d73f2c80c461b5b3c07dedcdb41402c3826a958d74be48382dc741dcf3e0eb8955397da33941fc47288147736d778914a57effbafccd4cf293e6ed1c7d19b55433bc0363e41546b3638a4c630eb35dc6a074f90185cb9daaa6eab54825a4daf76f49ad918e90e5777a826d6d5d52f32f7ceaf818f87251ab4d1b5406ae94e41cc97fe022b144f26335829d9c81725b3daead621a0df71313d18214ff8dc687a7ab86b8eec3070ee1ca9f62005a0cc15ca6e2f4fd893de8fd91f6210f6c96a576024678535c962a2dab06f56be377dfa74bca089adb7327abd05c3ad7646b5e9e6fc2f29916b34c8642f3c0caedb53b8f30c2a77d1757103b7ed156cdc703911366b02cde87ce7343886987f7a8c028921a7b87c5c0aca7ada34970a6d0d32eb1b177ed8e64c1fc6839b9d08acec19560bf4a815ca6187635f0cabb8bf062e8216d3b09b7abd99e956734129e16a7c4f3beb850fe2b1548729355f9015c9bba336d3e26a27b3d75d75722f7a8170d15ebf77f325c97778a5a9d7c76d3e101eeae354e54e6fa60b58cbdd900751854ede326b58fa5caca073c630f3719d6f52afe675f10d464e8b58e5fde75a4f225063ca48d76efd1b645e4bc89d98215beae765601f635a3bc8cfc08d74722f3d95ccb4cb4e3ea977d0c534a4abb866fb9a31771222cfd998231c30bd16b6844ef71038b67d72c910cca40db7260dff0b74162449a9e2cf15d7dfbfb3a685080e6c83ff4341c95819c0317502ed49af7ae688b52c9866518f74d69b4144500ab9d5a0829b9287d5fb67b78801119ddae7a76e80be8c4dbcec7866ffa7d081406e51cf617be061530b539cca7e1ef9118cc06e8eb2a01425b45947a1d2332e360acd0654bba8f1fa43ece68467690d36f6802a32f03f9ea056e57fd548dd4a3225ad5006c6c931aef1990639498dc88a23895ff1f75520a8009dbde4debc20ecc546e378eb7ed5ea3740d2244036588471d96e4751390b6b76b39816d853944cb5677b493b36de9736ba0fa404ad4b3a7d7c54d0c15072c040064b871401b25b88559d059a9519c7e2446b0d110a4aba9c12555e5f620680d1fea2359bc85cd15b5c0bfd6b3715d647514118cd60483dbc9c83e285192108f4ea6bcbee1f0935044610c68d052ccaba23258d09465d5521e2664d59358621ebbb8f28a4627362c8397f0a9852e5d8daf53a961d4ee66299e2b54d8adf5134ceedef57011f810aea76262422236c3e1a478a759584c7880fb3f32389c4bd4b637caad7b2bd6fd295aefb150754799434e99e0fd45c1cc4698ab14d1f63eeb06e53797cbdddd45e7f87e85b45a3dd0df6335c3b1addee87ba953bde29ed98042d745c1465a967ef922993798966e1c8b96ad6f68404136be0caa2264e24d8d93aa1b99da9316c7780904753d4e0b45cf282b43a0c91bc9ff83cb25cacea2ea72563b2e759b69cabbb6a50d6a0a5ba545622e5ce576cc301ba35afadbfd1e26668782e1d741feed8aae894b564a425141442fb8470b325cf7c8e1552973463bf4e67a2ad58d15417e418bb91d2df4b1310a0a70ac744bbb4245efd2ae642609079a44cbf6be19809a5ff7ad6847432368c9749cfb336ddcc0e6f52a699b910cd24671f38af5dc39268a3c87771f07d53bf220b7c2d5058cc7b0bcd492abfedf9bb295ec304107130f0e98dacaac6dab998b511f176d48daeb81db53643ad194690b6e28c5ed2927e09a1e959c494b90db401681f67bf1e23fe9ef4c903f666ef39332a91a25c63efe9bc518e9aff61842007dda72dcc0264aa47543c0a8b1f0d25749ddfbed487282241140d4c64def1831c4d75ca975fdb03258ddd013445e08bfb479a516b011fe3a12e4bfca439407c0022889e46914cd41a4d92a25eaa57a55bc7337e5fbbd11584dca34adb5643105c8171e53cf04b1412c3107e72330ebf1b52f524b4e72570cfdc0ab179991f3782d05091ea57b1a233048bf062e88939cfeefb61e8beaa90395faf61c4d974b23723a4a5cd39d70f92620f8f4f27bc99ca67bed7fb6e594913991ca3025480ad791bc94a0def36fca491a206440ec31e32bb85850c3606c875708309be63c2b4f5c477521aa08e1d059cedaafe4fbef5523b79f88b57d0c81bbdd09202095f10f13e2609e833ff41b862b2214c22e8f2b04a363b38d26bf95c07b184b9f909ad3a92122e158d3566d2204b22d4f2f3ce11a65544ccecb01a4a5ef62bc969fddcb648224a5c7bd94f8da9a7d4df393d880f537a377888874c19dad357a0564d303a5c1485c1451ea55d68779dc0c11c7c38025660684ba3f70cbbab00d15b34c0f2342207ad548eacb32ebad95292e85211a8669b586d05b0d0b9f278a35ea4d78e97fd5dafca6b72d8e1fbf3e704a60a8ec60befe2e3e4d3d37f9d33a0feb88add59f0171ddeba0b79a52feb9a1f4a7a6ee7c6927bd10968fba788a807409346a0fccd4f7daac3c8591fc689aed881829d479e8d360cdb5819d5eac718a6f860f2d9ef6a0d36ef6e10efbb37819bb7b03ab7649173447b2cd47f3433a2422b1611dff91cee0b10c6d060d4e84a9e3f4dc194514cb67f1e3985be05c845fc92b41955d0f61aeba6268789998bbf341a8b37af48f07b13a676a11d27330529cabcd52365842be559857cbc2a63a4ea1c77fa8619040e79705c5b51f473e13b73fc09c28598e070dbbb63ce884c2843ec365d4c5bebbf815ee3314dde0bab6b0a71a398e2d9ee8ba2f832863fae7eb0c18adcdd17f1dee0df29a8409acabf516c8e6dfea5a264c1c6657f774c86a14cf96eecac18a41b1650a9e652c6c9264b03aa2fd30e333a9f24cd6b0313358e3c00943a1de63ca970b7da2cb8a0fd1109cefbf12176f5dfb59457480428b194e88449bffd8b8d87d05d30f9ffe9ac3a7442b0df3418acf9165b14242489a54b6b47ea543fed5de74a00f61ab2af553b60d8d21c76c42052c72e4841bd94cf88185c39287c04d05f6336ae581cf7528a59b2874795caca79f5600ac64ad5820a91c711ae5a1c3762028242c5c8a9aae89177ec4db5785cd07402d45805a2e2e970059e4e6483074df1bcc01f57470fb66f45ab475ebb5343b727168e355a6c25d42384e39802d7b4a8c54ac94d82de12f8de13630ec8c19f008f98c505dbbfb21b363472e23d0147d1ac555f0981e2bfd07c62d097acf930094dcf239a40699421b207ac2575b7edf9b1d772ab066362820c182c2c5097a47d1dd25ca9e0dd9c3ae94e9a8f0dece74cdeeec3a17803d5e11f037820ea20364234079286a7c291f3424292b0eec3e956513cc6b078a76a3b8ab42c5fb5efdcea1d438f7ae08507275b48f9588a15be763ad094885269efa7330f6fc9d4746997c98d9f5feeb6dff2734d75afc6a11196b35bb9fd0c0af428cacef0df2c5ad4e5fb4559f0f93af2fafad6fb77f453238f409ec71a912350d7b62952e4858927f620d31569242615345265ff1cbbd7fdfaff35a45732628da663bfff3d3af3d7b537337754554458a2d1af0e16aa8ad9436096f42e243109cad32fac1adc58d714cd3d0d8483c783006991f3da263ef5ae1ff2ea06584e45849d64a07170675c29f0b2abcf1eedbb63b6f5d9dba600996c7d5edce9ac69448d05c0704fb9f84e831b60c376b8a5d33ea22030e2dd3dd421d8e0a810a77c085a3861fcba214a8baf592d624d673fb34f906581d923d80b06186db8ce5fbef2bb750166f7556adfe93d4951a825d55b0bf92c9f25776df784f6aec808ae221cc98d05ce988fe6a13ff96083dba15500e149409b54345274e3633fa8f6685d6fed40c20a5c5705f8b37099a5949846ca15def5a6a427eb4eec72747f116366adcb9b74d3de0b125bdee23ca98ee6312f41fa3d9bba43a8d343552c969c41f766ab4341a42ec4cd6f4d1d4c4b1f16979e5389fea36a150580418d95520506fe0cb1a1d861e09d21c57d88c46e10a3c5ad1aedc8f2743f5c06f10d6da9b2bb3ec783c6f5788ce9400795022cdcec197f9dd3ee4cd26531e7f057b6d9418a0c52ecdb35a24a2a079b3d396017feca8b31aa55e3d5ef79c9ea9ccc7e3d0b47f28f273276666fa1763b3a452672fedc94557d984c3353344a8bc9fc833dee685e33d63540d0801d8068cf66cc48ddcb0d42cec881eae36fc2614f96ad67fceb5c98ec33fbade0e3049178d503c13c2d5d71f32f4582d1cb0f47a2ace578b903796768a906998bed2995798251d7eb92faacc19255bf12c0024a94971c185841113faa288beb7e58d4a98289630fb3d230f936eb1b9d9c7b94b5ac9d3a211c0b454a26e29bdffb522548a65e8dde3730918fdf0575245e71ba013ce08f6e698342a61a81b1355d2483e97c06462cae1cdc7787f4bcee4396a08dac9c14981f2a8f4614a31b019c83782d5d8370acf9db467d9d95e8efbe44274fefde5860c2333cf81593a2ada9f5bb6c2362ba97fd7c3e5bc836c327c66b57c0f023efc0c0ff6feae0e625df2f4e21057060170c844c86412700d7d337b1f7835a0dafee5206cbd76104c5a36623c7783213f8dd457b5e69a86b74030a27b3c30074242b1d97e65a233885a681ec5a8532bce9dca1998dc32c6b40dd997b99a6ed6288e0b9b09447e356bc5345b2133571e65d47db2c736a391970879103d4137cab6c0724b8e67064167cd5521f32135fb6ca43c1e118adcded8227c9dbfdc18cdce154108eba5d8c60e5362e8fffc5c9ae6ac2572188617e4ce0f432e2476c74a4227af64b58e0ebafaf0b1ce01723ecd36a2a4167b7991e28b6a9e81992fcaf7b4b906d0361add02104db83914f28baea26b50561faa46293ba5247e8263ac0347509c36405747866d2fa2beef44f366108f6a4047e282a477c28654511075ddfaad9b9844e18e67320a831e647d923b2720d65ddd9ece165c222231d3c3e7f0001d15e3c690e9831ceb369a8edf183133814bfd20dd25d50973bda58ad03c4cbda8008556fc653ef401ff76ee858c1f79a0b09b4232768e72dd06e42078923d5647cb310bb644feb24d6b7e9d1167c3676cd96f79965a066aca314089db60bdc40c2be4b69c569ec76b3bb74a43fe731bc869c9222ab5404304a513d4f7d2ec5af278f7c3d664fcde579bba7bd472bdc00a1eb4c46ff69fb7e45e5712919e8656a8887afa28cadd66461fc57f53d574c92105818a89f210d7e8aee6de2e78228b2cb03b850a6e77627f70f51bb919bddf61837a978dd4cec2db138c657214ac07b67134bd53b071e2bffa3608a0b0bac88b0ddcfc1ba4dea17191c9ad76ab8de72118893256a7e13e15a3bf98bb5757a78c58328cc4b380f3786f22c6be81884d213ec3cc2784583a47a4003a59ebea08bd06e290a892c937448e664dac672942b068b839593c442f6e1d22875e01859cd24c17d108696a3196ea4794ddfdf25721d3dd3e754d1ea884e5086479819452991403a39014297fcc734e56f8daae4d49d5c47016fc3ead550783df895542229ff3b034b5b722ae2a2b04ba70e42c174e9ddb89ffa60024aa16f297ac9383b2ccad53de4bbe4ea2fa3fe3d059d16b4b4fe9959ba3c4e58922e7fa2673f50be5b636ee7c79b445471ddf5b851ec3ac505980bb184c8fe44c7776ae9aab4e66ce31fe1bc00efced390a82f96b4866e31ba3ff832a25b1e1d00ec44bf525ae523b7102ba60c1d3a2e2bed004524afc90a064b325a258eb36315b1496c748f5407e922914787acb8b47bdc495e521518e0637eac4b1b4fe1adede145181ec7ef038d48c473d6f296b349d7cf874d329c71f272883eb7e77ff303957e159fd417d5055d82687448950dd149e1074a1785518ebaf7ac167e07f1f559893a20d133b59aa294efebdae1e19a30ec9a3e257203eb9a854096395825ef4d1e4ecf1f8daeadfa049ea6c435c50d67fd21c6f6b11a8be46502f0dda1715f5349df5330454316498660b7996432e679c73f1af33e529ac669496bde538890cc093122842e3e2e4bff937708dd4b1b1d3fc066a63824266461e4af9245032d690aac0ea5636c29606473820ee57b112e2bd68c0ce1936b7e76a7873cad678b26b560d7bb10a7dcad3f69bbf226faf2f572c105741a121fa1c55ff30b2d0b7339ed9aa4c9a3671e6e4b572800afcbc8764b16f0a61c4c1ff24c3b64992cd84f39d1a4d5532a7dbd9f7bc847258a33c509a945e53236cbc46b61fc6fad662c523eef0c1eaa4bc0a49610c8d09659e7bdfa858d2494dc3da0a54fcce229951d366fd17f4120f27ac77e5e6b777693641a853eacec09cc4dc08ff6ba22295acec61c5e6215eaf2a3a012461eaade8faa9cba630c5ce2bee6f1a4676d54b4a38b7b5cfb6c98106a4882ed88153a4f0bad3e0f3d04dc1ae5318e3b8f4ab1d122a548eed47f70edad1a164a9c5c3eb10fdecb24b0b68005b2e958980481834c4f673478d3f47d07836d3c1c513dd920042381f70f1a68671acee2fdd453a7552eba497af27127999a13a33104f0086390e01635d1a0b79d92dd43211c74047804e82d9ab26f97ee88e664871dab52a2a79443e39f06a6e8ac9d5e986252529b389d9ed0b2f55fb16ca65f6e90cc9a149065f499630f973996c1e2b6c53f2ab391b7d78cc6926b1684d066a3a74b86b3b633baaf3730acd28deaf18fb926e1ec9c1f8a2345103cc4cbec05345db57c5adcf062412f289607f5fa41194f69bc2f426a30c7a6f8d1027ee8dc96c9957e90fbd9b16475b82dfd8698195159bd7b4860004beb1fa85e6843eca1acbbb0b8c7ec0b865ed108e297a2d5f915304167e18d01e51497e6e3ea76ae99bcb849f7595fa74c2a6263e2bef65f1063bce05483980ed51eac5289307117f17e99d761337e9b1fb625a1b900e6179f3b02de57a0b5f52352298c8a2d2c816182ec169d2b9c0490097ad98e2edc99c6df683a4b5b6eb73ccee0aaf07e8cf8f2f632381ac407c5c578bc1c5a8d0915dc231b01b92dbd25c2bfd412995780582793736572f1e23ef690bfe6872c2572285cd737a4be91f4dcafef09232de77b315d73f5beb23d03625e031d2438081222b063c343f52565ae314ac47a4fe518b45d0c12f2ceabc5e05c20f607b97035afbe0e29249e47961d9cf9b385c065966b0c7ea91cfa9ed1b55a58b9aaa9de080ca05c6405fdf15bcef74177226eb225a47d532bcbc82a5ffed7fd86c2609b146d86f566d0b84f638d46d6eb696bfbbc62c4fc981a94c1d6ccb9f3f7ed7976ea7e8ff1d2a2d79986fb27f1401f25d5a83f64844fa9e839fc8855007b417b261d325b6e7cb124b27ede8ad18d2b6da8bfc4d4f50c3960d5a1c82e4557b16d05471602d2a31462e4bac9535c9a57389ae0613a674815c2ec10c19f529c9274896dfe49ab06889da517d482145ed8f57ba4b7c0434ce24090ef2459682a4f6342ecc382b4cd3409c3415bcb7f1bbaadfb7ec308eea8b6cb2912469b707c99a55c1754db0650616754735b85a41433a30b28e3946754f90caeb03c7579fc9982e6ec5501d6f23e0f2b6392acc435907d79ea11eb6955723a81c4f02bfc78e2eeb1d0408f8f06b4d2f6d20d90f7698c4e58bcfa993884424f8fcb602ef35d23737fb6aff220927e28c19043ae708fd9755256a8a1660d9c5827bab1b836a10aa23aea9c92fa3b25428b3791c5d25f3f1b63befd5480ac4192c966350edceea8938ecc608e0f063d16d427049ad62625f5177470e7a0d811e8d4273aea8f7377d51db07fc34d9f18497a0c2b5c0bc5e8778e06bf7460f0487eed54d661d74346eeada9090957159b86f8b68183e33d0c3fc134d87e068badd8789d4c7adb829fe08e4558bada5ef3f526afb2c7b6184244af0d07aa5cb525c519ed32298bb6241d900ead0532b0b1fc77a6577963e7a44627ed326741af254ab957ca0298a74323d2ee4f1bca70e20ff796491424e108e03c20f2eed7374c0aa2474a91f3ced6f46165c886a510734d606ceaa08822bfced69def33cea3662512fb42ecefee341d1b499b826ad882542374b032e907a7e6a4dddc4620a5d1002b5aee25711fd2dd6e9d4e90ee350f2889d6c1f4328e4b711fc919ef3c655311637b83b4eff39c157e0510807ec61714b843bc9eb22a0f4dac7e5cc07b8e9ed587b701d9aca2a239e76ac9a16338b74d50578956e06b1ac35ee3b822ca779922d89de7d915afd7d80831e8534b8f8a2eaed252fd862abc99aadde62d4520d9a7c3c3da86081fc36927de60e3479096a2b5025b9a789da01da969cfb0ab2f252c82db9e6663dce3888146b365080f649cf94f991312817147d8f0d1774d8d44ba4afd846060df2de1d1043659c3b94b1eff51fff84e5a81a0c635aedcf677285e0d722e3335449fd0f49a41264fb963ea5bba31dae469c789047812071d8853291fd8003cc31a8968ce7acb68a6e0172ba6ee0e9dedbebeb62143047336c5a91c77085afb01fc075938b306d7e36383ecdfda55b9b5dfdab53aa34000289c398f617a146c4a06404737600484d8d4ea960061ec2cb575dc485f65f275540d0ce7550da08417632b6f0f7d044f6f719ff839aa3e5c9db94d45225a1cf0bdb0c5bffa781572ad605ad37aa988240858c9493dee9f00ed281e93532d89aba5e9e59ec430cdd5edfdfc2ef65e094eeab71cc40b59c997943a0e0dbbc80f1e11834bf3b53153ba1c1f0ccf63b3c802439b2ef1430be6994300d9b2efe4b84e25bd3bf8a566d4851e7fff57cada544d722438e8980a31563ef0558fdd8db9bdd6f1a3e34f06104b680f63c1f80a08ec6ed74bca69bb1023fe63d24c7e7a14ce85db6e21173f2ddf14f233f3787a37e4b347e4d64907fc0a23c3da017c81c27df9fafd4695886d0ddec8c47982912eceef886ab5680a130bfacbf3c67bb4f0cc118274bdfed43bbc2ba56f048d6a390e48932469b30ac84fdfc2e812f32d00a85349bb22f2d8091e64282fca1b40811db756059de5d03861d6a22cfc6289097d23c26c5e3f000f9b34a0e1b28a1269d8673d09107b29ccaa1adc8939bdca312c69ae4a238f45410d8f1b27392d594ceea2a6b42899ee5c5857965b29bea1bc413da618899b1894f2adff3b3a7b05a626e50e42379f5d0e0a148ded33d815f59d1401b197a85656466eaf88ed30d1ad4a87985570291efbb3a2c6f22c0b111e65c843ca3c6179e94335f0f91d4696e1a31107948a042f55f264c32a35e719668483957c9c8e13fd01e5f751870a509f5f06ba41ad63cbd5f706f25b1e598f6c9709ee6bab627211bc38494962e930779ed4ea2a8471d309c4c4f0603238959cb13476b673489696c87ad9da5fef0d6467145a77ae0b1089c8626988278a85be3292680d9d7e4c6866f19b78595d611f15f9a5e37b3d145d5aff4a5b58a3286bd25a862904817afe8e9b9105584af15f54554ca5e7dceaa0fbd1111aae126d74f68bb6f0ce98094dc9a59a31d9526729efa171beda9ac5b7db9118aa94b9b5ad58dc20ae1c328e31269244d636139
+Ciphertext = d248b9e47c303f735b0d29f6111a742d93509ae051466688d56b587104a74fab1b259da64475fc0d2c3e28d87ca4edfeaa5715c23dc0e5281eb0c0c14e22182bb02f9f7d3c24555cd6a3ff766c774e67730a920db5f85d47dc23bbbee460f0922cd7ddba81ccbe727b4b489e79a19db2d012dad2a732273dafabc0fbded3c47dbe5b6b585570c39eb62850dc47f4aa0c29bf5fadf334041fdd4658fa6cc29a81192a53dcf47c03ddca9d03b33b06e5b3808be77925b7e7d8cf51fa939e023161d969f92430917d73f3aa10b83d5b7402410280561a27c376ce0b5151a51be2ef4eb9057eed25a0715436233615dcad1559fdbd81042544441857cdf46d72f5f50ee552cfd3bf166c530e57fd97f34e2e71bff8a90b30b4c4cc3e843b0f06e4eb2ff82675e428f5303aa9141dbeb615cf6aca5540fd7cb756fe5f9b08a4abdc6eb90b2eaef51c21eb9ae79a0e44b0755b3ed48f5e6e57f3148ce02501528dd3dd2b0bbec2650710a183e38510990002ce6498dc5ce7bf33d699dd18b66c0f8031d958b11d678674c355a635f4b5e8d863785f5dc2f99eba9ce74595493c017697344b651dcc2a0b1d5386b73abd8bb2dc77a2d92173d3688d0d704da9e44a6385af9fb3a81db68822b1eac9ab284f0155c20f6bc34af85d8518d0dfd32fdaece1379abca339a00e1326b624b3e4050be5db8dced5e6c4b88b82b6ee2a48c373d236ea3565ecc072e953ffe01b624c6ecbf534678aad9c3f8a07d7dd7232134b6b397d0c96ab5f795f9e3af65b96e7a765283d8081dab9f953113abe06e8d150bf9a8416d8932fac17b032dc346be43736dbf066ed239328803510f6f62bc8abc92f6df9a82c02cbf85de91739bc8d7805d392341be99798079419540dc952fa0d3ceca4b806ab1db3b717f0d720038343465a8bc0da8e8964e58634e8a2d6c99230af2ac7c89acd3f86a22075dc40818028f3c632b36a39c0e064e3ca2a078c617a3e73aaea56ef11114f9efaac90a3ec8f8d9b18921a80d74b09ada83efee127f41179dc6c19c7965f3e7f43e22f636534b123e9246172f9920f253d2a2652a5e8c337ff93b2d479bef5e96e972a9b9cd8af057c750bd711010d59ce065ad50fdd487b5dde616301d0ae6373b6f9efae99d8972f242dd7a6bc61caee70201869be202fd384a992478dfc133b84171f013244c5d17585934aed3b43b818926246227d255bf832ff481f5f8d074ab159a11d6d17ed0ac50f727b870db966e0373bd3b1eecbf9ed66aa66caf33ac57cffe4ac6df3cf7b0e54ac54be4f3d50f61b33557c2990c908a710c85000ef6fa62716960daf918ae3d81ee60b3813e65673bd911ce468510bd230b9c2d215afe86ec12e49e0ae87e4235baf3df237188f5e0af2e61c22a4bf77190dd5dc804b4cc330b360c3dc093ef208c37d299ea0cd2ba906084011e16ac5f4fc9646538d5b538a99546d34a4599c8529c1524fc4b394d6a9cd762855905233ed92e72c8b538372ffe2f0df7085eb074616c7e695d7de40779e384d5fdb49fe02385424ea991dc05c6ae813f76c673eb45d6105bcdcfdbf04dcdd20caa6e30efcf3537bcf72947e1ac37d1e8c600ba9238569a4b3afa590d61acceb2572da85885146a142c8f8c60afe4d53ee4d61f33c47e5a99da9a346bcfbd013754ef39a4d7f16c4c5fbfa53d7f180c16e2b64f97dcfd65349939b5fc167c7a78926f638f1893fe9a81e897beea3258a4175d14f41dc123ddd846e45a87f35154db8a5ac27c7a0fc95d3b3113cfa9e7c828f83a1f0d91ab7789c33be5f55ecbb8eb0c81bcc0fccc880011b21000e2f10773388b198ce79c5d694472d3ef6b2e55c342b29c70e4f33fe59e2e0bd3f9ef617733dd3329a0e426338d9c007bcdd382522cb96e59b223825a39b01b52809f5e8518f64b81c99022d8215b5c435d87cc1a57bd440b31a19b197b277b2072968595ccd64c135ae1b218046e27a7f2685d013ce3173efd07586dc72a28ac4792e804d44f9efd785ef005213df928560a20daa4c24ab07f081479270a0dcee3c26331c48a164e4b9d79a7c30c77ab06b00e9b72c190d35fb873bc095d5e6231a89b52a0737a99532079bcc72ee221b48f0d0d9ba9105f981beb4225f6efc1230d6da10fd2b58a65112a98e4bbbe1accd6e8589eb6d9c771bb911cccf42aa6cbc68d1976f0da7eff1e70277e8c5f83734ec1efb2b00708fef08e986bd6519a0fa4b5772e585ac8e37fd2a2af07aa382579498b3b75863fe792461492b8e71c4a1a2f4421705696a96601317cfff1632784b5d75fc2036ed3fa650354620781b9fcfd53f1927223fa045edf4abe7b2144512f3e3aee99f7ac3e46028bc2427aeb18e9cb40db57b696ea884658abc9b7bae0d8117f93074a3ef903528f8b55c7687cf9f0119a1f246cc9e993219c6384359e7e5e639bb294b264048060224ae168d7b9f1f795c07eaafcddb10b61ac2be3ab3e1fddf75c1f47559f38d24f0c773d0e8bc5fa85d7d33e3aa8d0f15583b8c1e7aab6f5d0e085b7175678bf11cfee8eb069b78220377819e3f4d28eb833d3d21efff543d5c6357fffb4a8fdd6ce399fca42e2d71c53c50f6b20bcbaa1650b57ff483837c39a37d5e978393c332b43021508b8ef27773164d69d0af3c0dfdc125cf30a7c49a7d8e5320d68a35e80cdfd62a0b7ce6a412f08c8062e35265fad5d1f226d590e9b068d09e48772711d7dbd786a38c0325b3d5665c2ff45ad0a20c174dc5739896ac727b34f11c7af299d36d30c69bbdc35770138cf891cfdd8123489fdef2dfaffa9c2548ebd60b0f0bcedff44691979b4e92b364753120364dc2e3b895095da828e8659575a85cca587ba05ca625480f977a6fe10181ab6ce005defbcd8894f8c71811909cd6b56eb7ffe327f46793a9e98bd7fe8951400276bb9c7607f8ba1e633034b73d7f0d040197c3f346394eba68c8accccefe05f59cb7ea9ab1ae2e172d8f466ee21c6531cec2c9dfeebc477a6d98195c28bccc1d5e23ae50e3a1ddd7de189e36ffe0e387df7be43427b194b16e18b42eacd517bba78edc9f56a2c7e89e6f13513718869da7c8c529bc337217a69e14e35cf97ff7db2c23700347f0a33ad25a299fc52b35f63949735ad864aa127053797541864b07168f89ffb7ba5c9a8bfbcb4248383a95f45461a7aee9c658c5679205f47144ba4a06175e746037b8cb6556f06405e0d537d0f2bcd898dd5fb987d96dbce33001a50abff5b9cb0161dbfe30f5df5a161ddd8a750b0cb33898c110415881fc81239f2e25440bca41a5bc46fbd3787e6c8fe8a463415cd9a82be368a02566da740dca8e40e686e1213d9c15de2d3556a1e1180b298ba3074b4ab93e469dd9a39ac0c8a173b04a5ad913e72e4d7b5ff520f108e1a1747c11b6b2fcfaa89b3ef7e669f8ad9620364b4f4f0f9ab274e76bdd631df033357a24723653e427324d907a9eceb3c375c43ee36cdeb046a6374be19ab04922da93d4dc07c5914df06fee97dd813f5fd501ca75e3c5ad53574837f2e51ba6a257134e8ee0f4127c59840ba8b1bb13592dcbe47aea50e453c7837e91bb12ad1c74fd0f149479bc0334c511a822145690a3a408caa32671ed05c2dd219ea360c67727c1fe6a6cd842301761e94bedc73f93de7091b8b6d2783a788313b2fa12595904bf5d1167a5ddc4ee151b1522de60b7293b72a62c4d08b396ed682b6a6262a212ddc8c70dbec1a972cedc09f593e21d843279561884f9759a593da7b17a147db7559f19d5d6f43ea98012872f974306037dc0d344c55403b35a5903f766359341bee5bccb696fc0fd1c7aa8803e4c2f9e6e23d386d3a202027c5792e355592efab9330af330392a7c91e3cacc4e645359edafd78b77829374cd4b644817322b7650696fa763a0cc7143f9ec7e2f6ab3c9ec2443b0c0b0a31e9eeafb7bb8c375232357f08256959a10a6d4bc98d6cd9314a2ce7feaa8c0eb1eeb15047f715d6ae9ebd64238d648ed6bc50617a360d8ff9a01aa0ce0e29338d34bb9612751445372ac6d74837c7d2d67729760216ee33476cce1a154086ec31d986cc5a14e86561c6929554fb280646164bb03e8e52588a1b947960a77d61c2d2499212a742e1a5b78805b5b64fed141d3c4834301b8a8bef31ce65edb539fd9469b590a6980d0d1bd29e34a09f87438059a09b1ea234d1bb29882e67599fc1e417db9d86332077cfb05fe440ad1243e26a67a0ea30e63cdee8850a543d76e810140547412fb1400ac87a10e3bc77d3918750a5cc3e7a0efbd736c7ed4139cd5855ddba47143362bf40b91fcbf27222017c1552360466483e67ed125745724cc713c713dcf7ef6ea3081d65d8d78b903382717848bee7410431e1040ec92373f75a1bf229816f55dcfffb6e6da33ed8e1e8b05f9348cdcd6938f053eb9f93e0de639e922627bf61a6688f9649bb9cdfce6236a176db8b9b53ce4b5f9eb9c0680c92128bd327aa7f04a745025faaf117a18d5664027ab0e3f5898b834e1a75cd4b4087637733416f8bac1ccd67cb4457005945676d03f76fd0453fdb9968643fec98d28da7c8cd7070a803b14a2459f073ea075fd023a896d3306fdabc54416e95907103cd2fb642e301c71cc48e8eabedaae356582761a14e0b3b0ef1de06002c2acf594c85820ae3a094e5b4680566b592221543c1dc5192d6b208e86b5aca91d4e3454564eedb3b8208169ce97e1632b864f1d9d4c4c4c0fd4bcc5206e8f6d64c7cdf212d718cb5b7c7ee21593ada3f33f5952e12bba4f46cb99044978fe75349c6ca735db35891351d7e5f02a93354bc45a9ec756453f053cb87430b3e9211807f81ad99b6fceb8ef1b2d655910e1f5fd22f2ee90e42abab230f8f39a8345eed6ad294a0d32416a253f829093ecae209bc1dbfadae04a373080f9ea8394a28ddfe1134309bb53ae571d2019ff2bd4be94f8176d90987fcebad323f0b2921b85b2610852973f383a2ff4a5fa82a77b13cfd50a33f29164a9ff409422cc4cbd772132856cbd08470b220ace957a6b8e02c8003d750539a38a8df19a5b662907b72e3098d77c2fc3ece0693b47ff19ce911a93b6adce75653d48ace6af10b8f1141437f9206658707b16794e349db3f1a02606ea167d0213ce3644f64ced64de3799b1729210fc31ba1811b0c226306f2466b230ae35e6d8fa11c8f932e27da8cb1bd311919bf9178ef08bb7a2b4ca2d2e6e9585ee9f916991cfcd4862f5de9fbbc63bee6edbdcfcec9173a252eb59fc6d6e58258ca8b2a4475acfc1e09a0c9566d23d92e9ada97de51895bfb0867c42025c8d089c65bba67f4dd84d7c5155a930329345cdf3b1d6e910e730df273e183190beb900344bbce8c3bdb13a7e4ecbe967a61d47921aa55bac2bbb24e3e03d386ddbfafb3b32235b5ed922ed6ac2c89ded1316b69079b826507d708a6cca14ce2244a67be90fb91ddcb0c97432703729bceb432bc856f5eb9d2f169800a04283b080f0e053670a21468df9414fda9f4153eaf1669a19ede7925f832280800f0063ceee34b9d3b0f8da2012525fa7927e76bda71954714d5f51405b920391eca2ad71160acef4091878b907974573b4cf1b377baca0340ab0e4ec546fcaa6130603ad633c3ef980e88d8f44ec5de743cdc6cd9e0e4cbdb97a5c076be9ada8f26bc54d711facec16a2401292cc167bb98cdd320ec9321414bd97498f6d9b54dbb45ffe4b3e3f88260657ee23e19de48a93595c8e3a289a02d76a27ceead05d591633464709aca117c26aa49b64667f2a3b6371984f813d7098fae7a6ba1841775b52314a06c80b4c994ef8100e233ab3115ba2c39b97f2d5082a145720ad0b12b8a7cb275ba848b3fae14fc0c82bf0353195c056b302e508982f73a8519cca722892482b9d9e6a58bfb4d862fa393eabe6aedeae1be5ed772ea3c94a0df1d9684a131c35246c68b32e46aaf89f3649e58b2e99bd6bb3923d3ab43cbf73b6b3d19fe3b62bef178f46c79ba85e23ee4b25bc561e8fa97f51605bc0b210b02aa28242e81dae9489076d259f17d25b93b0e8a2010584d907314e3bd55482f0fa43d37ae9535629d28d6f837360bb35ec869d2a959789dc49b9c8c515942a1e03650566b736551a5180a60279bdb0ff9c387beebeb9e59ed930b3746464a010a6f7ef1de3c7d76fc6899b1e5ed98213813ffb333d969ad72fd8537ef4e12ca7b78d35c24f44ac82da4a7116492ca2efd86ee6a4474014e72a5cfeee7f729b77cfdd1a5d10a03f3cf28f1d314fca36d31ef2ecb3cfccecbcdfd22367b0a0e04435654286ae3d4fee13f56bb7cdab40b4e1dd01f9ef857f94a67c1e237e24819949935ff3bd73b0461ee9020fd0a2db2cc6312ace97e4a8a33c295271453a12822db8d1438f22ed0d466150990dcb39ed042424eef7a1210c83224c856923e3251484a81a15cddb4d7ada8bb7968dcc8f85e39ca99ece8ce2ed7753fcee6900cc9b7b5691f2d67ef9be13f70d195bbd0047908025df01b4f4d581fd59239836578627d9d585ebe9b053d807e9d3ba25405029a148938a746636decdade02b1afb5ccbf2f0e14a27c98a1e130d9208bbf7da4bb4e572927eb348568921d4a3309a2c24f367c935c2a8e1524c3024ff350ac7da8d2849586817bc9d46a08a21aef035a6151e608ed93b1556a484e455819f9ac2fb155020738962e7255a82a0854b31fe20cdd351c10a33eb693c9be1a51a932e04d0364ced41ee1bf800d0c12ab5eb37fe52563666e52827720e856d4f24eb06e0aba446910aabbe36513f2274362fedba4c19398433029495284ccb499bb559a9cdbc94a0d1b733136969a743945a04e1d2d4e77fed21550af35f22651c7de802eab7a3942d7ec55a3a5002bde8d5cccc1d4ac4bb7f4926615fcece543fe5d9092d2c4f50d94fd9868775a072f4a5bcf2e5fd10795f7f172a3341ce33505ba68e7ebedc9c1e9165864244ed31bbe5c308dceff858cc42010ad8c281a24689cf2dee8a549b1abab9981d70a912174944b403ce664d8608b2f723150f5c12164e4caf28676e7a25c3928ca2a4dbe96355ef8f282e57888d40715df07bd8b5895549ad957e758abf868def1c1f5e260d26498616e2ac962bcaa33b879874569f198a91ce4e50fc50da77fea1df9f9ea900c834dcdd462d338efcf8e612aedebf254fac596507d175d30a90543627cfcef6852c7cda8b430e255c4d6d417de31eb5dba123e3ce9e2269867d9a94fdcd8ccac40a9451953085109f5ae0c3e04daadb4a2a47b0e176917660eb3c9f1aae0ec6b00635fa387e056623947c0621f0a12e86fac1881ed1dc1b9f523388d6b6596a152b3e732c561972879dcd3f0232ef0773a4fb195a90c3186c4688ea58967ce7f18386b80bd38e90cfd4cb899337ab27cba8db6523e979b4c449645bb2f320ccd28578bc7ec38f47225273fa61a2e5df97c4d76c556fbe2b0fd30e615f5fc82c3de7194caed9f5946c151c22b7a0c48f4a7cf78aa153414f2913c5eb95e3dbcea7ca544272cd13a1c52fa87759aeb430aab144fab418c835344605df3a044825965ca15de6ba0e59b2080f5844b2d110d71587e19acf14264cec2de5b8c77d18893215d1c1da0a940e7c2ee429a99e2633c216aecb7675a2314a09044951ca5a8eac798f8878fb5ea65f4ddccac53ee0c786e597169079fb6e8ceb37a71580b0904a97450909ca454a690821e249aebb75449e582fe1b30f1fa9f6464bdef654daa5ede6d4f223f4589ea25a25f4672cfbe974d51008bce296628556f55d26646e40b59f40e3149273760b40806ace3b5171e0b79865c6adb53513da2f24c4115de243150cec76107b48ca8da19117f00b5870e67eb8357e43c1b7b593c9875795d46ede26a109e05406b69fda988947e49ab195f22454c3c743c2ec51b91370b4df8d38653b353e51bb83215d122bcfa591009c007bbb6124bc590fed3f9c5699180b3b1424ad02f7c90a149b77d22dea5c996aba675c2a1a20e206d9c25d9446247d495a26486c0d0bfb09d0b5a1a177a09fa749dc36cee73af0116a6b779c2b827512a04ff0f60b483edbcdb33d2a18339463c498ae67ffa9da0aa3f3beb6bc99212f9e6961afde89045520b1f3f2e2761666a333d76030f443f53322f099035584a60978ef8b49f46d7d4d8c5c758ea52a04b59c1a3a1c2f9df3f3b6f5c45cf4b3547043b18c1d615a2c965c3918d090cc72946e8fd0b938e60e03464f4bc71fb719a1d173b0931930e58bf7f6d4403971d36b40f83be6b57244a7029e1d41dc908764d57a5442557218b509faeda4e9fcf31debbc54ae671ef636871233f29e0013c0e33933543f4b59df1978ec89b109c3977b0cf938b7f6166d6c93be5e87684a703c8b7b5fe1a8bfe153a179b55575ff05e599b39e32ed10d958699a1ffe07136081f0719b18c69dc74f66f211103e9c544f3c81a88ba9f66a9bc7017d9ca9e2cd97634052694a598476b99daf1cdfb6122869375ca5873d32d5c1e07d9b5b380b4f09dbe04478cfb1a13853eafacfed70c8abcd444ed095f78d07c0e8b4093be95c3aa24b2e5b6bfe3a06e9d2d9fedfcfeac4cea2490627e6da6a5cca383351952f654ce2b0ad359c0f7f4ad3f8d1d4a030a947d4a2e417bb79102729115cc8b6558c3362b1d805fb48ce4858deff97677e60375ed13e150a12ee7dcc8ccc64d9710c7f516555c1f7a1a08f0d7c6fd21f864fcf28c8f748c40494e01fc32006f977a5100577f86a484d11b82c90cfe6b4d6b1902fef486cc6f3e033904e150e67283e49a5382961dabd244412ca9657b48796e476a82443167e277d5a65c0c563a6abca77d316e5d3ab639a1ecfb1110af2d29f146508bd9874486dbb56328d6f59479e2766692821660462aa60b6bc8a710707ceeb0ea6429e5113e03c9f41ce0d69c7589deb547527673e8a9f9a9a74e9e4bbcabf2e306b35504c1da99730ae86e94cd047b2e6ea5e97e63a492430d37ec446434fb3b066adde08b17d7d903ad194a4a863d6cfe181a45c8c97b5062bf7c4e44d69c0d1a7e1f5029b805b7c21d1b5e56e697999a32557870ebaae8d87dcb5ca5eea2c5547a16b3f30ef9df8df821028c106f86e091050ff8b6ea4171e59dc2592d405073bea53f8ea62edf112dfbc7ca69809db8005783d63557d3d90d123a944be395c1dc3b5e1476dff188346327769fea65f3cf9363e88ed67335870ec8ef13eb9d9ff5317c4e24dfce9d11699e5f47b4233cc8f9d1b915e716a5730a5898ee65d30b1628b484a5e82eda95a590964a8d8bc89dd3c5cf6c4f9137b8c6ee9d6a692e0c0d1d858dd5b3c12de48badade4d01bff312c56ce3ddb34b0fdde3b0c2706fc292b9fac7e1a0dcd0b6534c968117f7de15eba84d2754e4bcb8093a5440297605598659f686075e2b1b464b6b3ec68abb13cde263b1c607545c45746338b9b207b5c381da690f653b35e363e1249551ad938b9fd7b0a944151cda07127bf9ba76958e926472f4aa1de8512ce834cfcae5414b226f23acdb1fe5cf685d2201b78167ad35fc1da282744c2a43cc49d49242f968f7e06de14455e7ef5adedc5b33184346018114e2d1fc7a5349e378da9b2af5b328c213888652aca9f1145363809eca7c1fd8e64a5cc3255418736e048a731f3053db77971f67014e6121a8e464833e5dbd02ea6caf385e43e9f378bfba657986bf852b32adb55e35a2675bfc8d70d43a902032a61f59f57dad2dd7d7963322136233200cb9a90c952074e9ba0fc0654f1b6fd6f7f0eb77c0fa6d8143213ce6e8b0c178f73e17a7c64839f9bebca2fc955ea8ae406a13b80a9045fa8d129fd859faa46fd27c48bde7b890f98ee938c0d78889f84181ae2f5711304fe554d4251bbc6437ced59d577a2a1f26da736193c3674adb13cef9f4cb4aa6585c4d6874b0309ecde300493b1642c595746f09e03977c8902f3a4a877db1153b248f295a0ca2f1e437d15fcab8fd77c5f967304efb5c4920b990674ae61b954af40be17a8559dc377c591b68067fdcaf2d27bd9a22041b981a84be3de50d5962b58f8c4a22fa05192c5ac99a0a9423284fe62a3a59f085136cec72cda2a53af106a2eb5bda28b6e02c299118cd91714c2e7d045346c78d9ed1b41c73231a21e42c298949f70122277f4134ed5c56639edbf3c3e717310e3d1f03dc5a94e64c4ce148bc5c6bde64eb80b17d5979892786a31225eb89bf9f5a582bcf65b83ff7aa361ccd9238d144f6a22a3f77dd8a01382df4ee90a2057dd310a6b0c4b81dfc92a2cc0c606d3be8b18fbe64ddfdf2004eeabea892be2f914edd1edd8e8829dc7704d71bbaaf08c41824dd0f4b34c9eedead9e10e53bfc6fc0bd37417de0c5c71cff0754d672f29c262d8e27b524427e12bc4e4705ab311d3bedcb1ddd09a3ca0c268c05c64951b7d724a9dafe4d249aaabda91d68633aaab845bf78f9a22d467c7e0c5fc70fc9a318b01d7492efea7fffd329d70692e76647ae665c62b280da0d62f870a52e4dc4cd92c9150c96aab16f8c23475e3152d4debb41b6756f000c3d8aceef18b49e295be7a71da1eeadf4eb96509d45d7cc42af4b7013d8bb445f577e8d4cff92770b8ba0e451f3e24c6d981efdb68c7f2dfafee40b8a425955796e369f0d4da3e998c1626ae0fa583334475f1fdde68ca211c3f2e9afb003f553191702e11f8b731c89ea26059ea4466f2bd0a1a5601025ca9417006bca5c9a57dfdba44c603ef9ad38922623b40feda036d84425c47fa42973e348a180a7570e1215044c375313ab08d6f521052dda415707ebb74d6c4774e039bb04cadc2799224bde1802e2ee2a018032e3a341700c0fa2aa28bf93cc479231efe7da0e9f68e572415348c08cf648117e9b6d1267fef6617f5927252c86cc087775db3e30180feb5ce7e1ac9c3761161e07a4853aa6d97e525aa88302954cf9390fde81f8e11d97a11c79e3bad261364c18890dd1f8fc71127edefe3571518a42be611a46a0426a33221aa25a0ae6514daaf96038cb59aaba898de49e3b215a4464e0af614e638c2d9b6e676ec427fc906bc516331a18121f306a5246d179e2d3d0f38ab8393f7ea5a2d24585e7cca649637b9983924a15483c167e8780f8dd7aa1154cbf731745a8d8d54a8c4f8d854371bb8172303f9ba3c8c7cfe8c378ee56bc35c6376aafe907d3294ee9a8786281b7deff78ff125761f1a31d0e8fffe04a52a7574eeb8679670ca3bfb740167a559488d4337819613d32752d8a89013622f6a8d70f3c64b84a4215f4b7bb282a2d17c36a326167e3270757b8f1d9a0137bfc5ec278e8ca35a69e49779cfc25b95a89cc18732b5b9d1986b18878c57e118506909207207ad0b4edf32fb2b35b6e70546f45d0849bd139ffff9d8ae547787e7b51403b54f110e2ac65468cd0910d80a4e321deafd46e9af19609bee1efa41b762b8ace989dd681503539e7d9948664cf7a73ffac9ce2a34b514253c4f21bbccd38057a6d68732930dcdfc9a32219b53339d100db0037a8bbd101e71f5054f3
+AAD = 7b3b9c07148fcd897f657ecfcc87e530191536b8e77f9309e8d7323888b3b21477f2ab7c885c105d9c29ac96aed23b366f9fde4177401b7038c6770c7bd2ee8b4335105cc0eab9e367f0cea90d6f1ae3fa76cd21ceb9f3500ce7fb4b2a3f9e90f900a231ec693aeced7afb6821391d1f5b1b957895777aa7a2b71d9571c00336f26d54d756392cdb74bfb67d5a621d517db20441f74d0940180baf613b09452f64224f8af7bbc864ab4a8434ff624d0c0646ee07132fd376506951899bde975df8c836ab4ed9cc084f1f6d500ad56345d2f250a0d6991b9e458c62b6023191f341c8659e8a38c878cfac12b032674503df9c9bb01c4340c709eb6dd7c74907d769a317f4dd7317843c47bdb4c5e1f07f2380d464b0c47269389cc8a43a09adba86f6aa8f44c8fe514e73b5fe8d344769c1aa20a4538ecfbf47562ca79fa497b0f02f103f75522db9ead50d56dbe86997d6085f1b5aa7a4cab9e51a1247ce4f724a14983b6bafd17369fac973c6be268e20d800de870928e100990ebb0d3bedfceda36c64be3a729b603bce677a49e8caf282c9159b6e3e1e775129bd30dc3f5c9849535d86a27474be03bb5749b4c0115e2614f8feaa7405cc69b1de479b3b57e551f876a9c8c57ab9879cc68bb2ea110b2e77e59dd6a65eaa67cc4d4b2f4d6e646b2a298d3c80fb43969275d4414734e74726145dab06124c040656c39a94846e8fd58d326f4f9eafe5b95d85254765a21993f55070fcb9e85db5d42ab6b9464ce66de3f236dd2a0a26c4e5535dbdcd6eb350209a65aee785c6647ad4103d092a8ac932470880eb314f7c98cdff34fdf35ee2d36f09bd443b5defad7a5acb9df55965421fd043def6f4771e1bb27385b30ba22c0d8972aead6b654085a7dd3b60c4004a0dae22e25100e54e0badd0cadf909799329ddff699de8066dd6c3822d80c73c52d87e6fcbdb2dbbf852e37804b1256e23e76dbe43f30be4a577bc23c7941a3d708d1e1f579e9c6eebc219c74768168f6790a41f883790e08cd1e88ad09a544eb97b3d1d5af67eea666b9c027e5c7c976921189b955a9e605f6cc9c012c1c2e197c5b02504cb9ffbcb0f3ed778d540d5194fdf5d38dba6340c93da7c5501a082689616f337d8b59c2a92c25e777515726e1d7f6cc9552693cc7c30f1294b37f97d49814250d6c1e3eb335c5d214ef3641739d508b87106eaaf367902433a148ca962ec694409acb82d7749e1c88938ad382d0ca6e6cbe8255746832fe737c3e71dae8397f260c98d4a292a126ec21935c24096d2f91ae114194af659455d8a4206197495a28474dd2809debf5f550d77ffac2b0db521559910c352f23472d7aa9f4dbbdb158f40aa36912cbd918ae4c642e76d78d57ade1075c4fe1086ddee3d554353b4693bbcef1cfa87e49890838c36156af0edf384b0413d6d7aa
+Tag = 51cbcf4a2fd82f221de1bfebf86a8c24
+
# OFB tests from OpenSSL upstream.
# OFB-AES128.Encrypt
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
index c541db37..510b4c73 100644
--- a/src/crypto/cipher/tls_cbc.c
+++ b/src/crypto/cipher/tls_cbc.c
@@ -54,10 +54,11 @@
#include <string.h>
#include <openssl/digest.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/sha.h>
#include "../internal.h"
+#include "internal.h"
/* TODO(davidben): unsigned should be size_t. The various constant_time
@@ -146,7 +147,6 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
* the MAC's position can only vary by 255 bytes. */
unsigned scan_start = 0;
unsigned i, j;
- unsigned div_spoiler;
unsigned rotate_offset;
assert(orig_len >= in_len);
@@ -161,16 +161,46 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
if (orig_len > md_size + 255 + 1) {
scan_start = orig_len - (md_size + 255 + 1);
}
- /* div_spoiler contains a multiple of md_size that is used to cause the
- * modulo operation to be constant time. Without this, the time varies
- * based on the amount of padding when running on Intel chips at least.
+
+ /* Ideally the next statement would be:
+ *
+ * rotate_offset = (mac_start - scan_start) % md_size;
*
- * The aim of right-shifting md_size is so that the compiler doesn't
- * figure out that it can remove div_spoiler as that would require it
- * to prove that md_size is always even, which I hope is beyond it. */
- div_spoiler = md_size >> 1;
- div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
- rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
+ * However, division is not a constant-time operation (at least on Intel
+ * chips). Thus we enumerate the possible values of md_size and handle each
+ * separately. The value of |md_size| is public information (it's determined
+ * by the cipher suite in the ServerHello) so our timing can vary based on
+ * its value. */
+
+ rotate_offset = mac_start - scan_start;
+ /* rotate_offset can be, at most, 255 (bytes of padding) + 1 (padding length)
+ * + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */
+ assert(rotate_offset <= 304);
+
+ if (md_size == 16) {
+ rotate_offset &= 15;
+ } else if (md_size == 20) {
+ /* 1/20 is approximated as 25/512 and then Barrett reduction is used.
+ * Analytically, this is correct for 0 <= rotate_offset <= 853. */
+ unsigned q = (rotate_offset * 25) >> 9;
+ rotate_offset -= q * 20;
+ rotate_offset -=
+ constant_time_select(constant_time_ge(rotate_offset, 20), 20, 0);
+ } else if (md_size == 32) {
+ rotate_offset &= 31;
+ } else if (md_size == 48) {
+ /* 1/48 is approximated as 10/512 and then Barrett reduction is used.
+ * Analytically, this is correct for 0 <= rotate_offset <= 768. */
+ unsigned q = (rotate_offset * 10) >> 9;
+ rotate_offset -= q * 48;
+ rotate_offset -=
+ constant_time_select(constant_time_ge(rotate_offset, 48), 48, 0);
+ } else {
+ /* This should be impossible therefore this path doesn't run in constant
+ * time. */
+ assert(0);
+ rotate_offset = rotate_offset % md_size;
+ }
memset(rotated_mac, 0, md_size);
for (i = scan_start, j = 0; i < orig_len; i++) {
diff --git a/src/crypto/cmac/cmac_test.cc b/src/crypto/cmac/cmac_test.cc
index 53f45d15..2496f2a9 100644
--- a/src/crypto/cmac/cmac_test.cc
+++ b/src/crypto/cmac/cmac_test.cc
@@ -44,7 +44,7 @@ static int test(const char *name, const uint8_t *key, size_t key_len,
}
ScopedCMAC_CTX ctx(CMAC_CTX_new());
- if (!CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
+ if (!ctx || !CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
fprintf(stderr, "%s: CMAC_Init failed.\n", name);
return 0;
}
diff --git a/src/crypto/conf/conf.c b/src/crypto/conf/conf.c
index e098a2ce..e4fc428b 100644
--- a/src/crypto/conf/conf.c
+++ b/src/crypto/conf/conf.c
@@ -65,6 +65,7 @@
#include <openssl/mem.h>
#include "conf_def.h"
+#include "internal.h"
static uint32_t conf_value_hash(const CONF_VALUE *v) {
@@ -152,7 +153,7 @@ void NCONF_free(CONF *conf) {
OPENSSL_free(conf);
}
-CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
+static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
STACK_OF(CONF_VALUE) *sk = NULL;
int ok = 0;
CONF_VALUE *v = NULL, *old_value;
@@ -776,3 +777,12 @@ int CONF_parse_list(const char *list, char sep, int remove_whitespace,
lstart = p + 1;
}
}
+
+int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname,
+ unsigned long flags) {
+ return 1;
+}
+
+void CONF_modules_free(void) {}
+
+void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {}
diff --git a/src/crypto/cpu-aarch64-linux.c b/src/crypto/cpu-aarch64-linux.c
new file mode 100644
index 00000000..1b0f3955
--- /dev/null
+++ b/src/crypto/cpu-aarch64-linux.c
@@ -0,0 +1,61 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <sys/auxv.h>
+
+#include <openssl/arm_arch.h>
+
+#include "internal.h"
+
+
+extern uint32_t OPENSSL_armcap_P;
+
+void OPENSSL_cpuid_setup(void) {
+ unsigned long hwcap = getauxval(AT_HWCAP);
+
+ /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
+ * these values. */
+ static const unsigned long kNEON = 1 << 1;
+ static const unsigned long kAES = 1 << 3;
+ static const unsigned long kPMULL = 1 << 4;
+ static const unsigned long kSHA1 = 1 << 5;
+ static const unsigned long kSHA256 = 1 << 6;
+
+ if ((hwcap & kNEON) == 0) {
+ /* Matching OpenSSL, if NEON is missing, don't report other features
+ * either. */
+ return;
+ }
+
+ OPENSSL_armcap_P |= ARMV7_NEON;
+
+ if (hwcap & kAES) {
+ OPENSSL_armcap_P |= ARMV8_AES;
+ }
+ if (hwcap & kPMULL) {
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+ }
+ if (hwcap & kSHA1) {
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+ }
+ if (hwcap & kSHA256) {
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+}
+
+#endif /* OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP */
diff --git a/src/crypto/cpu-arm-asm.S b/src/crypto/cpu-arm-asm.S
deleted file mode 100644
index faf3ad89..00000000
--- a/src/crypto/cpu-arm-asm.S
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-#if !defined(OPENSSL_NO_ASM) && defined(__arm__)
-
-.syntax unified
-.cpu cortex-a8
-.fpu neon
-.text
-.thumb
-.align 2
-.global CRYPTO_arm_neon_probe
-.hidden CRYPTO_arm_neon_probe
-.type CRYPTO_arm_neon_probe, %function
-.thumb_func
-CRYPTO_arm_neon_probe:
- vorr q1, q1, q1
- bx lr
-.section .note.GNU-stack,"",%progbits
-
-#endif /* !OPENSSL_NO_ASM && __arm__ */
diff --git a/src/crypto/cpu-arm-linux.c b/src/crypto/cpu-arm-linux.c
new file mode 100644
index 00000000..73c38ecc
--- /dev/null
+++ b/src/crypto/cpu-arm-linux.c
@@ -0,0 +1,360 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <openssl/arm_arch.h>
+#include <openssl/buf.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+#define HWCAP_NEON (1 << 12)
+
+/* See /usr/include/asm/hwcap.h on an ARM installation for the source of
+ * these values. */
+#define HWCAP2_AES (1 << 0)
+#define HWCAP2_PMULL (1 << 1)
+#define HWCAP2_SHA1 (1 << 2)
+#define HWCAP2_SHA2 (1 << 3)
+
+/* |getauxval| is not available on Android until API level 20. Link it as a weak
+ * symbol and use other methods as fallback. */
+unsigned long getauxval(unsigned long type) __attribute__((weak));
+
+static int open_eintr(const char *path, int flags) {
+ int ret;
+ do {
+ ret = open(path, flags);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+static ssize_t read_eintr(int fd, void *out, size_t len) {
+ ssize_t ret;
+ do {
+ ret = read(fd, out, len);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+/* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of
+ * file, it returns zero. */
+static int read_full(int fd, void *out, size_t len) {
+ char *outp = out;
+ while (len > 0) {
+ ssize_t ret = read_eintr(fd, outp, len);
+ if (ret <= 0) {
+ return 0;
+ }
+ outp += ret;
+ len -= ret;
+ }
+ return 1;
+}
+
+/* read_file opens |path| and reads until end-of-file. On success, it returns
+ * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the
+ * contents. Otherwise, it returns zero. */
+static int read_file(char **out_ptr, size_t *out_len, const char *path) {
+ int fd = open_eintr(path, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ static const size_t kReadSize = 1024;
+ int ret = 0;
+ size_t cap = kReadSize, len = 0;
+ char *buf = OPENSSL_malloc(cap);
+ if (buf == NULL) {
+ goto err;
+ }
+
+ for (;;) {
+ if (cap - len < kReadSize) {
+ size_t new_cap = cap * 2;
+ if (new_cap < cap) {
+ goto err;
+ }
+ char *new_buf = OPENSSL_realloc(buf, new_cap);
+ if (new_buf == NULL) {
+ goto err;
+ }
+ buf = new_buf;
+ cap = new_cap;
+ }
+
+ ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize);
+ if (bytes_read < 0) {
+ goto err;
+ }
+ if (bytes_read == 0) {
+ break;
+ }
+ len += bytes_read;
+ }
+
+ *out_ptr = buf;
+ *out_len = len;
+ ret = 1;
+ buf = NULL;
+
+err:
+ OPENSSL_free(buf);
+ close(fd);
+ return ret;
+}
+
+/* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */
+static unsigned long getauxval_proc(unsigned long type) {
+ int fd = open_eintr("/proc/self/auxv", O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ struct {
+ unsigned long tag;
+ unsigned long value;
+ } entry;
+
+ for (;;) {
+ if (!read_full(fd, &entry, sizeof(entry)) ||
+ (entry.tag == 0 && entry.value == 0)) {
+ break;
+ }
+ if (entry.tag == type) {
+ close(fd);
+ return entry.value;
+ }
+ }
+ close(fd);
+ return 0;
+}
+
+typedef struct {
+ const char *data;
+ size_t len;
+} STRING_PIECE;
+
+static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) {
+ size_t b_len = strlen(b);
+ return a->len == b_len && memcmp(a->data, b, b_len) == 0;
+}
+
+/* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found,
+ * sets |*out_left| and |*out_right| to |in| split before and after it. It
+ * returns one if |sep| was found and zero otherwise. */
+static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right,
+ const STRING_PIECE *in, char sep) {
+ const char *p = memchr(in->data, sep, in->len);
+ if (p == NULL) {
+ return 0;
+ }
+ /* |out_left| or |out_right| may alias |in|, so make a copy. */
+ STRING_PIECE in_copy = *in;
+ out_left->data = in_copy.data;
+ out_left->len = p - in_copy.data;
+ out_right->data = in_copy.data + out_left->len + 1;
+ out_right->len = in_copy.len - out_left->len - 1;
+ return 1;
+}
+
+/* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */
+static void STRING_PIECE_trim(STRING_PIECE *s) {
+ while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) {
+ s->data++;
+ s->len--;
+ }
+ while (s->len != 0 &&
+ (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) {
+ s->len--;
+ }
+}
+
+/* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from
+ * |in|. If found, it sets |*out| to the value and returns one. Otherwise, it
+ * returns zero. */
+static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in,
+ const char *field) {
+ /* Process |in| one line at a time. */
+ STRING_PIECE remaining = *in, line;
+ while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) {
+ STRING_PIECE key, value;
+ if (!STRING_PIECE_split(&key, &value, &line, ':')) {
+ continue;
+ }
+ STRING_PIECE_trim(&key);
+ if (STRING_PIECE_equals(&key, field)) {
+ STRING_PIECE_trim(&value);
+ *out = value;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field,
+ const char *value) {
+ STRING_PIECE extracted;
+ return extract_cpuinfo_field(&extracted, cpuinfo, field) &&
+ STRING_PIECE_equals(&extracted, value);
+}
+
+/* has_list_item treats |list| as a space-separated list of items and returns
+ * one if |item| is contained in |list| and zero otherwise. */
+static int has_list_item(const STRING_PIECE *list, const char *item) {
+ STRING_PIECE remaining = *list, feature;
+ while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) {
+ if (STRING_PIECE_equals(&feature, item)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) {
+ if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) {
+ /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always
+ * available on ARMv8. Linux omits required features, so reading the
+ * "Features" line does not work. (For simplicity, use strict equality. We
+ * assume everything running on future ARM architectures will have a
+ * working |getauxval|.) */
+ return HWCAP_NEON;
+ }
+
+ STRING_PIECE features;
+ if (extract_cpuinfo_field(&features, cpuinfo, "Features") &&
+ has_list_item(&features, "neon")) {
+ return HWCAP_NEON;
+ }
+ return 0;
+}
+
+static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) {
+ STRING_PIECE features;
+ if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) {
+ return 0;
+ }
+
+ unsigned long ret = 0;
+ if (has_list_item(&features, "aes")) {
+ ret |= HWCAP2_AES;
+ }
+ if (has_list_item(&features, "pmull")) {
+ ret |= HWCAP2_PMULL;
+ }
+ if (has_list_item(&features, "sha1")) {
+ ret |= HWCAP2_SHA1;
+ }
+ if (has_list_item(&features, "sha2")) {
+ ret |= HWCAP2_SHA2;
+ }
+ return ret;
+}
+
+/* has_broken_neon returns one if |in| matches a CPU known to have a broken
+ * NEON unit. See https://crbug.com/341598. */
+static int has_broken_neon(const STRING_PIECE *cpuinfo) {
+ return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") &&
+ cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") &&
+ cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") &&
+ cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") &&
+ cpuinfo_field_equals(cpuinfo, "CPU revision", "0");
+}
+
+extern uint32_t OPENSSL_armcap_P;
+
+static int g_has_broken_neon;
+
+void OPENSSL_cpuid_setup(void) {
+ char *cpuinfo_data;
+ size_t cpuinfo_len;
+ if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
+ return;
+ }
+ STRING_PIECE cpuinfo;
+ cpuinfo.data = cpuinfo_data;
+ cpuinfo.len = cpuinfo_len;
+
+ /* |getauxval| is not available on Android until API level 20. If it is
+ * unavailable, read from /proc/self/auxv as a fallback. This is unreadable
+ * on some versions of Android, so further fall back to /proc/cpuinfo.
+ *
+ * See
+ * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2
+ * and b/13679666 (Google-internal) for details. */
+ unsigned long hwcap = 0;
+ if (getauxval != NULL) {
+ hwcap = getauxval(AT_HWCAP);
+ }
+ if (hwcap == 0) {
+ hwcap = getauxval_proc(AT_HWCAP);
+ }
+ if (hwcap == 0) {
+ hwcap = get_hwcap_cpuinfo(&cpuinfo);
+ }
+
+ /* Clear NEON support if known broken. */
+ g_has_broken_neon = has_broken_neon(&cpuinfo);
+ if (g_has_broken_neon) {
+ hwcap &= ~HWCAP_NEON;
+ }
+
+ /* Matching OpenSSL, only report other features if NEON is present. */
+ if (hwcap & HWCAP_NEON) {
+ OPENSSL_armcap_P |= ARMV7_NEON;
+
+ /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to
+ * /proc/cpuinfo. See https://crbug.com/596156. */
+ unsigned long hwcap2 = 0;
+ if (getauxval != NULL) {
+ hwcap2 = getauxval(AT_HWCAP2);
+ }
+ if (hwcap2 == 0) {
+ hwcap2 = get_hwcap2_cpuinfo(&cpuinfo);
+ }
+
+ if (hwcap2 & HWCAP2_AES) {
+ OPENSSL_armcap_P |= ARMV8_AES;
+ }
+ if (hwcap2 & HWCAP2_PMULL) {
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+ }
+ if (hwcap2 & HWCAP2_SHA1) {
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+ }
+ if (hwcap2 & HWCAP2_SHA2) {
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+ }
+
+ OPENSSL_free(cpuinfo_data);
+}
+
+int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; }
+
+#endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */
diff --git a/src/crypto/cpu-arm.c b/src/crypto/cpu-arm.c
index 675d174e..ef395eae 100644
--- a/src/crypto/cpu-arm.c
+++ b/src/crypto/cpu-arm.c
@@ -17,52 +17,15 @@
#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \
!defined(OPENSSL_STATIC_ARMCAP)
-#include <inttypes.h>
-#include <string.h>
-
-#include <setjmp.h>
-#include <signal.h>
-
#include <openssl/arm_arch.h>
-/* We can't include <sys/auxv.h> because the Android SDK version against which
- * Chromium builds is too old to have it. Instead we define all the constants
- * that we need and have a weak pointer to getauxval. */
-
-unsigned long getauxval(unsigned long type) __attribute__((weak));
-
extern uint32_t OPENSSL_armcap_P;
char CRYPTO_is_NEON_capable_at_runtime(void) {
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
}
-static char g_set_neon_called = 0;
-
-void CRYPTO_set_NEON_capable(char neon_capable) {
- g_set_neon_called = 1;
-
- if (neon_capable) {
- OPENSSL_armcap_P |= ARMV7_NEON;
- } else {
- OPENSSL_armcap_P &= ~ARMV7_NEON;
- }
-}
-
-char CRYPTO_is_NEON_functional(void) {
- static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
- return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
-}
-
-void CRYPTO_set_NEON_functional(char neon_functional) {
- if (neon_functional) {
- OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
- } else {
- OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
- }
-}
-
int CRYPTO_is_ARMv8_AES_capable(void) {
return (OPENSSL_armcap_P & ARMV8_AES) != 0;
}
@@ -71,129 +34,5 @@ int CRYPTO_is_ARMv8_PMULL_capable(void) {
return (OPENSSL_armcap_P & ARMV8_PMULL) != 0;
}
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM)
-
-static sigjmp_buf sigill_jmp;
-
-static void sigill_handler(int signal) {
- siglongjmp(sigill_jmp, signal);
-}
-
-void CRYPTO_arm_neon_probe(void);
-
-// probe_for_NEON returns 1 if a NEON instruction runs successfully. Because
-// getauxval doesn't exist on Android until Jelly Bean, supporting NEON on
-// older devices requires this.
-static int probe_for_NEON(void) {
- int supported = 0;
-
- sigset_t sigmask;
- sigfillset(&sigmask);
- sigdelset(&sigmask, SIGILL);
- sigdelset(&sigmask, SIGTRAP);
- sigdelset(&sigmask, SIGFPE);
- sigdelset(&sigmask, SIGBUS);
- sigdelset(&sigmask, SIGSEGV);
-
- struct sigaction sigill_original_action, sigill_action;
- memset(&sigill_action, 0, sizeof(sigill_action));
- sigill_action.sa_handler = sigill_handler;
- sigill_action.sa_mask = sigmask;
-
- sigset_t original_sigmask;
- sigprocmask(SIG_SETMASK, &sigmask, &original_sigmask);
-
- if (sigsetjmp(sigill_jmp, 1 /* save signals */) == 0) {
- sigaction(SIGILL, &sigill_action, &sigill_original_action);
-
- // This function cannot be inline asm because GCC will refuse to compile
- // inline NEON instructions unless building with -mfpu=neon, which would
- // defeat the point of probing for support at runtime.
- CRYPTO_arm_neon_probe();
- supported = 1;
- }
- // Note that Android up to and including Lollipop doesn't restore the signal
- // mask correctly after returning from a sigsetjmp. So that would need to be
- // set again here if more probes were added.
- // See https://android-review.googlesource.com/#/c/127624/
-
- sigaction(SIGILL, &sigill_original_action, NULL);
- sigprocmask(SIG_SETMASK, &original_sigmask, NULL);
-
- return supported;
-}
-
-#else
-
-static int probe_for_NEON(void) {
- return 0;
-}
-
-#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM */
-
-void OPENSSL_cpuid_setup(void) {
- if (getauxval == NULL) {
- // On ARM, but not AArch64, try a NEON instruction and see whether it works
- // in order to probe for NEON support.
- //
- // Note that |CRYPTO_is_NEON_capable| can be true even if
- // |CRYPTO_set_NEON_capable| has never been called if the code was compiled
- // with NEON support enabled (e.g. -mfpu=neon).
- if (!g_set_neon_called && !CRYPTO_is_NEON_capable() && probe_for_NEON()) {
- OPENSSL_armcap_P |= ARMV7_NEON;
- }
- return;
- }
-
- static const unsigned long AT_HWCAP = 16;
- unsigned long hwcap = getauxval(AT_HWCAP);
-
-#if defined(OPENSSL_ARM)
- static const unsigned long kNEON = 1 << 12;
- if ((hwcap & kNEON) == 0) {
- return;
- }
-
- /* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
- * value. */
- static const unsigned long AT_HWCAP2 = 26;
- hwcap = getauxval(AT_HWCAP2);
-
- /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
- * these values. */
- static const unsigned long kAES = 1 << 0;
- static const unsigned long kPMULL = 1 << 1;
- static const unsigned long kSHA1 = 1 << 2;
- static const unsigned long kSHA256 = 1 << 3;
-#elif defined(OPENSSL_AARCH64)
- /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
- * these values. */
- static const unsigned long kNEON = 1 << 1;
- static const unsigned long kAES = 1 << 3;
- static const unsigned long kPMULL = 1 << 4;
- static const unsigned long kSHA1 = 1 << 5;
- static const unsigned long kSHA256 = 1 << 6;
-
- if ((hwcap & kNEON) == 0) {
- return;
- }
-#endif
-
- OPENSSL_armcap_P |= ARMV7_NEON;
-
- if (hwcap & kAES) {
- OPENSSL_armcap_P |= ARMV8_AES;
- }
- if (hwcap & kPMULL) {
- OPENSSL_armcap_P |= ARMV8_PMULL;
- }
- if (hwcap & kSHA1) {
- OPENSSL_armcap_P |= ARMV8_SHA1;
- }
- if (hwcap & kSHA256) {
- OPENSSL_armcap_P |= ARMV8_SHA256;
- }
-}
-
#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) &&
!defined(OPENSSL_STATIC_ARMCAP) */
diff --git a/src/crypto/cpu-intel.c b/src/crypto/cpu-intel.c
index 924bab04..431e1e15 100644
--- a/src/crypto/cpu-intel.c
+++ b/src/crypto/cpu-intel.c
@@ -64,8 +64,8 @@
#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#include <inttypes.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#if defined(OPENSSL_WINDOWS)
@@ -75,6 +75,8 @@
#pragma warning(pop)
#endif
+#include "internal.h"
+
/* OPENSSL_cpuid runs the cpuid instruction. |leaf| is passed in as EAX and ECX
* is set to zero. It writes EAX, EBX, ECX, and EDX to |*out_eax| through
@@ -127,7 +129,7 @@ static void handle_cpu_env(uint32_t *out, const char *in) {
const int invert = in[0] == '~';
uint64_t v;
- if (!sscanf(in + invert, "%" PRIi64, &v)) {
+ if (!sscanf(in + invert, "%" PRIu64, &v)) {
return;
}
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index ace1c82e..89b0bd14 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -63,7 +63,7 @@ uint32_t OPENSSL_ia32cap_P[4] = {0};
uint32_t OPENSSL_armcap_P =
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
- ARMV7_NEON | ARMV7_NEON_FUNCTIONAL |
+ ARMV7_NEON |
#endif
#if defined(OPENSSL_STATIC_ARMCAP_AES)
ARMV8_AES |
@@ -79,10 +79,8 @@ uint32_t OPENSSL_armcap_P =
#endif
0;
-#elif defined(__ARM_NEON__)
-uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
#else
-uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
+uint32_t OPENSSL_armcap_P = 0;
#endif
#endif
@@ -138,3 +136,7 @@ int CRYPTO_malloc_init(void) {
}
void ENGINE_load_builtin_engines(void) {}
+
+void OPENSSL_load_builtin_modules(void) {}
+
+int FIPS_mode(void) { return 0; }
diff --git a/src/crypto/curve25519/CMakeLists.txt b/src/crypto/curve25519/CMakeLists.txt
index a2ef3bb2..195b1e6a 100644
--- a/src/crypto/curve25519/CMakeLists.txt
+++ b/src/crypto/curve25519/CMakeLists.txt
@@ -22,6 +22,7 @@ add_library(
OBJECT
curve25519.c
+ spake25519.c
x25519-x86_64.c
${CURVE25519_ARCH_SOURCES}
@@ -45,3 +46,12 @@ add_executable(
target_link_libraries(x25519_test crypto)
add_dependencies(all_tests x25519_test)
+
+add_executable(
+ spake25519_test
+
+ spake25519_test.cc
+)
+
+target_link_libraries(spake25519_test crypto)
+add_dependencies(all_tests spake25519_test)
diff --git a/src/crypto/curve25519/asm/x25519-asm-arm.S b/src/crypto/curve25519/asm/x25519-asm-arm.S
index 60d08dd5..3af1dba9 100644
--- a/src/crypto/curve25519/asm/x25519-asm-arm.S
+++ b/src/crypto/curve25519/asm/x25519-asm-arm.S
@@ -17,6 +17,9 @@
* domain licensed but the standard ISC license is included above to keep
* licensing simple. */
+#if !defined(OPENSSL_NO_ASM)
+#if defined(__arm__)
+
.fpu neon
.text
.align 4
@@ -2116,3 +2119,6 @@ ldr r0,=0
mov sp,r12
vpop {q4,q5,q6,q7}
bx lr
+
+#endif /* __arm__ */
+#endif /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/curve25519/asm/x25519-asm-x86_64.S b/src/crypto/curve25519/asm/x25519-asm-x86_64.S
index 7e86a231..531ac163 100644
--- a/src/crypto/curve25519/asm/x25519-asm-x86_64.S
+++ b/src/crypto/curve25519/asm/x25519-asm-x86_64.S
@@ -17,6 +17,9 @@
* domain licensed but the standard ISC license is included above to keep
* licensing simple. */
+#if !defined(OPENSSL_NO_ASM)
+#if defined(__x86_64__)
+
.data
.p2align 4
@@ -1929,3 +1932,6 @@ add %r11,%rsp
mov %rdi,%rax
mov %rsi,%rdx
ret
+
+#endif /* __x86_64__ */
+#endif /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/curve25519/curve25519.c b/src/crypto/curve25519/curve25519.c
index 272db6c1..1dd1b3ed 100644
--- a/src/crypto/curve25519/curve25519.c
+++ b/src/crypto/curve25519/curve25519.c
@@ -31,11 +31,10 @@
#include "internal.h"
-/* fe means field element. Here the field is \Z/(2^255-19). An element t,
- * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
- * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
- * context. */
-typedef int32_t fe[10];
+static const int64_t kBottom25Bits = INT64_C(0x1ffffff);
+static const int64_t kBottom26Bits = INT64_C(0x3ffffff);
+static const int64_t kTop39Bits = INT64_C(0xfffffffffe000000);
+static const int64_t kTop38Bits = INT64_C(0xfffffffffc000000);
static uint64_t load_3(const uint8_t *in) {
uint64_t result;
@@ -77,17 +76,17 @@ static void fe_frombytes(fe h, const uint8_t *s) {
int64_t carry8;
int64_t carry9;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -135,16 +134,6 @@ static void fe_tobytes(uint8_t *s, const fe h) {
int32_t h8 = h[8];
int32_t h9 = h[9];
int32_t q;
- int32_t carry0;
- int32_t carry1;
- int32_t carry2;
- int32_t carry3;
- int32_t carry4;
- int32_t carry5;
- int32_t carry6;
- int32_t carry7;
- int32_t carry8;
- int32_t carry9;
q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
q = (h0 + q) >> 26;
@@ -162,16 +151,16 @@ static void fe_tobytes(uint8_t *s, const fe h) {
h0 += 19 * q;
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
- carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
- carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
- carry9 = h9 >> 25; h9 -= carry9 << 25;
+ h1 += h0 >> 26; h0 &= kBottom26Bits;
+ h2 += h1 >> 25; h1 &= kBottom25Bits;
+ h3 += h2 >> 26; h2 &= kBottom26Bits;
+ h4 += h3 >> 25; h3 &= kBottom25Bits;
+ h5 += h4 >> 26; h4 &= kBottom26Bits;
+ h6 += h5 >> 25; h5 &= kBottom25Bits;
+ h7 += h6 >> 26; h6 &= kBottom26Bits;
+ h8 += h7 >> 25; h7 &= kBottom25Bits;
+ h9 += h8 >> 26; h8 &= kBottom26Bits;
+ h9 &= kBottom25Bits;
/* h10 = carry9 */
/* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
@@ -182,32 +171,32 @@ static void fe_tobytes(uint8_t *s, const fe h) {
s[0] = h0 >> 0;
s[1] = h0 >> 8;
s[2] = h0 >> 16;
- s[3] = (h0 >> 24) | (h1 << 2);
+ s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
s[4] = h1 >> 6;
s[5] = h1 >> 14;
- s[6] = (h1 >> 22) | (h2 << 3);
+ s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
s[7] = h2 >> 5;
s[8] = h2 >> 13;
- s[9] = (h2 >> 21) | (h3 << 5);
+ s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
s[10] = h3 >> 3;
s[11] = h3 >> 11;
- s[12] = (h3 >> 19) | (h4 << 6);
+ s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
s[13] = h4 >> 2;
s[14] = h4 >> 10;
s[15] = h4 >> 18;
s[16] = h5 >> 0;
s[17] = h5 >> 8;
s[18] = h5 >> 16;
- s[19] = (h5 >> 24) | (h6 << 1);
+ s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
s[20] = h6 >> 7;
s[21] = h6 >> 15;
- s[22] = (h6 >> 23) | (h7 << 3);
+ s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
s[23] = h7 >> 5;
s[24] = h7 >> 13;
- s[25] = (h7 >> 21) | (h8 << 4);
+ s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
s[26] = h8 >> 4;
s[27] = h8 >> 12;
- s[28] = (h8 >> 20) | (h9 << 6);
+ s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
s[29] = h9 >> 2;
s[30] = h9 >> 10;
s[31] = h9 >> 18;
@@ -447,46 +436,46 @@ static void fe_mul(fe h, const fe f, const fe g) {
* |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
* i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
/* |h0| <= 2^25 */
/* |h4| <= 2^25 */
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
/* |h1| <= 2^24; from now on fits into int32 */
/* |h5| <= 2^24; from now on fits into int32 */
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
/* |h6| <= 2^25; from now on fits into int32 unchanged */
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
/* |h7| <= 2^24; from now on fits into int32 unchanged */
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
/* |h8| <= 2^25; from now on fits into int32 unchanged */
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
@@ -612,24 +601,24 @@ static void fe_sq(fe h, const fe f) {
int64_t carry8;
int64_t carry9;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -880,24 +869,24 @@ static void fe_sq2(fe h, const fe f) {
h8 += h8;
h9 += h9;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -974,52 +963,7 @@ static void fe_pow22523(fe out, const fe z) {
fe_mul(out, t0, z);
}
-/* ge means group element.
-
- * Here the group is the set of pairs (x,y) of field elements (see fe.h)
- * satisfying -x^2 + y^2 = 1 + d x^2y^2
- * where d = -121665/121666.
- *
- * Representations:
- * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
- * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
- * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
- * ge_precomp (Duif): (y+x,y-x,2dxy) */
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
-} ge_p2;
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
- fe T;
-} ge_p3;
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
- fe T;
-} ge_p1p1;
-
-typedef struct {
- fe yplusx;
- fe yminusx;
- fe xy2d;
-} ge_precomp;
-
-typedef struct {
- fe YplusX;
- fe YminusX;
- fe Z;
- fe T2d;
-} ge_cached;
-
-static void ge_tobytes(uint8_t *s, const ge_p2 *h) {
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
@@ -1049,7 +993,7 @@ static const fe d = {-10913610, 13857413, -15372611, 6949391, 114729,
static const fe sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472,
-272473, -25146209, -2005654, 326686, 11406482};
-static int ge_frombytes_negate_vartime(ge_p3 *h, const uint8_t *s) {
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
fe u;
fe v;
fe v3;
@@ -1084,7 +1028,7 @@ static int ge_frombytes_negate_vartime(ge_p3 *h, const uint8_t *s) {
fe_mul(h->X, h->X, sqrtm1);
}
- if (fe_isnegative(h->X) == (s[31] >> 7)) {
+ if (fe_isnegative(h->X) != (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
@@ -1105,6 +1049,13 @@ static void ge_p3_0(ge_p3 *h) {
fe_0(h->T);
}
+static void ge_cached_0(ge_cached *h) {
+ fe_1(h->YplusX);
+ fe_1(h->YminusX);
+ fe_1(h->Z);
+ fe_0(h->T2d);
+}
+
static void ge_precomp_0(ge_precomp *h) {
fe_1(h->yplusx);
fe_1(h->yminusx);
@@ -1122,7 +1073,7 @@ static const fe d2 = {-21827239, -5839606, -30745221, 13898782, 229458,
15978800, -12551817, -6495438, 29715968, 9444199};
/* r = p */
-static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
@@ -1130,20 +1081,27 @@ static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
}
/* r = p */
-static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/* r = p */
-static void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
+/* r = p */
+static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
+ ge_p3 t;
+ x25519_ge_p1p1_to_p3(&t, p);
+ x25519_ge_p3_to_cached(r, &t);
+}
+
/* r = 2 * p */
static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
@@ -1199,7 +1157,7 @@ static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
}
/* r = p + q */
-static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
@@ -1216,7 +1174,7 @@ static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
}
/* r = p - q */
-static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
@@ -1242,12 +1200,64 @@ static uint8_t equal(signed char b, signed char c) {
return y;
}
-static void cmov(ge_precomp *t, ge_precomp *u, uint8_t b) {
+static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
+void x25519_ge_scalarmult_small_precomp(
+ ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
+ /* precomp_table is first expanded into matching |ge_precomp|
+ * elements. */
+ ge_precomp multiples[15];
+
+ unsigned i;
+ for (i = 0; i < 15; i++) {
+ const uint8_t *bytes = &precomp_table[i*(2 * 32)];
+ fe x, y;
+ fe_frombytes(x, bytes);
+ fe_frombytes(y, bytes + 32);
+
+ ge_precomp *out = &multiples[i];
+ fe_add(out->yplusx, y, x);
+ fe_sub(out->yminusx, y, x);
+ fe_mul(out->xy2d, x, y);
+ fe_mul(out->xy2d, out->xy2d, d2);
+ }
+
+ /* See the comment above |k25519SmallPrecomp| about the structure of the
+ * precomputed elements. This loop does 64 additions and 64 doublings to
+ * calculate the result. */
+ ge_p3_0(h);
+
+ for (i = 63; i < 64; i--) {
+ unsigned j;
+ signed char index = 0;
+
+ for (j = 0; j < 4; j++) {
+ const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
+ index |= (bit << j);
+ }
+
+ ge_precomp e;
+ ge_precomp_0(&e);
+
+ for (j = 1; j < 16; j++) {
+ cmov(&e, &multiples[j-1], equal(index, j));
+ }
+
+ ge_cached cached;
+ ge_p1p1 r;
+ x25519_ge_p3_to_cached(&cached, h);
+ x25519_ge_add(&r, h, &cached);
+ x25519_ge_p1p1_to_p3(h, &r);
+
+ ge_madd(&r, h, &e);
+ x25519_ge_p1p1_to_p3(h, &r);
+ }
+}
+
#if defined(OPENSSL_SMALL)
/* This block of code replaces the standard base-point table with a much smaller
@@ -1258,7 +1268,7 @@ static void cmov(ge_precomp *t, ge_precomp *u, uint8_t b) {
* element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
* is the most significant bit). The value of the group element is then:
* (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. */
-static const uint8_t kSmallPrecomp[15 * 2 * 32] = {
+static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66,
@@ -1341,60 +1351,14 @@ static const uint8_t kSmallPrecomp[15 * 2 * 32] = {
0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
};
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
- /* kSmallPrecomp is first expanded into matching |ge_precomp| elements. */
- ge_precomp multiples[15];
-
- unsigned i;
- for (i = 0; i < 15; i++) {
- const uint8_t *bytes = &kSmallPrecomp[i*(2 * 32)];
- fe x, y;
- fe_frombytes(x, bytes);
- fe_frombytes(y, bytes + 32);
-
- ge_precomp *out = &multiples[i];
- fe_add(out->yplusx, y, x);
- fe_sub(out->yminusx, y, x);
- fe_mul(out->xy2d, x, y);
- fe_mul(out->xy2d, out->xy2d, d2);
- }
-
- /* See the comment above |kSmallPrecomp| about the structure of the
- * precomputed elements. This loop does 64 additions and 64 doublings to
- * calculate the result. */
- ge_p3_0(h);
-
- for (i = 63; i < 64; i--) {
- unsigned j;
- signed char index = 0;
-
- for (j = 0; j < 4; j++) {
- const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
- index |= (bit << j);
- }
-
- ge_precomp e;
- ge_precomp_0(&e);
-
- for (j = 1; j < 16; j++) {
- cmov(&e, &multiples[j-1], equal(index, j));
- }
-
- ge_cached cached;
- ge_p1p1 r;
- ge_p3_to_cached(&cached, h);
- ge_add(&r, h, &cached);
- ge_p1p1_to_p3(h, &r);
-
- ge_madd(&r, h, &e);
- ge_p1p1_to_p3(h, &r);
- }
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
+ x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
}
#else
-/* base[i][j] = (j+1)*256^i*B */
-static ge_precomp base[32][8] = {
+/* k25519Precomp[i][j] = (j+1)*256^i*B */
+static const ge_precomp k25519Precomp[32][8] = {
{
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
@@ -3518,17 +3482,17 @@ static uint8_t negative(signed char b) {
static void table_select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
uint8_t bnegative = negative(b);
- uint8_t babs = b - (((-bnegative) & b) << 1);
+ uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
ge_precomp_0(t);
- cmov(t, &base[pos][0], equal(babs, 1));
- cmov(t, &base[pos][1], equal(babs, 2));
- cmov(t, &base[pos][2], equal(babs, 3));
- cmov(t, &base[pos][3], equal(babs, 4));
- cmov(t, &base[pos][4], equal(babs, 5));
- cmov(t, &base[pos][5], equal(babs, 6));
- cmov(t, &base[pos][6], equal(babs, 7));
- cmov(t, &base[pos][7], equal(babs, 8));
+ cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
+ cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
+ cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
+ cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
+ cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
+ cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
+ cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
+ cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
@@ -3541,7 +3505,7 @@ static void table_select(ge_precomp *t, int pos, signed char b) {
*
* Preconditions:
* a[31] <= 127 */
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
@@ -3570,27 +3534,88 @@ static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
for (i = 1; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
}
}
#endif
+static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
+ fe_cmov(t->YplusX, u->YplusX, b);
+ fe_cmov(t->YminusX, u->YminusX, b);
+ fe_cmov(t->Z, u->Z, b);
+ fe_cmov(t->T2d, u->T2d, b);
+}
+
+/* r = scalar * A.
+ * where a = a[0]+256*a[1]+...+256^31 a[31]. */
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) {
+ ge_p2 Ai_p2[8];
+ ge_cached Ai[16];
+ ge_p1p1 t;
+
+ ge_cached_0(&Ai[0]);
+ x25519_ge_p3_to_cached(&Ai[1], A);
+ ge_p3_to_p2(&Ai_p2[1], A);
+
+ unsigned i;
+ for (i = 2; i < 16; i += 2) {
+ ge_p2_dbl(&t, &Ai_p2[i / 2]);
+ ge_p1p1_to_cached(&Ai[i], &t);
+ if (i < 8) {
+ x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
+ }
+ x25519_ge_add(&t, A, &Ai[i]);
+ ge_p1p1_to_cached(&Ai[i + 1], &t);
+ if (i < 7) {
+ x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
+ }
+ }
+
+ ge_p2_0(r);
+ ge_p3 u;
+
+ for (i = 0; i < 256; i += 4) {
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p3(&u, &t);
+
+ uint8_t index = scalar[31 - i/8];
+ index >>= 4 - (i & 4);
+ index &= 0xf;
+
+ unsigned j;
+ ge_cached selected;
+ ge_cached_0(&selected);
+ for (j = 0; j < 16; j++) {
+ cmov_cached(&selected, &Ai[j], equal(j, index));
+ }
+
+ x25519_ge_add(&t, &u, &selected);
+ x25519_ge_p1p1_to_p2(r, &t);
+ }
+}
+
static void slide(signed char *r, const uint8_t *a) {
int i;
int b;
@@ -3625,7 +3650,7 @@ static void slide(signed char *r, const uint8_t *a) {
}
}
-static ge_precomp Bi[8] = {
+static const ge_precomp Bi[8] = {
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
-11754271, -6079156, 2047605},
@@ -3696,8 +3721,8 @@ static ge_precomp Bi[8] = {
* where a = a[0]+256*a[1]+...+256^31 a[31].
* and b = b[0]+256*b[1]+...+256^31 b[31].
* B is the Ed25519 base point (x,4/5) with x positive. */
-void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
- const ge_p3 *A, const uint8_t *b) {
+static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
+ const ge_p3 *A, const uint8_t *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
@@ -3709,30 +3734,30 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
slide(aslide, a);
slide(bslide, b);
- ge_p3_to_cached(&Ai[0], A);
+ x25519_ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
- ge_p1p1_to_p3(&A2, &t);
- ge_add(&t, &A2, &Ai[0]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[1], &u);
- ge_add(&t, &A2, &Ai[1]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[2], &u);
- ge_add(&t, &A2, &Ai[2]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[3], &u);
- ge_add(&t, &A2, &Ai[3]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[4], &u);
- ge_add(&t, &A2, &Ai[4]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[5], &u);
- ge_add(&t, &A2, &Ai[5]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[6], &u);
- ge_add(&t, &A2, &Ai[6]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[7], &u);
+ x25519_ge_p1p1_to_p3(&A2, &t);
+ x25519_ge_add(&t, &A2, &Ai[0]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[1], &u);
+ x25519_ge_add(&t, &A2, &Ai[1]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[2], &u);
+ x25519_ge_add(&t, &A2, &Ai[2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[3], &u);
+ x25519_ge_add(&t, &A2, &Ai[3]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[4], &u);
+ x25519_ge_add(&t, &A2, &Ai[4]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[5], &u);
+ x25519_ge_add(&t, &A2, &Ai[5]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[6], &u);
+ x25519_ge_add(&t, &A2, &Ai[6]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
@@ -3746,22 +3771,22 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
- ge_p1p1_to_p3(&u, &t);
- ge_add(&t, &u, &Ai[aslide[i] / 2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
- ge_p1p1_to_p3(&u, &t);
- ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
- ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
- ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
- ge_p1p1_to_p2(r, &t);
+ x25519_ge_p1p1_to_p2(r, &t);
}
}
@@ -3775,7 +3800,7 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
* s[0]+256*s[1]+...+256^31*s[31] = s mod l
* where l = 2^252 + 27742317777372353535851937790883648493.
* Overwrites s in place. */
-static void sc_reduce(uint8_t *s) {
+void x25519_sc_reduce(uint8_t *s) {
int64_t s0 = 2097151 & load_3(s);
int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
@@ -4609,7 +4634,7 @@ void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) {
az[31] |= 64;
ge_p3 A;
- ge_scalarmult_base(&A, az);
+ x25519_ge_scalarmult_base(&A, az);
ge_p3_tobytes(out_public_key, &A);
memcpy(out_private_key, seed, 32);
@@ -4632,9 +4657,9 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
uint8_t nonce[SHA512_DIGEST_LENGTH];
SHA512_Final(nonce, &hash_ctx);
- sc_reduce(nonce);
+ x25519_sc_reduce(nonce);
ge_p3 R;
- ge_scalarmult_base(&R, nonce);
+ x25519_ge_scalarmult_base(&R, nonce);
ge_p3_tobytes(out_sig, &R);
SHA512_Init(&hash_ctx);
@@ -4644,7 +4669,7 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
uint8_t hram[SHA512_DIGEST_LENGTH];
SHA512_Final(hram, &hash_ctx);
- sc_reduce(hram);
+ x25519_sc_reduce(hram);
sc_muladd(out_sig + 32, hram, az, nonce);
return 1;
@@ -4654,10 +4679,13 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32]) {
ge_p3 A;
if ((signature[63] & 224) != 0 ||
- ge_frombytes_negate_vartime(&A, public_key) != 0) {
+ x25519_ge_frombytes_vartime(&A, public_key) != 0) {
return 0;
}
+ fe_neg(A.X, A.X);
+ fe_neg(A.T, A.T);
+
uint8_t pkcopy[32];
memcpy(pkcopy, public_key, 32);
uint8_t rcopy[32];
@@ -4673,13 +4701,13 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
uint8_t h[SHA512_DIGEST_LENGTH];
SHA512_Final(h, &hash_ctx);
- sc_reduce(h);
+ x25519_sc_reduce(h);
ge_p2 R;
ge_double_scalarmult_vartime(&R, h, &A, scopy);
uint8_t rcheck[32];
- ge_tobytes(rcheck, &R);
+ x25519_ge_tobytes(rcheck, &R);
return CRYPTO_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
}
@@ -4749,17 +4777,17 @@ static void fe_mul121666(fe h, fe f) {
int64_t carry8;
int64_t carry9;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -4883,7 +4911,7 @@ void X25519_public_from_private(uint8_t out_public_value[32],
e[31] |= 64;
ge_p3 A;
- ge_scalarmult_base(&A, e);
+ x25519_ge_scalarmult_base(&A, e);
/* We only need the u-coordinate of the curve25519 point. The map is
* u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
diff --git a/src/crypto/curve25519/internal.h b/src/crypto/curve25519/internal.h
index 27994b7b..ea206a3e 100644
--- a/src/crypto/curve25519/internal.h
+++ b/src/crypto/curve25519/internal.h
@@ -37,6 +37,70 @@ void x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+ * context. */
+typedef int32_t fe[10];
+
+/* ge means group element.
+
+ * Here the group is the set of pairs (x,y) of field elements (see fe.h)
+ * satisfying -x^2 + y^2 = 1 + d x^2y^2
+ * where d = -121665/121666.
+ *
+ * Representations:
+ * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ * ge_precomp (Duif): (y+x,y-x,2dxy) */
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+} ge_p2;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p3;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p1p1;
+
+typedef struct {
+ fe yplusx;
+ fe yminusx;
+ fe xy2d;
+} ge_precomp;
+
+typedef struct {
+ fe YplusX;
+ fe YminusX;
+ fe Z;
+ fe T2d;
+} ge_cached;
+
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h);
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s);
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_scalarmult_small_precomp(
+ ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]);
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]);
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A);
+void x25519_sc_reduce(uint8_t *s);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/crypto/curve25519/spake25519.c b/src/crypto/curve25519/spake25519.c
new file mode 100644
index 00000000..617418cf
--- /dev/null
+++ b/src/crypto/curve25519/spake25519.c
@@ -0,0 +1,464 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/curve25519.h>
+
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+
+/* The following precomputation tables are for the following
+ * points used in the SPAKE2 protocol.
+ *
+ * N:
+ * x: 49918732221787544735331783592030787422991506689877079631459872391322455579424
+ * y: 54629554431565467720832445949441049581317094546788069926228343916274969994000
+ * encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778
+ *
+ * M:
+ * x: 31406539342727633121250288103050113562375374900226415211311216773867585644232
+ * y: 21177308356423958466833845032658859666296341766942662650232962324899758529114
+ * encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e
+ *
+ * These points and their precomputation tables are generated with the
+ * following Python code. For a description of the precomputation table,
+ * see curve25519.c in this directory.
+ *
+ * Exact copies of the source code are kept in bug 27296743.
+ *
+ * import hashlib
+ * import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py
+ *
+ * SEED_N = 'edwards25519 point generation seed (N)'
+ * SEED_M = 'edwards25519 point generation seed (M)'
+ *
+ * def genpoint(seed):
+ * v = hashlib.sha256(seed).digest()
+ * it = 1
+ * while True:
+ * try:
+ * x,y = E.decodepoint(v)
+ * except Exception, e:
+ * print e
+ * it += 1
+ * v = hashlib.sha256(v).digest()
+ * continue
+ * print "Found in %d iterations:" % it
+ * print " x = %d" % x
+ * print " y = %d" % y
+ * print " Encoded (hex)"
+ * print E.encodepoint((x,y)).encode('hex')
+ * return (x,y)
+ *
+ * def gentable(P):
+ * t = []
+ * for i in range(1,16):
+ * k = (i >> 3 & 1) * (1 << 192) + \
+ * (i >> 2 & 1) * (1 << 128) + \
+ * (i >> 1 & 1) * (1 << 64) + \
+ * (i & 1)
+ * t.append(E.scalarmult(P, k))
+ * return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
+ *
+ * def printtable(table, name):
+ * print "static const uint8_t %s[15 * 2 * 32] = {" % name,
+ * for i in range(15 * 2 * 32):
+ * if i % 12 == 0:
+ * print "\n ",
+ * print " 0x%02x," % ord(table[i]),
+ * print "\n};"
+ *
+ * if __name__ == "__main__":
+ * print "Searching for N"
+ * N = genpoint(SEED_N)
+ * print "Generating precomputation table for N"
+ * Ntable = gentable(N)
+ * printtable(Ntable, "kSpakeNSmallPrecomp")
+ *
+ * print "Searching for M"
+ * M = genpoint(SEED_M)
+ * print "Generating precomputation table for M"
+ * Mtable = gentable(M)
+ * printtable(Mtable, "kSpakeMSmallPrecomp")
+ */
+static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {
+ 0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3,
+ 0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2,
+ 0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a,
+ 0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10,
+ 0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11,
+ 0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45,
+ 0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec,
+ 0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23,
+ 0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21,
+ 0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8,
+ 0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d,
+ 0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0,
+ 0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27,
+ 0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39,
+ 0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c,
+ 0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23,
+ 0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25,
+ 0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e,
+ 0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f,
+ 0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7,
+ 0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39,
+ 0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2,
+ 0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9,
+ 0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31,
+ 0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7,
+ 0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe,
+ 0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb,
+ 0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51,
+ 0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e,
+ 0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70,
+ 0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d,
+ 0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13,
+ 0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6,
+ 0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb,
+ 0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2,
+ 0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb,
+ 0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21,
+ 0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe,
+ 0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42,
+ 0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c,
+ 0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b,
+ 0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f,
+ 0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce,
+ 0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a,
+ 0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57,
+ 0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84,
+ 0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3,
+ 0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d,
+ 0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30,
+ 0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55,
+ 0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa,
+ 0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44,
+ 0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4,
+ 0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a,
+ 0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea,
+ 0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a,
+ 0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5,
+ 0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b,
+ 0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3,
+ 0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72,
+ 0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c,
+ 0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a,
+ 0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f,
+ 0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c,
+ 0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10,
+ 0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae,
+ 0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7,
+ 0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87,
+ 0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26,
+ 0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31,
+ 0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb,
+ 0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f,
+ 0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf,
+ 0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31,
+ 0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0,
+ 0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87,
+ 0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68,
+ 0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd,
+ 0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d,
+ 0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71,
+};
+
+static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {
+ 0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee,
+ 0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e,
+ 0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b,
+ 0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c,
+ 0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b,
+ 0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35,
+ 0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89,
+ 0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44,
+ 0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba,
+ 0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee,
+ 0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa,
+ 0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8,
+ 0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e,
+ 0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05,
+ 0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96,
+ 0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69,
+ 0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06,
+ 0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9,
+ 0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88,
+ 0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b,
+ 0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74,
+ 0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a,
+ 0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11,
+ 0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c,
+ 0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf,
+ 0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c,
+ 0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5,
+ 0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19,
+ 0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86,
+ 0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3,
+ 0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e,
+ 0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11,
+ 0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c,
+ 0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d,
+ 0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41,
+ 0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73,
+ 0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8,
+ 0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0,
+ 0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0,
+ 0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b,
+ 0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5,
+ 0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d,
+ 0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab,
+ 0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43,
+ 0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8,
+ 0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a,
+ 0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2,
+ 0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12,
+ 0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b,
+ 0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51,
+ 0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd,
+ 0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e,
+ 0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40,
+ 0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b,
+ 0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11,
+ 0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35,
+ 0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0,
+ 0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1,
+ 0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54,
+ 0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84,
+ 0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc,
+ 0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c,
+ 0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06,
+ 0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11,
+ 0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36,
+ 0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8,
+ 0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d,
+ 0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d,
+ 0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08,
+ 0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b,
+ 0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15,
+ 0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17,
+ 0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88,
+ 0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36,
+ 0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1,
+ 0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2,
+ 0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81,
+ 0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00,
+ 0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71,
+ 0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06,
+};
+
+enum spake2_state_t {
+ spake2_state_init = 0,
+ spake2_state_msg_generated,
+ spake2_state_key_generated,
+};
+
+struct spake2_ctx_st {
+ uint8_t private_key[32];
+ uint8_t my_msg[32];
+ uint8_t password_scalar[32];
+ uint8_t password_hash[SHA512_DIGEST_LENGTH];
+ uint8_t *my_name;
+ size_t my_name_len;
+ uint8_t *their_name;
+ size_t their_name_len;
+ enum spake2_role_t my_role;
+ enum spake2_state_t state;
+};
+
+SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role,
+ const uint8_t *my_name, size_t my_name_len,
+ const uint8_t *their_name, size_t their_name_len) {
+ SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ memset(ctx, 0, sizeof(SPAKE2_CTX));
+ ctx->my_role = my_role;
+
+ CBS my_name_cbs, their_name_cbs;
+ CBS_init(&my_name_cbs, my_name, my_name_len);
+ CBS_init(&their_name_cbs, their_name, their_name_len);
+ if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) ||
+ !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) {
+ SPAKE2_CTX_free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void SPAKE2_CTX_free(SPAKE2_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ OPENSSL_free(ctx->my_name);
+ OPENSSL_free(ctx->their_name);
+ OPENSSL_free(ctx);
+}
+
+/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian
+ * order. */
+static void left_shift_3(uint8_t n[32]) {
+ uint8_t carry = 0;
+ unsigned i;
+
+ for (i = 0; i < 32; i++) {
+ const uint8_t next_carry = n[i] >> 5;
+ n[i] = (n[i] << 3) | carry;
+ carry = next_carry;
+ }
+}
+
+int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len,
+ size_t max_out_len, const uint8_t *password,
+ size_t password_len) {
+ if (ctx->state != spake2_state_init) {
+ return 0;
+ }
+
+ if (max_out_len < sizeof(ctx->my_msg)) {
+ return 0;
+ }
+
+ uint8_t private_tmp[64];
+ RAND_bytes(private_tmp, sizeof(private_tmp));
+ x25519_sc_reduce(private_tmp);
+ /* Multiply by the cofactor (eight) so that we'll clear it when operating on
+ * the peer's point later in the protocol. */
+ left_shift_3(private_tmp);
+ memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key));
+
+ ge_p3 P;
+ x25519_ge_scalarmult_base(&P, ctx->private_key);
+
+ /* mask = h(password) * <N or M>. */
+ uint8_t password_tmp[SHA512_DIGEST_LENGTH];
+ SHA512(password, password_len, password_tmp);
+ memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash));
+ x25519_sc_reduce(password_tmp);
+ memcpy(ctx->password_scalar, password_tmp, sizeof(ctx->password_scalar));
+
+ ge_p3 mask;
+ x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar,
+ ctx->my_role == spake2_role_alice
+ ? kSpakeMSmallPrecomp
+ : kSpakeNSmallPrecomp);
+
+ /* P* = P + mask. */
+ ge_cached mask_cached;
+ x25519_ge_p3_to_cached(&mask_cached, &mask);
+ ge_p1p1 Pstar;
+ x25519_ge_add(&Pstar, &P, &mask_cached);
+
+ /* Encode P* */
+ ge_p2 Pstar_proj;
+ x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar);
+ x25519_ge_tobytes(ctx->my_msg, &Pstar_proj);
+
+ memcpy(out, ctx->my_msg, sizeof(ctx->my_msg));
+ *out_len = sizeof(ctx->my_msg);
+ ctx->state = spake2_state_msg_generated;
+
+ return 1;
+}
+
+static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data,
+ const size_t len) {
+ uint8_t len_le[8];
+ size_t l = len;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ len_le[i] = l & 0xff;
+ l >>= 8;
+ }
+
+ SHA512_Update(sha, len_le, sizeof(len_le));
+ SHA512_Update(sha, data, len);
+}
+
+int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len,
+ size_t max_out_key_len, const uint8_t *their_msg,
+ size_t their_msg_len) {
+ if (ctx->state != spake2_state_msg_generated ||
+ their_msg_len != 32) {
+ return 0;
+ }
+
+ ge_p3 Qstar;
+ if (0 != x25519_ge_frombytes_vartime(&Qstar, their_msg)) {
+ /* Point received from peer was not on the curve. */
+ return 0;
+ }
+
+ /* Unmask peer's value. */
+ ge_p3 peers_mask;
+ x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar,
+ ctx->my_role == spake2_role_alice
+ ? kSpakeNSmallPrecomp
+ : kSpakeMSmallPrecomp);
+
+ ge_cached peers_mask_cached;
+ x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);
+
+ ge_p1p1 Q_compl;
+ ge_p3 Q_ext;
+ x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached);
+ x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl);
+
+ ge_p2 dh_shared;
+ x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext);
+
+ uint8_t dh_shared_encoded[32];
+ x25519_ge_tobytes(dh_shared_encoded, &dh_shared);
+
+ SHA512_CTX sha;
+ SHA512_Init(&sha);
+ if (ctx->my_role == spake2_role_alice) {
+ update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+ update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+ update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+ update_with_length_prefix(&sha, their_msg, 32);
+ } else {
+ update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+ update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+ update_with_length_prefix(&sha, their_msg, 32);
+ update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+ }
+ update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded));
+ update_with_length_prefix(&sha, ctx->password_hash,
+ sizeof(ctx->password_hash));
+
+ uint8_t key[SHA512_DIGEST_LENGTH];
+ SHA512_Final(key, &sha);
+
+ size_t to_copy = max_out_key_len;
+ if (to_copy > sizeof(key)) {
+ to_copy = sizeof(key);
+ }
+ memcpy(out_key, key, to_copy);
+ *out_key_len = to_copy;
+ ctx->state = spake2_state_key_generated;
+
+ return 1;
+}
diff --git a/src/crypto/curve25519/spake25519_test.cc b/src/crypto/curve25519/spake25519_test.cc
new file mode 100644
index 00000000..d97a8602
--- /dev/null
+++ b/src/crypto/curve25519/spake25519_test.cc
@@ -0,0 +1,169 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/curve25519.h>
+#include "../test/scoped_types.h"
+
+
+struct SPAKE2Run {
+ bool Run() {
+ ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(
+ spake2_role_alice,
+ reinterpret_cast<const uint8_t *>(alice_names.first.data()),
+ alice_names.first.size(),
+ reinterpret_cast<const uint8_t *>(alice_names.second.data()),
+ alice_names.second.size()));
+ ScopedSPAKE2_CTX bob(SPAKE2_CTX_new(
+ spake2_role_bob,
+ reinterpret_cast<const uint8_t *>(bob_names.first.data()),
+ bob_names.first.size(),
+ reinterpret_cast<const uint8_t *>(bob_names.second.data()),
+ bob_names.second.size()));
+
+ if (!alice || !bob) {
+ return false;
+ }
+
+ uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
+ uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE];
+ size_t alice_msg_len, bob_msg_len;
+
+ if (!SPAKE2_generate_msg(
+ alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg),
+ reinterpret_cast<const uint8_t *>(alice_password.data()),
+ alice_password.size()) ||
+ !SPAKE2_generate_msg(
+ bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg),
+ reinterpret_cast<const uint8_t *>(bob_password.data()),
+ bob_password.size())) {
+ return false;
+ }
+
+ if (alice_corrupt_msg_bit >= 0 &&
+ static_cast<size_t>(alice_corrupt_msg_bit) < 8 * alice_msg_len) {
+ alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7);
+ }
+
+ uint8_t alice_key[64], bob_key[64];
+ size_t alice_key_len, bob_key_len;
+
+ if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len,
+ sizeof(alice_key), bob_msg, bob_msg_len) ||
+ !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key),
+ alice_msg, alice_msg_len)) {
+ return false;
+ }
+
+ key_matches_ = (alice_key_len == bob_key_len &&
+ memcmp(alice_key, bob_key, alice_key_len) == 0);
+
+ return true;
+ }
+
+ bool key_matches() const {
+ return key_matches_;
+ }
+
+ std::string alice_password = "password";
+ std::string bob_password = "password";
+ std::pair<std::string, std::string> alice_names = {"alice", "bob"};
+ std::pair<std::string, std::string> bob_names = {"bob", "alice"};
+ int alice_corrupt_msg_bit = -1;
+
+ private:
+ bool key_matches_ = false;
+};
+
+static bool TestSPAKE2() {
+ for (unsigned i = 0; i < 20; i++) {
+ SPAKE2Run spake2;
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (!spake2.key_matches()) {
+ fprintf(stderr, "Key didn't match for equal passwords.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool TestWrongPassword() {
+ SPAKE2Run spake2;
+ spake2.bob_password = "wrong password";
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (spake2.key_matches()) {
+ fprintf(stderr, "Key matched for unequal passwords.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestWrongNames() {
+ SPAKE2Run spake2;
+ spake2.alice_names.second = "charlie";
+ spake2.bob_names.second = "charlie";
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (spake2.key_matches()) {
+ fprintf(stderr, "Key matched for unequal names.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestCorruptMessages() {
+ for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) {
+ SPAKE2Run spake2;
+ spake2.alice_corrupt_msg_bit = i;
+ if (spake2.Run() && spake2.key_matches()) {
+ fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */
+
+int main(int argc, char **argv) {
+ if (!TestSPAKE2() ||
+ !TestWrongPassword() ||
+ !TestWrongNames() ||
+ !TestCorruptMessages()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/curve25519/x25519_test.cc b/src/crypto/curve25519/x25519_test.cc
index 85ee4a2d..24dfa650 100644
--- a/src/crypto/curve25519/x25519_test.cc
+++ b/src/crypto/curve25519/x25519_test.cc
@@ -20,8 +20,7 @@
static bool TestX25519() {
- /* Taken from
- * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-5.2 */
+ /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
static const uint8_t kScalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
@@ -91,8 +90,7 @@ static bool TestX25519SmallOrder() {
}
static bool TestX25519Iterated() {
- /* Taken from
- * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-5.2 */
+ /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
unsigned i;
diff --git a/src/crypto/dh/check.c b/src/crypto/dh/check.c
index 06af6f25..d27fdf15 100644
--- a/src/crypto/dh/check.c
+++ b/src/crypto/dh/check.c
@@ -62,30 +62,52 @@
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
+ *ret = 0;
+
+ BN_CTX *ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ BN_CTX_start(ctx);
+
int ok = 0;
- BIGNUM q;
- *ret = 0;
- BN_init(&q);
- if (!BN_set_word(&q, 1)) {
+ /* Check |pub_key| is greater than 1. */
+ BIGNUM *tmp = BN_CTX_get(ctx);
+ if (tmp == NULL ||
+ !BN_set_word(tmp, 1)) {
goto err;
}
-
- if (BN_cmp(pub_key, &q) <= 0) {
+ if (BN_cmp(pub_key, tmp) <= 0) {
*ret |= DH_CHECK_PUBKEY_TOO_SMALL;
}
- if (!BN_copy(&q, dh->p) ||
- !BN_sub_word(&q, 1)) {
+
+ /* Check |pub_key| is less than |dh->p| - 1. */
+ if (!BN_copy(tmp, dh->p) ||
+ !BN_sub_word(tmp, 1)) {
goto err;
}
- if (BN_cmp(pub_key, &q) >= 0) {
+ if (BN_cmp(pub_key, tmp) >= 0) {
*ret |= DH_CHECK_PUBKEY_TOO_LARGE;
}
+ if (dh->q != NULL) {
+ /* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
+ * groups which are not safe primes but pick a generator on a prime-order
+ * subgroup of size |dh->q|. */
+ if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) {
+ goto err;
+ }
+ if (!BN_is_one(tmp)) {
+ *ret |= DH_CHECK_PUBKEY_INVALID;
+ }
+ }
+
ok = 1;
err:
- BN_free(&q);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index bf6196ce..a5cf94d9 100644
--- a/src/crypto/dh/dh.c
+++ b/src/crypto/dh/dh.c
@@ -74,7 +74,7 @@
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
DH *DH_new(void) {
- DH *dh = (DH *)OPENSSL_malloc(sizeof(DH));
+ DH *dh = OPENSSL_malloc(sizeof(DH));
if (dh == NULL) {
OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -236,7 +236,6 @@ int DH_generate_key(DH *dh) {
int generate_new_key = 0;
unsigned l;
BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
BIGNUM local_priv;
@@ -269,9 +268,8 @@ int DH_generate_key(DH *dh) {
pub_key = dh->pub_key;
}
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
- dh->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx)) {
goto err;
}
@@ -293,7 +291,8 @@ int DH_generate_key(DH *dh) {
}
BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
- if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) {
+ if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx,
+ dh->method_mont_p)) {
goto err;
}
@@ -318,7 +317,6 @@ err:
int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
BIGNUM *shared_key;
int ret = -1;
int check_result;
@@ -344,9 +342,8 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
goto err;
}
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
- dh->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx)) {
goto err;
}
@@ -357,7 +354,7 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
if (!BN_mod_exp_mont(shared_key, peers_key, &local_priv, dh->p, ctx,
- mont)) {
+ dh->method_mont_p)) {
OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
goto err;
}
diff --git a/src/crypto/dh/dh_test.cc b/src/crypto/dh/dh_test.cc
index c117bd49..885bd32b 100644
--- a/src/crypto/dh/dh_test.cc
+++ b/src/crypto/dh/dh_test.cc
@@ -72,12 +72,14 @@
static bool RunBasicTests();
static bool RunRFC5114Tests();
+static bool TestBadY();
int main(int argc, char *argv[]) {
CRYPTO_library_init();
if (!RunBasicTests() ||
- !RunRFC5114Tests()) {
+ !RunRFC5114Tests() ||
+ !TestBadY()) {
ERR_print_errors_fp(stderr);
return 1;
}
@@ -477,3 +479,57 @@ static bool RunRFC5114Tests() {
return 1;
}
+
+// kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP
+// Group with 224-bit Prime Order Subgroup (section 2.2).
+static const uint8_t kRFC5114_2048_224BadY[] = {
+ 0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3,
+ 0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad,
+ 0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20,
+ 0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67,
+ 0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88,
+ 0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83,
+ 0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f,
+ 0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8,
+ 0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2,
+ 0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70,
+ 0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f,
+ 0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66,
+ 0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22,
+ 0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44,
+ 0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d,
+ 0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed,
+ 0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01,
+ 0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a,
+ 0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72,
+ 0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2,
+ 0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89,
+ 0x93, 0x74, 0x89, 0x59,
+};
+
+static bool TestBadY() {
+ ScopedDH dh(DH_get_2048_224(nullptr));
+ ScopedBIGNUM pub_key(
+ BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr));
+ if (!dh || !pub_key || !DH_generate_key(dh.get())) {
+ return false;
+ }
+
+ int flags;
+ if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) {
+ return false;
+ }
+ if (!(flags & DH_CHECK_PUBKEY_INVALID)) {
+ fprintf(stderr, "DH_check_pub_key did not reject the key.\n");
+ return false;
+ }
+
+ std::vector<uint8_t> result(DH_size(dh.get()));
+ if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) {
+ fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ return true;
+}
diff --git a/src/crypto/digest/digest.c b/src/crypto/digest/digest.c
index eb71b073..fdd9fe55 100644
--- a/src/crypto/digest/digest.c
+++ b/src/crypto/digest/digest.c
@@ -60,7 +60,6 @@
#include <string.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
#include <openssl/mem.h>
#include "internal.h"
@@ -166,6 +165,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) {
if (ctx->digest != type) {
if (ctx->digest && ctx->digest->ctx_size > 0) {
OPENSSL_free(ctx->md_data);
+ ctx->md_data = NULL;
}
ctx->digest = type;
if (type->ctx_size > 0) {
@@ -231,11 +231,11 @@ const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) {
return ctx->digest;
}
-unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
return EVP_MD_size(EVP_MD_CTX_md(ctx));
}
-unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
return EVP_MD_block_size(EVP_MD_CTX_md(ctx));
}
diff --git a/src/crypto/digest/digest_test.cc b/src/crypto/digest/digest_test.cc
index 6a6113d5..39ceaffc 100644
--- a/src/crypto/digest/digest_test.cc
+++ b/src/crypto/digest/digest_test.cc
@@ -245,7 +245,6 @@ static int TestGetters() {
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
if (!TestDigest(&kTestVectors[i])) {
diff --git a/src/crypto/digest/md32_common.h b/src/crypto/digest/md32_common.h
index 9db8c54a..4cf050ca 100644
--- a/src/crypto/digest/md32_common.h
+++ b/src/crypto/digest/md32_common.h
@@ -140,89 +140,29 @@ extern "C" {
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
-#if !defined(PEDANTIC) && defined(__GNUC__) && __GNUC__ >= 2 && \
- !defined(OPENSSL_NO_ASM)
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
-/* The first macro gives a ~30-40% performance improvement in SHA-256 compiled
- * with gcc on P4. This can only be done on x86, where unaligned data fetches
- * are possible. */
-#define HOST_c2l(c, l) \
- (void)({ \
- uint32_t r = *((const uint32_t *)(c)); \
- __asm__("bswapl %0" : "=r"(r) : "0"(r)); \
- (c) += 4; \
- (l) = r; \
- })
-#define HOST_l2c(l, c) \
- (void)({ \
- uint32_t r = (l); \
- __asm__("bswapl %0" : "=r"(r) : "0"(r)); \
- *((uint32_t *)(c)) = r; \
- (c) += 4; \
- r; \
- })
-#elif defined(__aarch64__) && defined(__BYTE_ORDER__)
-#if defined(__ORDER_LITTLE_ENDIAN__) && \
- __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#define HOST_c2l(c, l) \
- (void)({ \
- uint32_t r; \
- __asm__("rev %w0, %w1" : "=r"(r) : "r"(*((const uint32_t *)(c)))); \
- (c) += 4; \
- (l) = r; \
- })
-#define HOST_l2c(l, c) \
- (void)({ \
- uint32_t r; \
- __asm__("rev %w0, %w1" : "=r"(r) : "r"((uint32_t)(l))); \
- *((uint32_t *)(c)) = r; \
- (c) += 4; \
- r; \
- })
-#elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4)
-#define HOST_l2c(l, c) (*((uint32_t *)(c)) = (l), (c) += 4, (l))
-#endif /* __aarch64__ && __BYTE_ORDER__ */
-#endif /* ARCH */
-#endif /* !PEDANTIC && GNUC && !NO_ASM */
-
-#ifndef HOST_c2l
#define HOST_c2l(c, l) \
(void)(l = (((uint32_t)(*((c)++))) << 24), \
l |= (((uint32_t)(*((c)++))) << 16), \
l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++)))))
-#endif
-#ifndef HOST_l2c
#define HOST_l2c(l, c) \
(void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
*((c)++) = (uint8_t)(((l)) & 0xff))
-#endif
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
-/* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
-#define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4)
-#define HOST_l2c(l, c) (void)(*((uint32_t *)(c)) = (l), (c) += 4, l)
-#endif /* OPENSSL_X86 || OPENSSL_X86_64 */
-
-#ifndef HOST_c2l
#define HOST_c2l(c, l) \
(void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \
l |= (((uint32_t)(*((c)++))) << 16), \
l |= (((uint32_t)(*((c)++))) << 24))
-#endif
-#ifndef HOST_l2c
#define HOST_l2c(l, c) \
(void)(*((c)++) = (uint8_t)(((l)) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 24) & 0xff))
-#endif
#endif /* DATA_ORDER */
diff --git a/src/crypto/directory.h b/src/crypto/directory.h
deleted file mode 100644
index 29123ea9..00000000
--- a/src/crypto/directory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copied from Richard Levitte's (richard@levitte.org) LP library. All
- * symbol names have been changed, with permission from the author. */
-
-/* $LP: LPlib/source/LPdir.h,v 1.1 2004/06/14 08:56:04 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS 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 REGENTS OR 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 OPENSSL_HEADER_DIRECTORY_H
-#define OPENSSL_HEADER_DIRECTORY_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/* Directory functions abstract the O/S specific operations for opening and
- * reading directories in the filesystem. */
-
-
-/* OPENSSL_dir_context_st is an opaque structure that represents an open
- * directory and a position in that directory. */
-typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX;
-
-/* OPENSSL_DIR_read reads a single filename from |ctx|. On the first call,
- * |directory| must be given and |*ctx| must be NULL. Subsequent calls with the
- * same |*ctx| will return subsequent file names until it returns NULL to
- * indicate EOF. The strings returned reference a buffer internal to the
- * |OPENSSL_DIR_CTX| and will be overridden by subsequent calls. */
-OPENSSL_EXPORT const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx,
- const char *directory);
-
-/* OPENSSL_DIR_end closes |*ctx|. It returns one on success and zero on
- * error. */
-OPENSSL_EXPORT int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx);
-
-
-#if defined(__cplusplus)
-} /* extern C */
-#endif
-
-#endif /* OPENSSL_HEADER_DIRECTORY_H */
diff --git a/src/crypto/directory_posix.c b/src/crypto/directory_posix.c
deleted file mode 100644
index b944b692..00000000
--- a/src/crypto/directory_posix.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS 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 COPYRIGHT
- * OWNER OR 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. */
-
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 201409 /* for readdir_r */
-#endif
-
-#include "directory.h"
-
-
-#if !defined(OPENSSL_WINDOWS)
-
-#include <dirent.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(OPENSSL_PNACL)
-/* pnacl doesn't include readdir_r! So we do the best we can. */
-int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
- errno = 0;
- *result = readdir(dirp);
- if (*result != NULL) {
- return 0;
- }
- if (errno) {
- return 1;
- }
- return 0;
-}
-#endif
-
-struct OPENSSL_dir_context_st {
- DIR *dir;
- struct dirent dirent;
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
- struct dirent *dirent;
-
- if (ctx == NULL || directory == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- errno = 0;
- if (*ctx == NULL) {
- *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
- if (*ctx == NULL) {
- errno = ENOMEM;
- return 0;
- }
- memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
- (*ctx)->dir = opendir(directory);
- if ((*ctx)->dir == NULL) {
- int save_errno = errno; /* Probably not needed, but I'm paranoid */
- free(*ctx);
- *ctx = NULL;
- errno = save_errno;
- return 0;
- }
- }
-
- if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 ||
- dirent == NULL) {
- return 0;
- }
-
- return (*ctx)->dirent.d_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
- if (ctx != NULL && *ctx != NULL) {
- int r = closedir((*ctx)->dir);
- free(*ctx);
- *ctx = NULL;
- return r == 0;
- }
-
- errno = EINVAL;
- return 0;
-}
-
-#endif /* !OPENSSL_WINDOWS */
diff --git a/src/crypto/directory_win.c b/src/crypto/directory_win.c
deleted file mode 100644
index 4ebacf21..00000000
--- a/src/crypto/directory_win.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS 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 COPYRIGHT
- * OWNER OR 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 "directory.h"
-
-
-#if defined(OPENSSL_WINDOWS)
-
-#pragma warning(push, 3)
-#include <windows.h>
-#pragma warning(pop)
-#include <errno.h>
-#include <string.h>
-#include <tchar.h>
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-#include <openssl/mem.h>
-
-
-struct OPENSSL_dir_context_st {
- WIN32_FIND_DATA ctx;
- HANDLE handle;
- char entry_name[NAME_MAX + 1];
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
- if (ctx == NULL || directory == NULL) {
- errno = EINVAL;
- return 0;
- }
-
- errno = 0;
- if (*ctx == NULL) {
- *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
- if (*ctx == NULL) {
- errno = ENOMEM;
- return 0;
- }
- memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
- if (sizeof(TCHAR) != sizeof(char)) {
- TCHAR *wdir = NULL;
- /* len_0 denotes string length *with* trailing 0 */
- size_t index = 0, len_0 = strlen(directory) + 1;
-
- wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR));
- if (wdir == NULL) {
- free(*ctx);
- *ctx = NULL;
- errno = ENOMEM;
- return 0;
- }
-
- if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir,
- len_0)) {
- for (index = 0; index < len_0; index++) {
- wdir[index] = (TCHAR)directory[index];
- }
- }
-
- (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
-
- free(wdir);
- } else {
- (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
- }
-
- if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
- free(*ctx);
- *ctx = NULL;
- errno = EINVAL;
- return 0;
- }
- } else {
- if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
- return 0;
- }
- }
-
- if (sizeof(TCHAR) != sizeof(char)) {
- TCHAR *wdir = (*ctx)->ctx.cFileName;
- size_t index, len_0 = 0;
-
- while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) {
- len_0++;
- }
- len_0++;
-
- if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0,
- (*ctx)->entry_name, sizeof((*ctx)->entry_name),
- NULL, 0)) {
- for (index = 0; index < len_0; index++) {
- (*ctx)->entry_name[index] = (char)wdir[index];
- }
- }
- } else {
- strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
- sizeof((*ctx)->entry_name) - 1);
- }
-
- (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
-
- return (*ctx)->entry_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
- if (ctx != NULL && *ctx != NULL) {
- FindClose((*ctx)->handle);
- free(*ctx);
- *ctx = NULL;
- return 1;
- }
- errno = EINVAL;
- return 0;
-}
-
-#endif /* OPENSSL_WINDOWS */
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index ebe55e84..fe29aa0e 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -61,7 +61,6 @@
#include <string.h>
-#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
@@ -73,7 +72,6 @@
#include <openssl/sha.h>
#include <openssl/thread.h>
-#include "internal.h"
#include "../internal.h"
@@ -86,7 +84,7 @@
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
DSA *DSA_new(void) {
- DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA));
+ DSA *dsa = OPENSSL_malloc(sizeof(DSA));
if (dsa == NULL) {
OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -94,7 +92,6 @@ DSA *DSA_new(void) {
memset(dsa, 0, sizeof(DSA));
- dsa->write_params = 1;
dsa->references = 1;
CRYPTO_MUTEX_init(&dsa->method_mont_p_lock);
@@ -393,6 +390,21 @@ err:
return ok;
}
+DSA *DSAparams_dup(const DSA *dsa) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ ret->p = BN_dup(dsa->p);
+ ret->q = BN_dup(dsa->q);
+ ret->g = BN_dup(dsa->g);
+ if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
int DSA_generate_key(DSA *dsa) {
int ok = 0;
BN_CTX *ctx = NULL;
@@ -579,7 +591,6 @@ int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
BN_CTX *ctx;
BIGNUM u1, u2, t1;
- BN_MONT_CTX *mont = NULL;
int ret = 0;
unsigned i;
@@ -650,15 +661,14 @@ int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
goto err;
}
- mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- (CRYPTO_MUTEX *)&dsa->method_mont_p_lock,
- dsa->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
+ ctx)) {
goto err;
}
if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx,
- mont)) {
+ dsa->method_mont_p)) {
goto err;
}
@@ -740,24 +750,38 @@ err:
return ret;
}
-int DSA_size(const DSA *dsa) {
- int ret, i;
- ASN1_INTEGER bs;
- unsigned char buf[4]; /* 4 bytes looks really small.
- However, i2d_ASN1_INTEGER() will not look
- beyond the first byte, as long as the second
- parameter is NULL. */
+/* der_len_len returns the number of bytes needed to represent a length of |len|
+ * in DER. */
+static size_t der_len_len(size_t len) {
+ if (len < 0x80) {
+ return 1;
+ }
+ size_t ret = 1;
+ while (len > 0) {
+ ret++;
+ len >>= 8;
+ }
+ return ret;
+}
- i = BN_num_bits(dsa->q);
- bs.length = (i + 7) / 8;
- bs.data = buf;
- bs.type = V_ASN1_INTEGER;
- /* If the top bit is set the asn1 encoding is 1 larger. */
- buf[0] = 0xff;
-
- i = i2d_ASN1_INTEGER(&bs, NULL);
- i += i; /* r and s */
- ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
+int DSA_size(const DSA *dsa) {
+ size_t order_len = BN_num_bytes(dsa->q);
+ /* Compute the maximum length of an |order_len| byte integer. Defensively
+ * assume that the leading 0x00 is included. */
+ size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len;
+ if (integer_len < order_len) {
+ return 0;
+ }
+ /* A DSA signature is two INTEGERs. */
+ size_t value_len = 2 * integer_len;
+ if (value_len < integer_len) {
+ return 0;
+ }
+ /* Add the header. */
+ size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len;
+ if (ret < value_len) {
+ return 0;
+ }
return ret;
}
@@ -797,9 +821,9 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
BN_set_flags(&k, BN_FLG_CONSTTIME);
- if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
- ctx) == NULL) {
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
+ ctx)) {
goto err;
}
diff --git a/src/crypto/dsa/dsa_asn1.c b/src/crypto/dsa/dsa_asn1.c
index b6b3fa4d..ff5ee003 100644
--- a/src/crypto/dsa/dsa_asn1.c
+++ b/src/crypto/dsa/dsa_asn1.c
@@ -54,97 +54,286 @@
#include <openssl/dsa.h>
-#include <string.h>
+#include <assert.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include "internal.h"
+#include "../bytestring/internal.h"
-static int dsa_sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg) {
- if (operation != ASN1_OP_NEW_PRE) {
- return 1;
+static int parse_integer(CBS *cbs, BIGNUM **out) {
+ assert(*out == NULL);
+ *out = BN_new();
+ if (*out == NULL) {
+ return 0;
}
+ return BN_parse_asn1_unsigned(cbs, *out);
+}
- DSA_SIG *sig;
- sig = OPENSSL_malloc(sizeof(DSA_SIG));
- if (!sig) {
- OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE);
+static int marshal_integer(CBB *cbb, BIGNUM *bn) {
+ if (bn == NULL) {
+ /* A DSA object may be missing some components. */
+ OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
-
- memset(sig, 0, sizeof(DSA_SIG));
- *pval = (ASN1_VALUE *)sig;
- return 2;
+ return BN_marshal_asn1(cbb, bn);
}
-ASN1_SEQUENCE_cb(DSA_SIG, dsa_sig_cb) = {
- ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
- ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG);
+DSA_SIG *DSA_SIG_parse(CBS *cbs) {
+ DSA_SIG *ret = DSA_SIG_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->r) ||
+ !parse_integer(&child, &ret->s) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_SIG_free(ret);
+ return NULL;
+ }
+ return ret;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG);
+int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, sig->r) ||
+ !marshal_integer(&child, sig->s) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
+}
+DSA *DSA_parse_public_key(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->pub_key) ||
+ !parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
-static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg) {
- switch (operation) {
- case ASN1_OP_NEW_PRE:
- *pval = (ASN1_VALUE *)DSA_new();
- if (*pval) {
- return 2;
- }
- return 0;
+int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, dsa->pub_key) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
+}
- case ASN1_OP_FREE_PRE:
- DSA_free((DSA *)*pval);
- *pval = NULL;
- return 2;
+DSA *DSA_parse_parameters(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
- default:
- return 1;
+int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
}
+ return 1;
}
-ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
- ASN1_SIMPLE(DSA, version, LONG),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM),
- ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_SIMPLE(DSA, priv_key, BIGNUM)} ASN1_SEQUENCE_END_cb(DSA,
- DSAPrivateKey);
+DSA *DSA_parse_private_key(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ CBS child;
+ uint64_t version;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&child, &version)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ goto err;
+ }
+
+ if (version != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
+ goto err;
+ }
+
+ if (!parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ !parse_integer(&child, &ret->pub_key) ||
+ !parse_integer(&child, &ret->priv_key) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ goto err;
+ }
+ return ret;
+
+err:
+ DSA_free(ret);
+ return NULL;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey);
+int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&child, 0 /* version */) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !marshal_integer(&child, dsa->pub_key) ||
+ !marshal_integer(&child, dsa->priv_key) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
+}
-ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
- ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM), } ASN1_SEQUENCE_END_cb(DSA, DSAparams);
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA_SIG *ret = DSA_SIG_parse(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out_sig != NULL) {
+ DSA_SIG_free(*out_sig);
+ *out_sig = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams);
+int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_SIG_marshal(&cbb, in)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
+DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_public_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-/* DSA public key is a bit trickier... its effectively a CHOICE type decided by
- * a field called write_params which can either write out just the public key
- * as an INTEGER or the parameters and public key in a SEQUENCE. */
+int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_public_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
-ASN1_SEQUENCE(dsa_pub_internal) = {
- ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM)
-} ASN1_SEQUENCE_END_name(DSA, dsa_pub_internal);
+DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_private_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = {
- ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_EX_COMBINE(0, 0, dsa_pub_internal)
-} ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params);
+int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_private_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey);
+DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_parameters(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-DSA *DSAparams_dup(const DSA *dsa) {
- return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), (DSA*) dsa);
+int i2d_DSAparams(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_parameters(&cbb, in)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
}
diff --git a/src/crypto/dsa/dsa_test.c b/src/crypto/dsa/dsa_test.c
index 8bdaaf44..6296c8f0 100644
--- a/src/crypto/dsa/dsa_test.c
+++ b/src/crypto/dsa/dsa_test.c
@@ -65,8 +65,6 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
-#include "internal.h"
-
static int dsa_cb(int p, int n, BN_GENCB *arg);
diff --git a/src/crypto/dsa/internal.h b/src/crypto/dsa/internal.h
deleted file mode 100644
index ef991585..00000000
--- a/src/crypto/dsa/internal.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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 acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS 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 AUTHOR OR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- *
- * The DSS routines are based on patches supplied by
- * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
-
-#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
-#define OPENSSL_HEADER_DSA_INTERNAL_H
-
-#include <openssl/base.h>
-
-#include <openssl/bn.h>
-#include <openssl/ex_data.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-
-#if defined(__cplusplus)
-} /* extern C */
-#endif
-
-#endif /* OPENSSL_HEADER_DSA_INTERNAL_H */
diff --git a/src/crypto/ec/asm/p256-x86_64-asm.pl b/src/crypto/ec/asm/p256-x86_64-asm.pl
index 361a84b2..50a5fe6e 100644..100755
--- a/src/crypto/ec/asm/p256-x86_64-asm.pl
+++ b/src/crypto/ec/asm/p256-x86_64-asm.pl
@@ -1729,6 +1729,7 @@ $code.=<<___;
push %r15
sub \$32*5+8, %rsp
+.Lpoint_double_shortcut$x:
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x
mov $a_ptr, $b_ptr # backup copy
movdqu 0x10($a_ptr), %xmm1
@@ -2019,6 +2020,7 @@ $code.=<<___;
mov 0x40+8*1($b_ptr), $acc6
mov 0x40+8*2($b_ptr), $acc7
mov 0x40+8*3($b_ptr), $acc0
+ movq $b_ptr, %xmm1
lea 0x40-$bias($b_ptr), $a_ptr
lea $Z1sqr(%rsp), $r_ptr # Z1^2
@@ -2074,7 +2076,7 @@ $code.=<<___;
test $acc0, $acc0
jnz .Ladd_proceed$x # (in1infty || in2infty)?
test $acc1, $acc1
- jz .Ladd_proceed$x # is_equal(S1,S2)?
+ jz .Ladd_double$x # is_equal(S1,S2)?
movq %xmm0, $r_ptr # restore $r_ptr
pxor %xmm0, %xmm0
@@ -2087,6 +2089,13 @@ $code.=<<___;
jmp .Ladd_done$x
.align 32
+.Ladd_double$x:
+ movq %xmm1, $a_ptr # restore $a_ptr
+ movq %xmm0, $r_ptr # restore $r_ptr
+ add \$`32*(18-5)`, %rsp # difference in frame sizes
+ jmp .Lpoint_double_shortcut$x
+
+.align 32
.Ladd_proceed$x:
`&load_for_sqr("$R(%rsp)", "$src0")`
lea $Rsqr(%rsp), $r_ptr # R^2
diff --git a/src/crypto/ec/ec.c b/src/crypto/ec/ec.c
index 827cc570..8f3fa6e1 100644
--- a/src/crypto/ec/ec.c
+++ b/src/crypto/ec/ec.c
@@ -73,7 +73,7 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
#include "../internal.h"
@@ -228,10 +228,25 @@ static const struct curve_data P521 = {
#endif
const struct built_in_curve OPENSSL_built_in_curves[] = {
- {NID_secp521r1, &P521, 0},
- {NID_secp384r1, &P384, 0},
{
- NID_X9_62_prime256v1, &P256,
+ NID_secp521r1,
+ /* 1.3.132.0.35 */
+ {0x2b, 0x81, 0x04, 0x00, 0x23}, 5,
+ &P521,
+ NULL,
+ },
+ {
+ NID_secp384r1,
+ /* 1.3.132.0.34 */
+ {0x2b, 0x81, 0x04, 0x00, 0x22}, 5,
+ &P384,
+ NULL,
+ },
+ {
+ NID_X9_62_prime256v1,
+ /* 1.2.840.10045.3.1.7 */
+ {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8,
+ &P256,
#if defined(BORINGSSL_USE_INT128_CODE)
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
!defined(OPENSSL_SMALL)
@@ -240,18 +255,21 @@ const struct built_in_curve OPENSSL_built_in_curves[] = {
EC_GFp_nistp256_method,
#endif
#else
- 0,
+ NULL,
#endif
},
{
- NID_secp224r1, &P224,
+ NID_secp224r1,
+ /* 1.3.132.0.33 */
+ {0x2b, 0x81, 0x04, 0x00, 0x21}, 5,
+ &P224,
#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL)
EC_GFp_nistp224_method,
#else
- 0,
+ NULL,
#endif
},
- {NID_undef, 0, 0},
+ {NID_undef, {0}, 0, NULL, NULL},
};
/* built_in_curve_scalar_field_monts contains Montgomery contexts for
@@ -373,40 +391,50 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor) {
- if (group->curve_name != NID_undef) {
- /* |EC_GROUP_set_generator| should only be used with |EC_GROUP|s returned
- * by |EC_GROUP_new_curve_GFp|. */
+ if (group->curve_name != NID_undef || group->generator != NULL) {
+ /* |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
+ * |EC_GROUP_new_curve_GFp| and may only used once on each group. */
return 0;
}
- if (group->generator == NULL) {
- group->generator = EC_POINT_new(group);
- if (group->generator == NULL) {
- return 0;
- }
- }
+ group->generator = EC_POINT_new(group);
+ return group->generator != NULL &&
+ EC_POINT_copy(group->generator, generator) &&
+ BN_copy(&group->order, order) &&
+ BN_copy(&group->cofactor, cofactor);
+}
- if (!EC_POINT_copy(group->generator, generator)) {
- return 0;
+EC_GROUP *EC_GROUP_new_arbitrary(const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, const BIGNUM *gx,
+ const BIGNUM *gy, const BIGNUM *order,
+ const BIGNUM *cofactor) {
+ BN_CTX *ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return NULL;
}
- if (order != NULL) {
- if (!BN_copy(&group->order, order)) {
- return 0;
- }
- } else {
- BN_zero(&group->order);
+ EC_POINT *generator = NULL;
+ EC_GROUP *ret = EC_GROUP_new_curve_GFp(p, a, b, ctx);
+ if (ret == NULL) {
+ goto err;
}
- if (cofactor != NULL) {
- if (!BN_copy(&group->cofactor, cofactor)) {
- return 0;
- }
- } else {
- BN_zero(&group->cofactor);
+ generator = EC_POINT_new(ret);
+ if (generator == NULL ||
+ !EC_POINT_set_affine_coordinates_GFp(ret, generator, gx, gy, ctx) ||
+ !EC_GROUP_set_generator(ret, generator, order, cofactor)) {
+ goto err;
}
- return 1;
+ EC_POINT_free(generator);
+ BN_CTX_free(ctx);
+ return ret;
+
+err:
+ EC_POINT_free(generator);
+ EC_GROUP_free(ret);
+ BN_CTX_free(ctx);
+ return NULL;
}
static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) {
@@ -887,3 +915,21 @@ void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
abort();
}
}
+
+size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
+ size_t max_num_curves) {
+ unsigned num_built_in_curves;
+ for (num_built_in_curves = 0;; num_built_in_curves++) {
+ if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) {
+ break;
+ }
+ }
+
+ unsigned i;
+ for (i = 0; i < max_num_curves && i < num_built_in_curves; i++) {
+ out_curves[i].comment = OPENSSL_built_in_curves[i].data->comment;
+ out_curves[i].nid = OPENSSL_built_in_curves[i].nid;
+ }
+
+ return num_built_in_curves;
+}
diff --git a/src/crypto/ec/ec_asn1.c b/src/crypto/ec/ec_asn1.c
index a085be53..f31e1587 100644
--- a/src/crypto/ec/ec_asn1.c
+++ b/src/crypto/ec/ec_asn1.c
@@ -53,490 +53,453 @@
#include <openssl/ec.h>
+#include <limits.h>
#include <string.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
+#include "../bytestring/internal.h"
+
+
+static const uint8_t kParametersTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0;
+static const uint8_t kPublicKeyTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
+
+EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
+ CBS ec_private_key, private_key;
+ uint64_t version;
+ if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&ec_private_key, &version) ||
+ version != 1 ||
+ !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return NULL;
+ }
-
-typedef struct x9_62_fieldid_st {
- ASN1_OBJECT *fieldType;
- union {
- char *ptr;
- /* NID_X9_62_prime_field */
- ASN1_INTEGER *prime;
- /* anything else */
- ASN1_TYPE *other;
- } p;
-} X9_62_FIELDID;
-
-ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
-
-ASN1_ADB(X9_62_FIELDID) = {
- ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
-} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
-
-ASN1_SEQUENCE(X9_62_FIELDID) = {
- ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
- ASN1_ADB_OBJECT(X9_62_FIELDID)
-} ASN1_SEQUENCE_END(X9_62_FIELDID);
-
-typedef struct x9_62_curve_st {
- ASN1_OCTET_STRING *a;
- ASN1_OCTET_STRING *b;
- ASN1_BIT_STRING *seed;
-} X9_62_CURVE;
-
-ASN1_SEQUENCE(X9_62_CURVE) = {
- ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
- ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
- ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(X9_62_CURVE);
-
-typedef struct ec_parameters_st {
- long version;
- X9_62_FIELDID *fieldID;
- X9_62_CURVE *curve;
- ASN1_OCTET_STRING *base;
- ASN1_INTEGER *order;
- ASN1_INTEGER *cofactor;
-} ECPARAMETERS;
-
-DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
-
-ASN1_SEQUENCE(ECPARAMETERS) = {
- ASN1_SIMPLE(ECPARAMETERS, version, LONG),
- ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
- ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
- ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
- ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
- ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(ECPARAMETERS);
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
-
-typedef struct ecpk_parameters_st {
- int type;
- union {
- ASN1_OBJECT *named_curve;
- ECPARAMETERS *parameters;
- } value;
-} ECPKPARAMETERS;
-
-/* SEC1 ECPrivateKey */
-typedef struct ec_privatekey_st {
- long version;
- ASN1_OCTET_STRING *privateKey;
- ECPKPARAMETERS *parameters;
- ASN1_BIT_STRING *publicKey;
-} EC_PRIVATEKEY;
-
-DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS);
-
-ASN1_CHOICE(ECPKPARAMETERS) = {
- ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
- ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
-} ASN1_CHOICE_END(ECPKPARAMETERS);
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
-
-DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY);
-
-ASN1_SEQUENCE(EC_PRIVATEKEY) = {
- ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
- ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
- ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
- ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1),
-} ASN1_SEQUENCE_END(EC_PRIVATEKEY);
-
-IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
-
-
-ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
- ECPKPARAMETERS *params) {
- int ok = 0, nid;
- ECPKPARAMETERS *ret = params;
-
- if (ret == NULL) {
- ret = ECPKPARAMETERS_new();
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- return NULL;
+ /* Parse the optional parameters field. */
+ EC_GROUP *inner_group = NULL;
+ EC_KEY *ret = NULL;
+ if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) {
+ /* Per SEC 1, as an alternative to omitting it, one is allowed to specify
+ * this field and put in a NULL to mean inheriting this value. This was
+ * omitted in a previous version of this logic without problems, so leave it
+ * unimplemented. */
+ CBS child;
+ if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ goto err;
+ }
+ inner_group = EC_KEY_parse_parameters(&child);
+ if (inner_group == NULL) {
+ goto err;
+ }
+ if (group == NULL) {
+ group = inner_group;
+ } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
+ /* If a group was supplied externally, it must match. */
+ OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
+ goto err;
+ }
+ if (CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ goto err;
}
- } else {
- ASN1_OBJECT_free(ret->value.named_curve);
}
- /* use the ASN.1 OID to describe the the elliptic curve parameters. */
- nid = EC_GROUP_get_curve_name(group);
- if (nid) {
- ret->type = 0;
- ret->value.named_curve = (ASN1_OBJECT*) OBJ_nid2obj(nid);
- ok = ret->value.named_curve != NULL;
+ if (group == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
+ goto err;
}
- if (!ok) {
- ECPKPARAMETERS_free(ret);
- return NULL;
+ ret = EC_KEY_new();
+ if (ret == NULL || !EC_KEY_set_group(ret, group)) {
+ goto err;
}
- return ret;
-}
-
-EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) {
- EC_GROUP *ret = NULL;
- int nid = NID_undef;
+ /* Although RFC 5915 specifies the length of the key, OpenSSL historically
+ * got this wrong, so accept any length. See upstream's
+ * 30cd4ff294252c4b6a4b69cbef6a5b4117705d22. */
+ ret->priv_key =
+ BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
+ ret->pub_key = EC_POINT_new(group);
+ if (ret->priv_key == NULL || ret->pub_key == NULL) {
+ goto err;
+ }
- if (params == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
- return NULL;
+ if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(group)) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER);
+ goto err;
}
- if (params->type == 0) {
- nid = OBJ_obj2nid(params->value.named_curve);
- } else if (params->type == 1) {
- /* We don't support arbitary curves so we attempt to recognise it from the
- * group order. */
- const ECPARAMETERS *ecparams = params->value.parameters;
- unsigned i;
- const struct built_in_curve *curve;
-
- for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
- curve = &OPENSSL_built_in_curves[i];
- const unsigned param_len = curve->data->param_len;
- if ((unsigned) ecparams->order->length == param_len &&
- memcmp(ecparams->order->data, &curve->data->data[param_len * 5],
- param_len) == 0) {
- nid = curve->nid;
- break;
- }
+ if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
+ CBS child, public_key;
+ uint8_t padding;
+ if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) ||
+ !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
+ /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then
+ * encoded as a BIT STRING with bits ordered as in the DER encoding. */
+ !CBS_get_u8(&public_key, &padding) ||
+ padding != 0 ||
+ /* Explicitly check |public_key| is non-empty to save the conversion
+ * form later. */
+ CBS_len(&public_key) == 0 ||
+ !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
+ CBS_len(&public_key), NULL) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ goto err;
}
+
+ /* Save the point conversion form.
+ * TODO(davidben): Consider removing this. */
+ ret->conv_form = (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01);
+ } else {
+ /* Compute the public key instead. */
+ if (!EC_POINT_mul(group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) {
+ goto err;
+ }
+ /* Remember the original private-key-only encoding.
+ * TODO(davidben): Consider removing this. */
+ ret->enc_flag |= EC_PKEY_NO_PUBKEY;
}
- if (nid == NID_undef) {
- OPENSSL_PUT_ERROR(EC, EC_R_NON_NAMED_CURVE);
- return NULL;
+ if (CBS_len(&ec_private_key) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ goto err;
}
- ret = EC_GROUP_new_by_curve_name(nid);
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
- return NULL;
+ /* Ensure the resulting key is valid. */
+ if (!EC_KEY_check_key(ret)) {
+ goto err;
}
+ EC_GROUP_free(inner_group);
return ret;
+
+err:
+ EC_KEY_free(ret);
+ EC_GROUP_free(inner_group);
+ return NULL;
}
-static EC_GROUP *d2i_ECPKParameters(EC_GROUP **groupp, const uint8_t **inp,
- long len) {
- EC_GROUP *group = NULL;
- ECPKPARAMETERS *params = NULL;
- const uint8_t *in = *inp;
+int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
+ unsigned enc_flags) {
+ if (key == NULL || key->group == NULL || key->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
- params = d2i_ECPKPARAMETERS(NULL, &in, len);
- if (params == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_D2I_ECPKPARAMETERS_FAILURE);
- ECPKPARAMETERS_free(params);
- return NULL;
+ CBB ec_private_key, private_key;
+ if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) ||
+ !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !BN_bn2cbb_padded(&private_key,
+ BN_num_bytes(EC_GROUP_get0_order(key->group)),
+ key->priv_key)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+ return 0;
}
- group = ec_asn1_pkparameters2group(params);
- if (group == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_PKPARAMETERS2GROUP_FAILURE);
- ECPKPARAMETERS_free(params);
- return NULL;
+ if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
+ CBB child;
+ if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
+ !EC_KEY_marshal_curve_name(&child, key->group) ||
+ !CBB_flush(&ec_private_key)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+ return 0;
+ }
}
- if (groupp) {
- EC_GROUP_free(*groupp);
- *groupp = group;
+ /* TODO(fork): replace this flexibility with sensible default? */
+ if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
+ CBB child, public_key;
+ if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) ||
+ !CBB_add_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
+ /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then
+ * encoded as a BIT STRING with bits ordered as in the DER encoding. */
+ !CBB_add_u8(&public_key, 0 /* padding */) ||
+ !EC_POINT_point2cbb(&public_key, key->group, key->pub_key,
+ key->conv_form, NULL) ||
+ !CBB_flush(&ec_private_key)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+ return 0;
+ }
+ }
+
+ if (!CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+ return 0;
}
- ECPKPARAMETERS_free(params);
- *inp = in;
- return group;
+ return 1;
}
-static int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
- int ret = 0;
- ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(group, NULL);
- if (tmp == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_GROUP2PKPARAMETERS_FAILURE);
+/* is_unsigned_integer returns one if |cbs| is a valid unsigned DER INTEGER and
+ * zero otherwise. */
+static int is_unsigned_integer(const CBS *cbs) {
+ if (CBS_len(cbs) == 0) {
return 0;
}
- ret = i2d_ECPKPARAMETERS(tmp, outp);
- if (ret == 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_I2D_ECPKPARAMETERS_FAILURE);
- ECPKPARAMETERS_free(tmp);
+ uint8_t byte = CBS_data(cbs)[0];
+ if ((byte & 0x80) ||
+ (byte == 0 && CBS_len(cbs) > 1 && (CBS_data(cbs)[1] & 0x80) == 0)) {
+ /* Negative or not minimally-encoded. */
return 0;
}
- ECPKPARAMETERS_free(tmp);
- return ret;
+ return 1;
}
-EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **inp, long len) {
- int ok = 0;
- EC_KEY *ret = NULL;
- EC_PRIVATEKEY *priv_key = NULL;
-
- const uint8_t *in = *inp;
- priv_key = d2i_EC_PRIVATEKEY(NULL, &in, len);
- if (priv_key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- return NULL;
+/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */
+static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01};
+
+static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
+ CBS *out_b, CBS *out_base_x,
+ CBS *out_base_y, CBS *out_order) {
+ /* See RFC 3279, section 2.3.5. Note that RFC 3279 calls this structure an
+ * ECParameters while RFC 5480 calls it a SpecifiedECDomain. */
+ CBS params, field_id, field_type, curve, base;
+ uint64_t version;
+ if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&params, &version) ||
+ version != 1 ||
+ !CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
+ CBS_len(&field_type) != sizeof(kPrimeField) ||
+ memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 ||
+ !CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) ||
+ !is_unsigned_integer(out_prime) ||
+ CBS_len(&field_id) != 0 ||
+ !CBS_get_asn1(&params, &curve, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&curve, out_a, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&curve, out_b, CBS_ASN1_OCTETSTRING) ||
+ /* |curve| has an optional BIT STRING seed which we ignore. */
+ !CBS_get_asn1(&params, &base, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&params, out_order, CBS_ASN1_INTEGER) ||
+ !is_unsigned_integer(out_order)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return 0;
}
- if (a == NULL || *a == NULL) {
- ret = EC_KEY_new();
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- } else {
- ret = *a;
- }
+ /* |params| has an optional cofactor which we ignore. With the optional seed
+ * in |curve|, a group already has arbitrarily many encodings. Parse enough to
+ * uniquely determine the curve. */
- if (priv_key->parameters) {
- EC_GROUP_free(ret->group);
- ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
+ /* Require that the base point use uncompressed form. */
+ uint8_t form;
+ if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) {
+ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
+ return 0;
}
- if (ret->group == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
+ if (CBS_len(&base) % 2 != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return 0;
}
+ size_t field_len = CBS_len(&base) / 2;
+ CBS_init(out_base_x, CBS_data(&base), field_len);
+ CBS_init(out_base_y, CBS_data(&base) + field_len, field_len);
- ret->version = priv_key->version;
+ return 1;
+}
- if (priv_key->privateKey) {
- ret->priv_key =
- BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
- M_ASN1_STRING_length(priv_key->privateKey), ret->priv_key);
- if (ret->priv_key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
- }
- } else {
- OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PRIVATE_KEY);
- goto err;
+/* integers_equal returns one if |a| and |b| are equal, up to leading zeros, and
+ * zero otherwise. */
+static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) {
+ /* Remove leading zeros from |a| and |b|. */
+ CBS a_copy = *a;
+ while (CBS_len(&a_copy) > 0 && CBS_data(&a_copy)[0] == 0) {
+ CBS_skip(&a_copy, 1);
}
-
- if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(ret->group)) >= 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER);
- goto err;
+ while (b_len > 0 && b[0] == 0) {
+ b++;
+ b_len--;
}
+ return CBS_mem_equal(&a_copy, b, b_len);
+}
- EC_POINT_free(ret->pub_key);
- ret->pub_key = EC_POINT_new(ret->group);
- if (ret->pub_key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
+EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
+ CBS named_curve;
+ if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return NULL;
}
- if (priv_key->publicKey) {
- const uint8_t *pub_oct;
- int pub_oct_len;
-
- pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
- pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
- /* The first byte (the point conversion form) must be present. */
- if (pub_oct_len <= 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
- goto err;
- }
- /* Save the point conversion form. */
- ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
- if (!EC_POINT_oct2point(ret->group, ret->pub_key, pub_oct, pub_oct_len,
- NULL)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
+ /* Look for a matching curve. */
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ if (CBS_len(&named_curve) == curve->oid_len &&
+ memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) {
+ return EC_GROUP_new_by_curve_name(curve->nid);
}
- } else {
- if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL,
- NULL)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
- }
- /* Remember the original private-key-only encoding. */
- ret->enc_flag |= EC_PKEY_NO_PUBKEY;
}
- if (a) {
- *a = ret;
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return NULL;
+}
+
+int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
+ int nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef) {
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return 0;
}
- *inp = in;
- ok = 1;
-err:
- if (!ok) {
- if (a == NULL || *a != ret) {
- EC_KEY_free(ret);
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ if (curve->nid == nid) {
+ CBB child;
+ return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
+ CBB_add_bytes(&child, curve->oid, curve->oid_len) &&
+ CBB_flush(cbb);
}
- ret = NULL;
}
- EC_PRIVATEKEY_free(priv_key);
-
- return ret;
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return 0;
}
-int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
- int ret = 0, ok = 0;
- uint8_t *buffer = NULL;
- size_t buf_len = 0, tmp_len;
- EC_PRIVATEKEY *priv_key = NULL;
-
- if (key == NULL || key->group == NULL || key->priv_key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
- goto err;
+EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
+ if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
+ return EC_KEY_parse_curve_name(cbs);
}
- priv_key = EC_PRIVATEKEY_new();
- if (priv_key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
+ /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
+ * of named curves.
+ *
+ * TODO(davidben): Remove support for this. */
+ CBS prime, a, b, base_x, base_y, order;
+ if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
+ &order)) {
+ return NULL;
}
- priv_key->version = key->version;
-
- buf_len = BN_num_bytes(&key->group->order);
- buffer = OPENSSL_malloc(buf_len);
- if (buffer == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
+ /* Look for a matching prime curve. */
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ const unsigned param_len = curve->data->param_len;
+ /* |curve->data->data| is ordered p, a, b, x, y, order, each component
+ * zero-padded up to the field length. Although SEC 1 states that the
+ * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
+ * |a| and |b|, so this comparison must allow omitting leading zeros. (This
+ * is relevant for P-521 whose |b| has a leading 0.) */
+ if (integers_equal(&prime, curve->data->data, param_len) &&
+ integers_equal(&a, curve->data->data + param_len, param_len) &&
+ integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
+ integers_equal(&base_x, curve->data->data + param_len * 3, param_len) &&
+ integers_equal(&base_y, curve->data->data + param_len * 4, param_len) &&
+ integers_equal(&order, curve->data->data + param_len * 5, param_len)) {
+ return EC_GROUP_new_by_curve_name(curve->nid);
+ }
}
- if (!BN_bn2bin_padded(buffer, buf_len, key->priv_key)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
- }
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return NULL;
+}
- if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_ASN1_LIB);
- goto err;
+EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) {
+ /* This function treats its |out| parameter differently from other |d2i|
+ * functions. If supplied, take the group from |*out|. */
+ const EC_GROUP *group = NULL;
+ if (out != NULL && *out != NULL) {
+ group = EC_KEY_get0_group(*out);
}
- /* TODO(fork): replace this flexibility with key sensible default? */
- if (!(key->enc_flag & EC_PKEY_NO_PARAMETERS)) {
- if ((priv_key->parameters = ec_asn1_group2pkparameters(
- key->group, priv_key->parameters)) == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
- }
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return NULL;
}
-
- /* TODO(fork): replace this flexibility with key sensible default? */
- if (!(key->enc_flag & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
- priv_key->publicKey = M_ASN1_BIT_STRING_new();
- if (priv_key->publicKey == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- tmp_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
- 0, NULL);
-
- if (tmp_len > buf_len) {
- uint8_t *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
- if (!tmp_buffer) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- buffer = tmp_buffer;
- buf_len = tmp_len;
- }
-
- if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, buffer,
- buf_len, NULL)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
- }
-
- priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
- if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_ASN1_LIB);
- goto err;
- }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group);
+ if (ret == NULL) {
+ return NULL;
}
-
- ret = i2d_EC_PRIVATEKEY(priv_key, outp);
- if (ret == 0) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- goto err;
+ if (out != NULL) {
+ EC_KEY_free(*out);
+ *out = ret;
}
- ok = 1;
-
-err:
- OPENSSL_free(buffer);
- EC_PRIVATEKEY_free(priv_key);
- return (ok ? ret : 0);
+ *inp = CBS_data(&cbs);
+ return ret;
}
-int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
- if (key == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) {
+ CBB_cleanup(&cbb);
+ return -1;
}
- return i2d_ECPKParameters(key->group, outp);
+ return CBB_finish_i2d(&cbb, outp);
}
-EC_KEY *d2i_ECParameters(EC_KEY **key, const uint8_t **inp, long len) {
- EC_KEY *ret;
-
- if (inp == NULL || *inp == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) {
+ if (len < 0) {
return NULL;
}
- if (key == NULL || *key == NULL) {
- ret = EC_KEY_new();
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- } else {
- ret = *key;
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EC_GROUP *group = EC_KEY_parse_parameters(&cbs);
+ if (group == NULL) {
+ return NULL;
}
- if (!d2i_ECPKParameters(&ret->group, inp, len)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- if (key == NULL || *key == NULL) {
- EC_KEY_free(ret);
- }
+ EC_KEY *ret = EC_KEY_new();
+ if (ret == NULL || !EC_KEY_set_group(ret, group)) {
+ EC_GROUP_free(group);
+ EC_KEY_free(ret);
return NULL;
}
+ EC_GROUP_free(group);
- if (key) {
- *key = ret;
+ if (out_key != NULL) {
+ EC_KEY_free(*out_key);
+ *out_key = ret;
}
+ *inp = CBS_data(&cbs);
return ret;
}
+int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
+ if (key == NULL || key->group == NULL) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !EC_KEY_marshal_curve_name(&cbb, key->group)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
+
EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
EC_KEY *ret = NULL;
if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+ return NULL;
}
ret = *keyp;
if (ret->pub_key == NULL &&
(ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- return 0;
+ return NULL;
}
if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
- return 0;
+ return NULL;
}
/* save the point conversion form */
ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
diff --git a/src/crypto/ec/ec_key.c b/src/crypto/ec/ec_key.c
index d3bf4c61..fee71fed 100644
--- a/src/crypto/ec/ec_key.c
+++ b/src/crypto/ec/ec_key.c
@@ -85,7 +85,7 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); }
EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
- EC_KEY *ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
+ EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY));
if (ret == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -100,7 +100,6 @@ EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
METHOD_ref(ret->ecdsa_meth);
}
- ret->version = 1;
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
ret->references = 1;
@@ -209,8 +208,6 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) {
/* copy the rest */
dest->enc_flag = src->enc_flag;
dest->conv_form = src->conv_form;
- dest->version = src->version;
- dest->flags = src->flags;
return dest;
}
@@ -368,15 +365,24 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
return 0;
}
ctx = BN_CTX_new();
+
+ if (ctx == NULL) {
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
point = EC_POINT_new(key->group);
- if (ctx == NULL ||
- point == NULL) {
+ if (point == NULL) {
goto err;
}
tx = BN_CTX_get(ctx);
ty = BN_CTX_get(ctx);
+ if (tx == NULL ||
+ ty == NULL) {
+ goto err;
+ }
if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
!EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) {
@@ -401,6 +407,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
ok = 1;
err:
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
diff --git a/src/crypto/ec/ec_montgomery.c b/src/crypto/ec/ec_montgomery.c
index 1d4113db..35df3651 100644
--- a/src/crypto/ec/ec_montgomery.c
+++ b/src/crypto/ec/ec_montgomery.c
@@ -79,31 +79,18 @@ int ec_GFp_mont_group_init(EC_GROUP *group) {
ok = ec_GFp_simple_group_init(group);
group->mont = NULL;
- group->one = NULL;
return ok;
}
void ec_GFp_mont_group_finish(EC_GROUP *group) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
ec_GFp_simple_group_finish(group);
}
-void ec_GFp_mont_group_clear_finish(EC_GROUP *group) {
- BN_MONT_CTX_free(group->mont);
- group->mont = NULL;
- BN_clear_free(group->one);
- group->one = NULL;
- ec_GFp_simple_group_clear_finish(group);
-}
-
int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
BN_MONT_CTX_free(dest->mont);
dest->mont = NULL;
- BN_clear_free(dest->one);
- dest->one = NULL;
if (!ec_GFp_simple_group_copy(dest, src)) {
return 0;
@@ -118,12 +105,6 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
goto err;
}
}
- if (src->one != NULL) {
- dest->one = BN_dup(src->one);
- if (dest->one == NULL) {
- goto err;
- }
- }
return 1;
@@ -137,13 +118,10 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
BN_MONT_CTX *mont = NULL;
- BIGNUM *one = NULL;
int ret = 0;
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
@@ -160,29 +138,20 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
- one = BN_new();
- if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) {
- goto err;
- }
group->mont = mont;
mont = NULL;
- group->one = one;
- one = NULL;
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
}
err:
BN_CTX_free(new_ctx);
BN_MONT_CTX_free(mont);
- BN_free(one);
return ret;
}
@@ -226,19 +195,6 @@ int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return BN_from_montgomery(r, a, group->mont, ctx);
}
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
- BN_CTX *ctx) {
- if (group->one == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
- return 0;
- }
-
- if (!BN_copy(r, group->one)) {
- return 0;
- }
- return 1;
-}
-
static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group,
const EC_POINT* pub_key,
BN_CTX *ctx) {
@@ -259,21 +215,108 @@ err:
return ret;
}
+static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
+ if (EC_POINT_is_at_infinity(group, point)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
+ return 0;
+ }
+
+ BN_CTX *new_ctx = NULL;
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ int ret = 0;
+
+ BN_CTX_start(ctx);
+
+ if (BN_cmp(&point->Z, &group->one) == 0) {
+ /* |point| is already affine. */
+ if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) {
+ goto err;
+ }
+ if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) {
+ goto err;
+ }
+ } else {
+ /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
+
+ BIGNUM *Z_1 = BN_CTX_get(ctx);
+ BIGNUM *Z_2 = BN_CTX_get(ctx);
+ BIGNUM *Z_3 = BN_CTX_get(ctx);
+ if (Z_1 == NULL ||
+ Z_2 == NULL ||
+ Z_3 == NULL) {
+ goto err;
+ }
+
+ /* The straightforward way to calculate the inverse of a Montgomery-encoded
+ * value where the result is Montgomery-encoded is:
+ *
+ * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|.
+ *
+ * This is equivalent, but more efficient, because |BN_from_montgomery|
+ * is more efficient (at least in theory) than |BN_to_montgomery|, since it
+ * doesn't have to do the multiplication before the reduction. */
+ if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) ||
+ !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) ||
+ !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) {
+ goto err;
+ }
+
+ if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) {
+ goto err;
+ }
+
+ /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
+ * and then calling |BN_from_montgomery| again to convert the |y|
+ * coordinate below, convert the common factor |Z_2| once now, saving one
+ * reduction. */
+ if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+
+ if (x != NULL) {
+ if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+ }
+
+ if (y != NULL) {
+ if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) ||
+ !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) {
+ goto err;
+ }
+ }
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
const EC_METHOD *EC_GFp_mont_method(void) {
static const EC_METHOD ret = {
ec_GFp_mont_group_init,
ec_GFp_mont_group_finish,
- ec_GFp_mont_group_clear_finish,
ec_GFp_mont_group_copy,
ec_GFp_mont_group_set_curve,
- ec_GFp_simple_point_get_affine_coordinates,
+ ec_GFp_mont_point_get_affine_coordinates,
ec_wNAF_mul /* XXX: Not constant time. */,
ec_GFp_mont_check_pub_key_order,
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
};
return &ret;
diff --git a/src/crypto/ec/ec_test.cc b/src/crypto/ec/ec_test.cc
index 2088e72b..ce9d99f3 100644
--- a/src/crypto/ec/ec_test.cc
+++ b/src/crypto/ec/ec_test.cc
@@ -17,6 +17,7 @@
#include <vector>
+#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
@@ -34,6 +35,36 @@ static const uint8_t kECKeyWithoutPublic[] = {
0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
};
+// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
+// spelled out rather than using a named curve.
+static const uint8_t kECKeySpecifiedCurve[] = {
+ 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
+ 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
+ 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
+ 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
+ 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
+ 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
+ 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+ 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
+ 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
+ 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
+ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
+ 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
+ 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
+ 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
+ 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
+ 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
+ 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
+ 0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
+};
+
// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
// the private key is one. The private key is incorrectly encoded without zero
// padding.
@@ -66,9 +97,10 @@ static const uint8_t kECKeyWithZeros[] = {
// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
// result or nullptr on error.
static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) {
- const uint8_t *inp = in;
- ScopedEC_KEY ret(d2i_ECPrivateKey(NULL, &inp, in_len));
- if (!ret || inp != in + in_len) {
+ CBS cbs;
+ CBS_init(&cbs, in, in_len);
+ ScopedEC_KEY ret(EC_KEY_parse_private_key(&cbs, NULL));
+ if (!ret || CBS_len(&cbs) != 0) {
return nullptr;
}
return ret;
@@ -76,14 +108,21 @@ static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) {
// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
// returns true on success or false on error.
-static bool EncodeECPrivateKey(std::vector<uint8_t> *out, EC_KEY *key) {
- int len = i2d_ECPrivateKey(key, NULL);
- out->resize(len);
- uint8_t *outp = out->data();
- return i2d_ECPrivateKey(key, &outp) == len;
+static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
+ ScopedCBB cbb;
+ uint8_t *der;
+ size_t der_len;
+ if (!CBB_init(cbb.get(), 0) ||
+ !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
+ return false;
+ }
+ out->assign(der, der + der_len);
+ OPENSSL_free(der);
+ return true;
}
-bool Testd2i_ECPrivateKey() {
+static bool Testd2i_ECPrivateKey() {
ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic,
sizeof(kECKeyWithoutPublic));
if (!key) {
@@ -172,7 +211,39 @@ static bool TestZeroPadding() {
return true;
}
-bool TestSetAffine(const int nid) {
+static bool TestSpecifiedCurve() {
+ // Test keys with specified curves may be decoded.
+ ScopedEC_KEY key =
+ DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
+ if (!key) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ // The group should have been interpreted as P-256.
+ if (EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())) !=
+ NID_X9_62_prime256v1) {
+ fprintf(stderr, "Curve name incorrect.\n");
+ return false;
+ }
+
+ // Encoding the key should still use named form.
+ std::vector<uint8_t> out;
+ if (!EncodeECPrivateKey(&out, key.get())) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ if (std::vector<uint8_t>(kECKeyWithoutPublic,
+ kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
+ out) {
+ fprintf(stderr, "Serialisation of key was incorrect.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestSetAffine(const int nid) {
ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
if (!key) {
return false;
@@ -240,16 +311,206 @@ bool TestSetAffine(const int nid) {
return true;
}
+static bool TestArbitraryCurve() {
+ // Make a P-256 key and extract the affine coordinates.
+ ScopedEC_KEY key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ if (!key || !EC_KEY_generate_key(key.get())) {
+ return false;
+ }
+
+ // Make an arbitrary curve which is identical to P-256.
+ static const uint8_t kP[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const uint8_t kA[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ };
+ static const uint8_t kB[] = {
+ 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
+ 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+ 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
+ };
+ static const uint8_t kX[] = {
+ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
+ 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
+ 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
+ };
+ static const uint8_t kY[] = {
+ 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
+ 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
+ 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
+ };
+ static const uint8_t kOrder[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
+ 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
+ };
+ ScopedBN_CTX ctx(BN_CTX_new());
+ ScopedBIGNUM p(BN_bin2bn(kP, sizeof(kP), nullptr));
+ ScopedBIGNUM a(BN_bin2bn(kA, sizeof(kA), nullptr));
+ ScopedBIGNUM b(BN_bin2bn(kB, sizeof(kB), nullptr));
+ ScopedBIGNUM gx(BN_bin2bn(kX, sizeof(kX), nullptr));
+ ScopedBIGNUM gy(BN_bin2bn(kY, sizeof(kY), nullptr));
+ ScopedBIGNUM order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
+ ScopedBIGNUM cofactor(BN_new());
+ if (!ctx || !p || !a || !b || !gx || !gy || !order || !cofactor ||
+ !BN_set_word(cofactor.get(), 1)) {
+ return false;
+ }
+
+ ScopedEC_GROUP group(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
+ if (!group) {
+ return false;
+ }
+ ScopedEC_POINT generator(EC_POINT_new(group.get()));
+ if (!generator ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(),
+ gx.get(), gy.get(), ctx.get()) ||
+ !EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
+ cofactor.get())) {
+ return false;
+ }
+
+ // |group| should not have a curve name.
+ if (EC_GROUP_get_curve_name(group.get()) != NID_undef) {
+ return false;
+ }
+
+ // Copy |key| to |key2| using |group|.
+ ScopedEC_KEY key2(EC_KEY_new());
+ ScopedEC_POINT point(EC_POINT_new(group.get()));
+ ScopedBIGNUM x(BN_new()), y(BN_new());
+ if (!key2 || !point || !x || !y ||
+ !EC_KEY_set_group(key2.get(), group.get()) ||
+ !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) ||
+ !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
+ EC_KEY_get0_public_key(key.get()),
+ x.get(), y.get(), nullptr) ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(),
+ y.get(), nullptr) ||
+ !EC_KEY_set_public_key(key2.get(), point.get())) {
+ fprintf(stderr, "Could not copy key.\n");
+ return false;
+ }
+
+ // The key must be valid according to the new group too.
+ if (!EC_KEY_check_key(key2.get())) {
+ fprintf(stderr, "Copied key is not valid.\n");
+ return false;
+ }
+
+ // Repeat the process for |EC_GROUP_new_arbitrary|.
+ group.reset(EC_GROUP_new_arbitrary(p.get(), a.get(), b.get(), gx.get(),
+ gy.get(), order.get(), cofactor.get()));
+ if (!group) {
+ return false;
+ }
+
+ // |group| should not have a curve name.
+ if (EC_GROUP_get_curve_name(group.get()) != NID_undef) {
+ return false;
+ }
+
+ // Copy |key| to |key2| using |group|.
+ key2.reset(EC_KEY_new());
+ point.reset(EC_POINT_new(group.get()));
+ if (!key2 || !point ||
+ !EC_KEY_set_group(key2.get(), group.get()) ||
+ !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(),
+ y.get(), nullptr) ||
+ !EC_KEY_set_public_key(key2.get(), point.get())) {
+ fprintf(stderr, "Could not copy key.\n");
+ return false;
+ }
+
+ // The key must be valid according to the new group too.
+ if (!EC_KEY_check_key(key2.get())) {
+ fprintf(stderr, "Copied key is not valid.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestAddingEqualPoints(int nid) {
+ ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
+ if (!key) {
+ return false;
+ }
+
+ const EC_GROUP *const group = EC_KEY_get0_group(key.get());
+
+ if (!EC_KEY_generate_key(key.get())) {
+ fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ ScopedEC_POINT p1(EC_POINT_new(group));
+ ScopedEC_POINT p2(EC_POINT_new(group));
+ ScopedEC_POINT double_p1(EC_POINT_new(group));
+ ScopedEC_POINT p1_plus_p2(EC_POINT_new(group));
+ if (!p1 || !p2 || !double_p1 || !p1_plus_p2) {
+ return false;
+ }
+
+ if (!EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())) ||
+ !EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))) {
+ fprintf(stderr, "EC_POINT_COPY failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ ScopedBN_CTX ctx(BN_CTX_new());
+ if (!ctx) {
+ return false;
+ }
+
+ if (!EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()) ||
+ !EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())) {
+ fprintf(stderr, "Point operation failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()) != 0) {
+ fprintf(stderr, "A+A != 2A for nid %d", nid);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ForEachCurve(bool (*test_func)(int nid)) {
+ const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
+ std::vector<EC_builtin_curve> curves(num_curves);
+ EC_get_builtin_curves(curves.data(), num_curves);
+
+ for (const auto& curve : curves) {
+ if (!test_func(curve.nid)) {
+ fprintf(stderr, "Test failed for %s\n", curve.comment);
+ return false;
+ }
+ }
+
+ return true;
+}
+
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!Testd2i_ECPrivateKey() ||
!TestZeroPadding() ||
- !TestSetAffine(NID_secp224r1) ||
- !TestSetAffine(NID_X9_62_prime256v1) ||
- !TestSetAffine(NID_secp384r1) ||
- !TestSetAffine(NID_secp521r1)) {
+ !TestSpecifiedCurve() ||
+ !ForEachCurve(TestSetAffine) ||
+ !ForEachCurve(TestAddingEqualPoints) ||
+ !TestArbitraryCurve()) {
fprintf(stderr, "failed\n");
return 1;
}
diff --git a/src/crypto/ec/example_mul.c b/src/crypto/ec/example_mul.c
index ebb724fa..a2bdd527 100644
--- a/src/crypto/ec/example_mul.c
+++ b/src/crypto/ec/example_mul.c
@@ -70,10 +70,10 @@
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/ec.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
-int example_EC_POINT_mul(void) {
+static int example_EC_POINT_mul(void) {
/* This example ensures that 10×∞ + G = G, in P-256. */
EC_GROUP *group = NULL;
EC_POINT *p = NULL, *result = NULL;
diff --git a/src/crypto/ec/internal.h b/src/crypto/ec/internal.h
index bcc0e37f..f2cbb961 100644
--- a/src/crypto/ec/internal.h
+++ b/src/crypto/ec/internal.h
@@ -80,18 +80,11 @@ extern "C" {
struct ec_method_st {
- /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
int (*group_init)(EC_GROUP *);
void (*group_finish)(EC_GROUP *);
- void (*group_clear_finish)(EC_GROUP *);
int (*group_copy)(EC_GROUP *, const EC_GROUP *);
-
- /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
- /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
-
- /* used by EC_POINT_get_affine_coordinates_GFp: */
int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
BIGNUM *x, BIGNUM *y, BN_CTX *);
@@ -112,8 +105,6 @@ struct ec_method_st {
int (*check_pub_key_order)(const EC_GROUP *group, const EC_POINT *pub_key,
BN_CTX *ctx);
- /* internal functions */
-
/* 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that the
* same implementations of point operations can be used with different
* optimized implementations of expensive field operations: */
@@ -125,7 +116,6 @@ struct ec_method_st {
BN_CTX *); /* e.g. to Montgomery */
int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *); /* e.g. from Montgomery */
- int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
} /* EC_METHOD */;
const EC_METHOD* EC_GFp_mont_method(void);
@@ -133,7 +123,7 @@ const EC_METHOD* EC_GFp_mont_method(void);
struct ec_group_st {
const EC_METHOD *meth;
- EC_POINT *generator; /* optional */
+ EC_POINT *generator;
BIGNUM order, cofactor;
int curve_name; /* optional NID for named curve */
@@ -150,20 +140,17 @@ struct ec_group_st {
int a_is_minus3; /* enable optimized point arithmetics for special case */
BN_MONT_CTX *mont; /* Montgomery structure. */
- BIGNUM *one; /* The value one */
+
+ BIGNUM one; /* The value one. */
} /* EC_GROUP */;
struct ec_point_st {
const EC_METHOD *meth;
- /* All members except 'meth' are handled by the method functions,
- * even if they appear generic */
-
BIGNUM X;
BIGNUM Y;
BIGNUM Z; /* Jacobian projective coordinates:
* (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */
- int Z_is_one; /* enable optimized point arithmetics for special case */
} /* EC_POINT */;
EC_GROUP *ec_group_new(const EC_METHOD *meth);
@@ -180,14 +167,12 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
/* method functions in simple.c */
int ec_GFp_simple_group_init(EC_GROUP *);
void ec_GFp_simple_group_finish(EC_GROUP *);
-void ec_GFp_simple_group_clear_finish(EC_GROUP *);
int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *);
unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *);
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
int ec_GFp_simple_point_init(EC_POINT *);
void ec_GFp_simple_point_finish(EC_POINT *);
void ec_GFp_simple_point_clear_finish(EC_POINT *);
@@ -204,9 +189,6 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *);
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BN_CTX *);
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
const BIGNUM *x, int y_bit,
BN_CTX *);
@@ -232,7 +214,6 @@ int ec_GFp_mont_group_init(EC_GROUP *);
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
void ec_GFp_mont_group_finish(EC_GROUP *);
-void ec_GFp_mont_group_clear_finish(EC_GROUP *);
int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
@@ -242,22 +223,12 @@ int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx);
-void ec_GFp_nistp_points_make_affine_internal(
- size_t num, void *point_array, size_t felem_size, void *tmp_felems,
- void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
- void (*felem_assign)(void *out, const void *in),
- void (*felem_square)(void *out, const void *in),
- void (*felem_mul)(void *out, const void *in1, const void *in2),
- void (*felem_inv)(void *out, const void *in),
- void (*felem_contract)(void *out, const void *in));
-
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
const EC_METHOD *EC_GFp_nistp224_method(void);
@@ -268,8 +239,6 @@ const EC_METHOD *EC_GFp_nistp256_method(void);
const EC_METHOD *EC_GFp_nistz256_method(void);
struct ec_key_st {
- int version;
-
EC_GROUP *group;
EC_POINT *pub_key;
@@ -279,7 +248,6 @@ struct ec_key_st {
point_conversion_form_t conv_form;
CRYPTO_refcount_t references;
- int flags;
ECDSA_METHOD *ecdsa_meth;
@@ -303,6 +271,8 @@ struct curve_data {
struct built_in_curve {
int nid;
+ uint8_t oid[8];
+ uint8_t oid_len;
const struct curve_data *data;
const EC_METHOD *(*method)(void);
};
diff --git a/src/crypto/ec/oct.c b/src/crypto/ec/oct.c
index e39337dd..bf1957ca 100644
--- a/src/crypto/ec/oct.c
+++ b/src/crypto/ec/oct.c
@@ -68,6 +68,7 @@
#include <openssl/ec.h>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
#include "internal.h"
@@ -268,11 +269,27 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
}
+int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
+ point_conversion_form_t form, BN_CTX *ctx) {
+ size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
+ if (len == 0) {
+ return 0;
+ }
+ uint8_t *p;
+ return CBB_add_space(out, &p, len) &&
+ EC_POINT_point2oct(group, point, form, p, len, ctx) == len;
+}
+
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x_,
+ EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx) {
+ if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
+ return 0;
+ }
+
BN_CTX *new_ctx = NULL;
- BIGNUM *tmp1, *tmp2, *x, *y;
+ BIGNUM *tmp1, *tmp2, *y;
int ret = 0;
ERR_clear_error();
@@ -289,7 +306,6 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
BN_CTX_start(ctx);
tmp1 = BN_CTX_get(ctx);
tmp2 = BN_CTX_get(ctx);
- x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL) {
goto err;
@@ -300,19 +316,15 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
* so y is one of the square roots of x^3 + a*x + b. */
/* tmp1 := x^3 */
- if (!BN_nnmod(x, x_, &group->field, ctx)) {
- goto err;
- }
-
if (group->meth->field_decode == 0) {
/* field_{sqr,mul} work on standard representation */
- if (!group->meth->field_sqr(group, tmp2, x_, ctx) ||
- !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) {
+ if (!group->meth->field_sqr(group, tmp2, x, ctx) ||
+ !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) {
goto err;
}
} else {
- if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) ||
- !BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) {
+ if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
+ !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
goto err;
}
}
diff --git a/src/crypto/ec/p224-64.c b/src/crypto/ec/p224-64.c
index e026fc47..7bf889c9 100644
--- a/src/crypto/ec/p224-64.c
+++ b/src/crypto/ec/p224-64.c
@@ -26,11 +26,11 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <string.h>
#include "internal.h"
+#include "../internal.h"
typedef uint8_t u8;
@@ -50,7 +50,7 @@ typedef int64_t s64;
* to the unique minimal representation at the end of the computation. */
typedef uint64_t limb;
-typedef __uint128_t widelimb;
+typedef uint128_t widelimb;
typedef limb felem[4];
typedef widelimb widefelem[7];
@@ -60,23 +60,6 @@ typedef widelimb widefelem[7];
* scalars for point multiplication. */
typedef u8 felem_bytearray[28];
-static const felem_bytearray nistp224_curve_params[5] = {
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* p */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* a */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE},
- {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, /* b */
- 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B,
- 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4},
- {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, /* x */
- 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32,
- 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21},
- {0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, /* y */
- 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5,
- 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34}};
-
/* Precomputed multiples of the standard generator
* Points are given in coordinates (X, Y, Z) where Z normally is 1
* (0 for the point at infinity).
@@ -209,7 +192,7 @@ static void bin28_to_felem(felem out, const u8 in[28]) {
}
static void felem_to_bin28(u8 out[28], const felem in) {
- unsigned i;
+ size_t i;
for (i = 0; i < 7; ++i) {
out[i] = in[0] >> (8 * i);
out[i + 7] = in[1] >> (8 * i);
@@ -219,8 +202,8 @@ static void felem_to_bin28(u8 out[28], const felem in) {
}
/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
- unsigned i;
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+ size_t i;
for (i = 0; i < len; ++i) {
out[i] = in[len - 1 - i];
}
@@ -231,7 +214,7 @@ static int BN_to_felem(felem out, const BIGNUM *bn) {
/* BN_bn2bin eats leading zeroes */
felem_bytearray b_out;
memset(b_out, 0, sizeof(b_out));
- unsigned num_bytes = BN_num_bytes(bn);
+ size_t num_bytes = BN_num_bytes(bn);
if (num_bytes > sizeof(b_out) ||
BN_is_negative(bn)) {
OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
@@ -258,13 +241,6 @@ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) {
* expected to be correct in general - e.g., multiplication with a large scalar
* will cause an overflow. */
-static void felem_one(felem out) {
- out[0] = 1;
- out[1] = 0;
- out[2] = 0;
- out[3] = 0;
-}
-
static void felem_assign(felem out, const felem in) {
out[0] = in[0];
out[1] = in[1];
@@ -476,18 +452,6 @@ static void felem_reduce(felem out, const widefelem in) {
out[3] = output[3];
}
-static void felem_square_reduce(felem out, const felem in) {
- widefelem tmp;
- felem_square(tmp, in);
- felem_reduce(out, tmp);
-}
-
-static void felem_mul_reduce(felem out, const felem in1, const felem in2) {
- widefelem tmp;
- felem_mul(tmp, in1, in2);
- felem_reduce(out, tmp);
-}
-
/* Reduce to unique minimal representation.
* Requires 0 <= in < 2*p (always call felem_reduce first) */
static void felem_contract(felem out, const felem in) {
@@ -555,16 +519,12 @@ static limb felem_is_zero(const felem in) {
return (zero | two224m96p1 | two225m97p2);
}
-static limb felem_is_zero_int(const felem in) {
- return (int)(felem_is_zero(in) & ((limb)1));
-}
-
/* Invert a field element */
/* Computation chain copied from djb's code */
static void felem_inv(felem out, const felem in) {
felem ftmp, ftmp2, ftmp3, ftmp4;
widefelem tmp;
- unsigned i;
+ size_t i;
felem_square(tmp, in);
felem_reduce(ftmp, tmp); /* 2 */
@@ -644,7 +604,7 @@ static void felem_inv(felem out, const felem in) {
* if icopy == 1, copy in to out,
* if icopy == 0, copy out to itself. */
static void copy_conditional(felem out, const felem in, limb icopy) {
- unsigned i;
+ size_t i;
/* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */
const limb copy = -icopy;
for (i = 0; i < 4; ++i) {
@@ -901,12 +861,12 @@ static void point_add(felem x3, felem y3, felem z3, const felem x1,
/* select_point selects the |idx|th point from a precomputation table and
* copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
+static void select_point(const u64 idx, size_t size,
const felem pre_comp[/*size*/][3], felem out[3]) {
- unsigned i, j;
limb *outlimbs = &out[0][0];
memset(outlimbs, 0, 3 * sizeof(felem));
+ size_t i;
for (i = 0; i < size; i++) {
const limb *inlimbs = &pre_comp[i][0][0];
u64 mask = i ^ idx;
@@ -915,6 +875,7 @@ static void select_point(const u64 idx, unsigned int size,
mask |= mask >> 1;
mask &= 1;
mask--;
+ size_t j;
for (j = 0; j < 4 * 3; j++) {
outlimbs[j] |= inlimbs[j] & mask;
}
@@ -922,7 +883,7 @@ static void select_point(const u64 idx, unsigned int size,
}
/* get_bit returns the |i|th bit in |in| */
-static char get_bit(const felem_bytearray in, unsigned i) {
+static char get_bit(const felem_bytearray in, size_t i) {
if (i >= 224) {
return 0;
}
@@ -936,11 +897,8 @@ static char get_bit(const felem_bytearray in, unsigned i) {
* Output point (X, Y, Z) is stored in x_out, y_out, z_out */
static void batch_mul(felem x_out, felem y_out, felem z_out,
const felem_bytearray scalars[],
- const unsigned num_points, const u8 *g_scalar,
- const int mixed, const felem pre_comp[][17][3]) {
- int i, skip;
- unsigned num;
- unsigned gen_mul = (g_scalar != NULL);
+ const size_t num_points, const u8 *g_scalar,
+ const felem pre_comp[][17][3]) {
felem nq[3], tmp[4];
u64 bits;
u8 sign, digit;
@@ -951,15 +909,16 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Loop over all scalars msb-to-lsb, interleaving additions
* of multiples of the generator (two in each of the last 28 rounds)
* and additions of other points multiples (every 5th round). */
- skip = 1; /* save two point operations in the first round */
- for (i = (num_points ? 220 : 27); i >= 0; --i) {
+ int skip = 1; /* save two point operations in the first round */
+ size_t i = num_points != 0 ? 220 : 27;
+ for (;;) {
/* double */
if (!skip) {
point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
}
/* add multiples of the generator */
- if (gen_mul && (i <= 27)) {
+ if (g_scalar != NULL && i <= 27) {
/* first, look 28 bits upwards */
bits = get_bit(g_scalar, i + 196) << 3;
bits |= get_bit(g_scalar, i + 140) << 2;
@@ -988,8 +947,9 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
}
/* do other additions every 5 doublings */
- if (num_points && (i % 5 == 0)) {
+ if (num_points != 0 && i % 5 == 0) {
/* loop over all scalars */
+ size_t num;
for (num = 0; num < num_points; ++num) {
bits = get_bit(scalars[num], i + 4) << 5;
bits |= get_bit(scalars[num], i + 3) << 4;
@@ -1005,70 +965,31 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
copy_conditional(tmp[1], tmp[3], sign);
if (!skip) {
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
- tmp[1], tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
memcpy(nq, tmp, 3 * sizeof(felem));
skip = 0;
}
}
}
+
+ if (i == 0) {
+ break;
+ }
+ --i;
}
felem_assign(x_out, nq[0]);
felem_assign(y_out, nq[1]);
felem_assign(z_out, nq[2]);
}
-int ec_GFp_nistp224_group_init(EC_GROUP *group) {
- int ret;
- ret = ec_GFp_simple_group_init(group);
- group->a_is_minus3 = 1;
- return ret;
-}
-
-int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx) {
- int ret = 0;
- BN_CTX *new_ctx = NULL;
- BIGNUM *curve_p, *curve_a, *curve_b;
-
- if (ctx == NULL) {
- ctx = BN_CTX_new();
- new_ctx = ctx;
- if (ctx == NULL) {
- return 0;
- }
- }
- BN_CTX_start(ctx);
- if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
- ((curve_a = BN_CTX_get(ctx)) == NULL) ||
- ((curve_b = BN_CTX_get(ctx)) == NULL)) {
- goto err;
- }
- BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p);
- BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
- BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b);
- if (BN_cmp(curve_p, p) ||
- BN_cmp(curve_a, a) ||
- BN_cmp(curve_b, b)) {
- OPENSSL_PUT_ERROR(EC, EC_R_WRONG_CURVE_PARAMETERS);
- goto err;
- }
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
-
-err:
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
- return ret;
-}
-
/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
* (X', Y') = (X/Z^2, Y/Z^3) */
-int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx) {
+static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
felem z1, z2, x_in, y_in, x_out, y_out;
widefelem tmp;
@@ -1107,23 +1028,12 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
return 1;
}
-static void make_points_affine(size_t num, felem points[/*num*/][3],
- felem tmp_felems[/*num+1*/]) {
- /* Runs in constant time, unless an input is the point at infinity
- * (which normally shouldn't happen). */
- ec_GFp_nistp_points_make_affine_internal(
- num, points, sizeof(felem), tmp_felems, (void (*)(void *))felem_one,
- (int (*)(const void *))felem_is_zero_int,
- (void (*)(void *, const void *))felem_assign,
- (void (*)(void *, const void *))felem_square_reduce,
- (void (*)(void *, const void *, const void *))felem_mul_reduce,
- (void (*)(void *, const void *))felem_inv,
- (void (*)(void *, const void *))felem_contract);
-}
-
-int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *g_scalar, const EC_POINT *p_,
- const BIGNUM *p_scalar_, BN_CTX *ctx) {
+static int ec_GFp_nistp224_points_mul(const EC_GROUP *group,
+ EC_POINT *r,
+ const BIGNUM *g_scalar,
+ const EC_POINT *p_,
+ const BIGNUM *p_scalar_,
+ BN_CTX *ctx) {
/* TODO: This function used to take |points| and |scalars| as arrays of
* |num| elements. The code below should be simplified to work in terms of
* |p_| and |p_scalar_|. */
@@ -1132,17 +1042,12 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
int ret = 0;
- int j;
- unsigned i;
- int mixed = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *z, *tmp_scalar;
felem_bytearray g_secret;
felem_bytearray *secrets = NULL;
felem(*pre_comp)[17][3] = NULL;
- felem *tmp_felems = NULL;
felem_bytearray tmp;
- unsigned num_bytes;
size_t num_points = num;
felem x_in, y_in, z_in, x_out, y_out, z_out;
const EC_POINT *p = NULL;
@@ -1165,19 +1070,10 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (num_points > 0) {
- if (num_points >= 3) {
- /* unless we precompute multiples for just one or two points,
- * converting those into affine form is time well spent */
- mixed = 1;
- }
secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
pre_comp = OPENSSL_malloc(num_points * sizeof(felem[17][3]));
- if (mixed) {
- tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
- }
if (secrets == NULL ||
- pre_comp == NULL ||
- (mixed && tmp_felems == NULL)) {
+ pre_comp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1186,6 +1082,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
* i.e., they contribute nothing to the linear combination */
memset(secrets, 0, num_points * sizeof(felem_bytearray));
memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
+ size_t i;
for (i = 0; i < num_points; ++i) {
if (i == num) {
/* the generator */
@@ -1198,6 +1095,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (p_scalar != NULL && p != NULL) {
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^224 */
if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) {
/* this is an unusual input, and we don't guarantee
@@ -1223,6 +1121,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_assign(pre_comp[i][1][1], y_out);
felem_assign(pre_comp[i][1][2], z_out);
+ size_t j;
for (j = 2; j <= 16; ++j) {
if (j & 1) {
point_add(pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
@@ -1237,14 +1136,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
}
}
-
- if (mixed) {
- make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
- }
}
if (g_scalar != NULL) {
memset(g_secret, 0, sizeof(g_secret));
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^224 */
if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) {
/* this is an unusual input, and we don't guarantee constant-timeness */
@@ -1260,7 +1156,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
flip_endian(g_secret, tmp, num_bytes);
}
batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
- num_points, g_scalar != NULL ? g_secret : NULL, mixed,
+ num_points, g_scalar != NULL ? g_secret : NULL,
(const felem(*)[17][3])pre_comp);
/* reduce the output to its unique minimal representation */
@@ -1280,24 +1176,21 @@ err:
BN_CTX_free(new_ctx);
OPENSSL_free(secrets);
OPENSSL_free(pre_comp);
- OPENSSL_free(tmp_felems);
return ret;
}
const EC_METHOD *EC_GFp_nistp224_method(void) {
- static const EC_METHOD ret = {ec_GFp_nistp224_group_init,
+ static const EC_METHOD ret = {ec_GFp_simple_group_init,
ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
ec_GFp_simple_group_copy,
- ec_GFp_nistp224_group_set_curve,
+ ec_GFp_simple_group_set_curve,
ec_GFp_nistp224_point_get_affine_coordinates,
ec_GFp_nistp224_points_mul,
0 /* check_pub_key_order */,
ec_GFp_simple_field_mul,
ec_GFp_simple_field_sqr,
0 /* field_encode */,
- 0 /* field_decode */,
- 0 /* field_set_to_one */};
+ 0 /* field_decode */};
return &ret;
}
diff --git a/src/crypto/ec/p256-64.c b/src/crypto/ec/p256-64.c
index 32852dd6..c4259b62 100644
--- a/src/crypto/ec/p256-64.c
+++ b/src/crypto/ec/p256-64.c
@@ -27,44 +27,22 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <string.h>
#include "internal.h"
+#include "../internal.h"
typedef uint8_t u8;
typedef uint64_t u64;
typedef int64_t s64;
-typedef __uint128_t uint128_t;
-typedef __int128_t int128_t;
/* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We
* can serialise an element of this field into 32 bytes. We call this an
* felem_bytearray. */
typedef u8 felem_bytearray[32];
-/* These are the parameters of P256, taken from FIPS 186-3, page 86. These
- * values are big-endian. */
-static const felem_bytearray nistp256_curve_params[5] = {
- {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
- 0x00, 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, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xfc}, /* b */
- {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55,
- 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
- 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
- {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
- 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
- 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
- {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
- 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
- 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}};
-
/* The representation of field elements.
* ------------------------------------
*
@@ -99,10 +77,10 @@ static const u64 bottom63bits = 0x7ffffffffffffffful;
/* bin32_to_felem takes a little-endian byte array and converts it into felem
* form. This assumes that the CPU is little-endian. */
static void bin32_to_felem(felem out, const u8 in[32]) {
- out[0] = *((u64 *)&in[0]);
- out[1] = *((u64 *)&in[8]);
- out[2] = *((u64 *)&in[16]);
- out[3] = *((u64 *)&in[24]);
+ out[0] = *((const u64 *)&in[0]);
+ out[1] = *((const u64 *)&in[8]);
+ out[2] = *((const u64 *)&in[16]);
+ out[3] = *((const u64 *)&in[24]);
}
/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian,
@@ -115,8 +93,8 @@ static void smallfelem_to_bin32(u8 out[32], const smallfelem in) {
}
/* To preserve endianness when using BN_bn2bin and BN_bin2bn. */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
- unsigned i;
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+ size_t i;
for (i = 0; i < len; ++i) {
out[i] = in[len - 1 - i];
}
@@ -132,7 +110,7 @@ static int BN_to_felem(felem out, const BIGNUM *bn) {
felem_bytearray b_out;
/* BN_bn2bin eats leading zeroes */
memset(b_out, 0, sizeof(b_out));
- unsigned num_bytes = BN_num_bytes(bn);
+ size_t num_bytes = BN_num_bytes(bn);
if (num_bytes > sizeof(b_out)) {
OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
@@ -155,20 +133,6 @@ static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) {
/* Field operations. */
-static void smallfelem_one(smallfelem out) {
- out[0] = 1;
- out[1] = 0;
- out[2] = 0;
- out[3] = 0;
-}
-
-static void smallfelem_assign(smallfelem out, const smallfelem in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
-}
-
static void felem_assign(felem out, const felem in) {
out[0] = in[0];
out[1] = in[1];
@@ -364,8 +328,7 @@ static void felem_shrink(smallfelem out, const felem in) {
* conditionally subtract kPrime if tmp[3] is large enough. */
high = tmp[3] >> 64;
/* As tmp[3] < 2^65, high is either 1 or 0 */
- high <<= 63;
- high >>= 63;
+ high = ~(high - 1);
/* high is:
* all ones if the high word of tmp[3] is 1
* all zeros if the high word of tmp[3] if 0 */
@@ -756,7 +719,7 @@ static void felem_contract(smallfelem out, const felem in) {
* each u64, from most-significant to least significant. For each one, if
* all words so far have been equal (m is all ones) then a non-equal
* result is the answer. Otherwise we continue. */
- unsigned i;
+ size_t i;
for (i = 3; i < 4; i--) {
u64 equal;
uint128_t a = ((uint128_t)kPrime[i]) - out[i];
@@ -800,25 +763,6 @@ static void felem_contract(smallfelem out, const felem in) {
subtract_u64(&out[3], &carry, result & kPrime[3]);
}
-static void smallfelem_square_contract(smallfelem out, const smallfelem in) {
- longfelem longtmp;
- felem tmp;
-
- smallfelem_square(longtmp, in);
- felem_reduce(tmp, longtmp);
- felem_contract(out, tmp);
-}
-
-static void smallfelem_mul_contract(smallfelem out, const smallfelem in1,
- const smallfelem in2) {
- longfelem longtmp;
- felem tmp;
-
- smallfelem_mul(longtmp, in1, in2);
- felem_reduce(tmp, longtmp);
- felem_contract(out, tmp);
-}
-
/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
* otherwise.
* On entry:
@@ -855,10 +799,6 @@ static limb smallfelem_is_zero(const smallfelem small) {
return result;
}
-static int smallfelem_is_zero_int(const smallfelem small) {
- return (int)(smallfelem_is_zero(small) & ((limb)1));
-}
-
/* felem_inv calculates |out| = |in|^{-1}
*
* Based on Fermat's Little Theorem:
@@ -870,7 +810,7 @@ static void felem_inv(felem out, const felem in) {
/* each e_I will hold |in|^{2^I - 1} */
felem e2, e4, e8, e16, e32, e64;
longfelem tmp;
- unsigned i;
+ size_t i;
felem_square(tmp, in);
felem_reduce(ftmp, tmp); /* 2^1 */
@@ -958,14 +898,6 @@ static void felem_inv(felem out, const felem in) {
felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
}
-static void smallfelem_inv_contract(smallfelem out, const smallfelem in) {
- felem tmp;
-
- smallfelem_expand(tmp, in);
- felem_inv(tmp, tmp);
- felem_contract(out, tmp);
-}
-
/* Group operations
* ----------------
*
@@ -1076,7 +1008,7 @@ static void point_double_small(smallfelem x_out, smallfelem y_out,
/* copy_conditional copies in to out iff mask is all ones. */
static void copy_conditional(felem out, const felem in, limb mask) {
- unsigned i;
+ size_t i;
for (i = 0; i < NLIMBS; ++i) {
const limb tmp = mask & (in[i] ^ out[i]);
out[i] ^= tmp;
@@ -1085,7 +1017,7 @@ static void copy_conditional(felem out, const felem in, limb mask) {
/* copy_small_conditional copies in to out iff mask is all ones. */
static void copy_small_conditional(felem out, const smallfelem in, limb mask) {
- unsigned i;
+ size_t i;
const u64 mask64 = mask;
for (i = 0; i < NLIMBS; ++i) {
out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask);
@@ -1469,20 +1401,22 @@ static const smallfelem g_pre_comp[2][16][3] = {
/* select_point selects the |idx|th point from a precomputation table and
* copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
- const smallfelem pre_comp[16][3], smallfelem out[3]) {
- unsigned i, j;
+static void select_point(const u64 idx, size_t size,
+ const smallfelem pre_comp[/*size*/][3],
+ smallfelem out[3]) {
u64 *outlimbs = &out[0][0];
memset(outlimbs, 0, 3 * sizeof(smallfelem));
+ size_t i;
for (i = 0; i < size; i++) {
- const u64 *inlimbs = (u64 *)&pre_comp[i][0][0];
+ const u64 *inlimbs = (const u64 *)&pre_comp[i][0][0];
u64 mask = i ^ idx;
mask |= mask >> 4;
mask |= mask >> 2;
mask |= mask >> 1;
mask &= 1;
mask--;
+ size_t j;
for (j = 0; j < NLIMBS * 3; j++) {
outlimbs[j] |= inlimbs[j] & mask;
}
@@ -1504,10 +1438,8 @@ static char get_bit(const felem_bytearray in, int i) {
* Output point (X, Y, Z) is stored in x_out, y_out, z_out. */
static void batch_mul(felem x_out, felem y_out, felem z_out,
const felem_bytearray scalars[],
- const unsigned num_points, const u8 *g_scalar,
- const int mixed, const smallfelem pre_comp[][17][3]) {
- int i, skip;
- unsigned num, gen_mul = (g_scalar != NULL);
+ const size_t num_points, const u8 *g_scalar,
+ const smallfelem pre_comp[][17][3]) {
felem nq[3], ftmp;
smallfelem tmp[3];
u64 bits;
@@ -1520,16 +1452,16 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
* of the generator (two in each of the last 32 rounds) and additions of
* other points multiples (every 5th round). */
- skip = 1; /* save two point operations in the first
- * round */
- for (i = (num_points ? 255 : 31); i >= 0; --i) {
+ int skip = 1; /* save two point operations in the first round */
+ size_t i = num_points != 0 ? 255 : 31;
+ for (;;) {
/* double */
if (!skip) {
point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
}
/* add multiples of the generator */
- if (gen_mul && i <= 31) {
+ if (g_scalar != NULL && i <= 31) {
/* first, look 32 bits upwards */
bits = get_bit(g_scalar, i + 224) << 3;
bits |= get_bit(g_scalar, i + 160) << 2;
@@ -1539,9 +1471,8 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
select_point(bits, 16, g_pre_comp[1], tmp);
if (!skip) {
- /* Arg 1 below is for "mixed" */
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
- tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
smallfelem_expand(nq[0], tmp[0]);
smallfelem_expand(nq[1], tmp[1]);
@@ -1556,14 +1487,14 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
bits |= get_bit(g_scalar, i);
/* select the point to add, in constant time */
select_point(bits, 16, g_pre_comp[0], tmp);
- /* Arg 1 below is for "mixed" */
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
- tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0],
+ tmp[1], tmp[2]);
}
/* do other additions every 5 doublings */
- if (num_points && (i % 5 == 0)) {
+ if (num_points != 0 && i % 5 == 0) {
/* loop over all scalars */
+ size_t num;
for (num = 0; num < num_points; ++num) {
bits = get_bit(scalars[num], i + 4) << 5;
bits |= get_bit(scalars[num], i + 3) << 4;
@@ -1581,8 +1512,8 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
felem_contract(tmp[1], ftmp);
if (!skip) {
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
- tmp[1], tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
smallfelem_expand(nq[0], tmp[0]);
smallfelem_expand(nq[1], tmp[1]);
@@ -1591,6 +1522,11 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
}
}
}
+
+ if (i == 0) {
+ break;
+ }
+ --i;
}
felem_assign(x_out, nq[0]);
felem_assign(y_out, nq[1]);
@@ -1602,53 +1538,12 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
* OPENSSL EC_METHOD FUNCTIONS
*/
-int ec_GFp_nistp256_group_init(EC_GROUP *group) {
- int ret = ec_GFp_simple_group_init(group);
- group->a_is_minus3 = 1;
- return ret;
-}
-
-int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx) {
- int ret = 0;
- BN_CTX *new_ctx = NULL;
- BIGNUM *curve_p, *curve_a, *curve_b;
-
- if (ctx == NULL) {
- if ((ctx = new_ctx = BN_CTX_new()) == NULL) {
- return 0;
- }
- }
- BN_CTX_start(ctx);
- if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
- ((curve_a = BN_CTX_get(ctx)) == NULL) ||
- ((curve_b = BN_CTX_get(ctx)) == NULL)) {
- goto err;
- }
- BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
- BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
- BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
- if (BN_cmp(curve_p, p) ||
- BN_cmp(curve_a, a) ||
- BN_cmp(curve_b, b)) {
- OPENSSL_PUT_ERROR(EC, EC_R_WRONG_CURVE_PARAMETERS);
- goto err;
- }
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
-
-err:
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
- return ret;
-}
-
/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3). */
-int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx) {
+static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
felem z1, z2, x_in, y_in;
smallfelem x_out, y_out;
longfelem tmp;
@@ -1665,45 +1560,38 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
felem_inv(z2, z1);
felem_square(tmp, z2);
felem_reduce(z1, tmp);
- felem_mul(tmp, x_in, z1);
- felem_reduce(x_in, tmp);
- felem_contract(x_out, x_in);
- if (x != NULL && !smallfelem_to_BN(x, x_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+
+ if (x != NULL) {
+ felem_mul(tmp, x_in, z1);
+ felem_reduce(x_in, tmp);
+ felem_contract(x_out, x_in);
+ if (!smallfelem_to_BN(x, x_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
- felem_mul(tmp, z1, z2);
- felem_reduce(z1, tmp);
- felem_mul(tmp, y_in, z1);
- felem_reduce(y_in, tmp);
- felem_contract(y_out, y_in);
- if (y != NULL && !smallfelem_to_BN(y, y_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+
+ if (y != NULL) {
+ felem_mul(tmp, z1, z2);
+ felem_reduce(z1, tmp);
+ felem_mul(tmp, y_in, z1);
+ felem_reduce(y_in, tmp);
+ felem_contract(y_out, y_in);
+ if (!smallfelem_to_BN(y, y_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
- return 1;
-}
-/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */
-static void make_points_affine(size_t num, smallfelem points[][3],
- smallfelem tmp_smallfelems[]) {
- /* Runs in constant time, unless an input is the point at infinity (which
- * normally shouldn't happen). */
- ec_GFp_nistp_points_make_affine_internal(
- num, points, sizeof(smallfelem), tmp_smallfelems,
- (void (*)(void *))smallfelem_one,
- (int (*)(const void *))smallfelem_is_zero_int,
- (void (*)(void *, const void *))smallfelem_assign,
- (void (*)(void *, const void *))smallfelem_square_contract,
- (void (*)(void *, const void *, const void *))smallfelem_mul_contract,
- (void (*)(void *, const void *))smallfelem_inv_contract,
- /* nothing to contract */
- (void (*)(void *, const void *))smallfelem_assign);
+ return 1;
}
-int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *g_scalar, const EC_POINT *p_,
- const BIGNUM *p_scalar_, BN_CTX *ctx) {
+static int ec_GFp_nistp256_points_mul(const EC_GROUP *group,
+ EC_POINT *r,
+ const BIGNUM *g_scalar,
+ const EC_POINT *p_,
+ const BIGNUM *p_scalar_,
+ BN_CTX *ctx) {
/* TODO: This function used to take |points| and |scalars| as arrays of
* |num| elements. The code below should be simplified to work in terms of |p|
* and |p_scalar|. */
@@ -1712,16 +1600,12 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
int ret = 0;
- int j;
- int mixed = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *z, *tmp_scalar;
felem_bytearray g_secret;
felem_bytearray *secrets = NULL;
smallfelem(*pre_comp)[17][3] = NULL;
- smallfelem *tmp_smallfelems = NULL;
felem_bytearray tmp;
- unsigned i, num_bytes;
size_t num_points = num;
smallfelem x_in, y_in, z_in;
felem x_out, y_out, z_out;
@@ -1744,19 +1628,9 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (num_points > 0) {
- if (num_points >= 3) {
- /* unless we precompute multiples for just one or two points,
- * converting those into affine form is time well spent */
- mixed = 1;
- }
secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
pre_comp = OPENSSL_malloc(num_points * sizeof(smallfelem[17][3]));
- if (mixed) {
- tmp_smallfelems =
- OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
- }
- if (secrets == NULL || pre_comp == NULL ||
- (mixed && tmp_smallfelems == NULL)) {
+ if (secrets == NULL || pre_comp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1765,6 +1639,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
* i.e., they contribute nothing to the linear combination. */
memset(secrets, 0, num_points * sizeof(felem_bytearray));
memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
+ size_t i;
for (i = 0; i < num_points; ++i) {
if (i == num) {
/* we didn't have a valid precomputation, so we pick the generator. */
@@ -1776,6 +1651,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
p_scalar = scalars[i];
}
if (p_scalar != NULL && p != NULL) {
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^256 */
if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) {
/* this is an unusual input, and we don't guarantee
@@ -1798,6 +1674,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_shrink(pre_comp[i][1][0], x_out);
felem_shrink(pre_comp[i][1][1], y_out);
felem_shrink(pre_comp[i][1][2], z_out);
+ size_t j;
for (j = 2; j <= 16; ++j) {
if (j & 1) {
point_add_small(pre_comp[i][j][0], pre_comp[i][j][1],
@@ -1813,12 +1690,11 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
}
}
}
- if (mixed) {
- make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
- }
}
if (g_scalar != NULL) {
+ size_t num_bytes;
+
memset(g_secret, 0, sizeof(g_secret));
/* reduce g_scalar to 0 <= g_scalar < 2^256 */
if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
@@ -1835,7 +1711,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
flip_endian(g_secret, tmp, num_bytes);
}
batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
- num_points, g_scalar != NULL ? g_secret : NULL, mixed,
+ num_points, g_scalar != NULL ? g_secret : NULL,
(const smallfelem(*)[17][3])pre_comp);
/* reduce the output to its unique minimal representation */
@@ -1855,21 +1731,20 @@ err:
BN_CTX_free(new_ctx);
OPENSSL_free(secrets);
OPENSSL_free(pre_comp);
- OPENSSL_free(tmp_smallfelems);
return ret;
}
const EC_METHOD *EC_GFp_nistp256_method(void) {
static const EC_METHOD ret = {
- ec_GFp_nistp256_group_init,
+ ec_GFp_simple_group_init,
ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_simple_group_copy, ec_GFp_nistp256_group_set_curve,
+ ec_GFp_simple_group_copy,
+ ec_GFp_simple_group_set_curve,
ec_GFp_nistp256_point_get_affine_coordinates,
ec_GFp_nistp256_points_mul,
0 /* check_pub_key_order */,
ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr,
- 0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */
+ 0 /* field_encode */, 0 /* field_decode */,
};
return &ret;
diff --git a/src/crypto/ec/p256-x86_64-table.h b/src/crypto/ec/p256-x86_64-table.h
index 5b3254cc..e4705f8e 100644
--- a/src/crypto/ec/p256-x86_64-table.h
+++ b/src/crypto/ec/p256-x86_64-table.h
@@ -24,12 +24,7 @@
* in order to increase the chances of using a large page but that appears to
* lead to invalid ELF files being produced. */
-#if defined(__GNUC__)
-__attribute((aligned(4096)))
-#elif defined(_MSC_VER)
-__declspec(align(4096))
-#endif
-static const BN_ULONG
+static const alignas(4096) BN_ULONG
ecp_nistz256_precomputed[37][64 * sizeof(P256_POINT_AFFINE) /
sizeof(BN_ULONG)] = {
{TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601),
diff --git a/src/crypto/ec/p256-x86_64.c b/src/crypto/ec/p256-x86_64.c
index 2f7023d6..e1afec48 100644
--- a/src/crypto/ec/p256-x86_64.c
+++ b/src/crypto/ec/p256-x86_64.c
@@ -39,15 +39,6 @@
!defined(OPENSSL_SMALL)
-#if defined(__GNUC__)
-#define ALIGN(x) __attribute((aligned(x)))
-#elif defined(_MSC_VER)
-#define ALIGN(x) __declspec(align(x))
-#else
-#define ALIGN(x)
-#endif
-
-#define ALIGNPTR(p, N) ((uint8_t *)p + N - (size_t)p % N)
#define P256_LIMBS (256 / BN_BITS2)
typedef struct {
@@ -214,9 +205,7 @@ static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
- ecp_nistz256_mul_mont(res, res, in);
-
- memcpy(r, res, sizeof(res));
+ ecp_nistz256_mul_mont(r, res, in);
}
/* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
@@ -245,7 +234,7 @@ static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
/* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should
* add no more than 63 bytes of overhead. Thus, |table| should require
* ~1599 ((96 * 16) + 63) bytes of stack space. */
- ALIGN(64) P256_POINT table[16];
+ alignas(64) P256_POINT table[16];
uint8_t p_str[33];
@@ -326,7 +315,7 @@ static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]);
BN_ULONG tmp[P256_LIMBS];
- ALIGN(32) P256_POINT h;
+ alignas(32) P256_POINT h;
unsigned index = 255;
unsigned wvalue = p_str[(index - 1) / 8];
wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
@@ -390,7 +379,7 @@ static int ecp_nistz256_points_mul(
static const unsigned kWindowSize = 7;
static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
- ALIGN(32) union {
+ alignas(32) union {
P256_POINT p;
P256_POINT_AFFINE a;
} t, p;
@@ -399,17 +388,6 @@ static int ecp_nistz256_points_mul(
BN_CTX *new_ctx = NULL;
int ctx_started = 0;
- /* Need 256 bits for space for all coordinates. */
- if (bn_wexpand(&r->X, P256_LIMBS) == NULL ||
- bn_wexpand(&r->Y, P256_LIMBS) == NULL ||
- bn_wexpand(&r->Z, P256_LIMBS) == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- r->X.top = P256_LIMBS;
- r->Y.top = P256_LIMBS;
- r->Z.top = P256_LIMBS;
-
if (g_scalar != NULL) {
if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
if (ctx == NULL) {
@@ -503,15 +481,12 @@ static int ecp_nistz256_points_mul(
}
}
- memcpy(r->X.d, p.p.X, sizeof(p.p.X));
- memcpy(r->Y.d, p.p.Y, sizeof(p.p.Y));
- memcpy(r->Z.d, p.p.Z, sizeof(p.p.Z));
-
/* Not constant-time, but we're only operating on the public output. */
- bn_correct_top(&r->X);
- bn_correct_top(&r->Y);
- bn_correct_top(&r->Z);
- r->Z_is_one = BN_is_one(&r->Z);
+ if (!bn_set_words(&r->X, p.p.X, P256_LIMBS) ||
+ !bn_set_words(&r->Y, p.p.Y, P256_LIMBS) ||
+ !bn_set_words(&r->Z, p.p.Z, P256_LIMBS)) {
+ return 0;
+ }
ret = 1;
@@ -527,8 +502,6 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx) {
BN_ULONG z_inv2[P256_LIMBS];
BN_ULONG z_inv3[P256_LIMBS];
- BN_ULONG x_aff[P256_LIMBS];
- BN_ULONG y_aff[P256_LIMBS];
BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
if (EC_POINT_is_at_infinity(group, point)) {
@@ -545,7 +518,12 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
ecp_nistz256_mod_inverse(z_inv3, point_z);
ecp_nistz256_sqr_mont(z_inv2, z_inv3);
- ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
+
+ /* Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate
+ * and then calling |ecp_nistz256_from_mont| again to convert the |y|
+ * coordinate below, convert the common factor |z_inv2| once now, saving one
+ * reduction. */
+ ecp_nistz256_from_mont(z_inv2, z_inv2);
if (x != NULL) {
if (bn_wexpand(x, P256_LIMBS) == NULL) {
@@ -553,19 +531,20 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
return 0;
}
x->top = P256_LIMBS;
- ecp_nistz256_from_mont(x->d, x_aff);
+ x->neg = 0;
+ ecp_nistz256_mul_mont(x->d, z_inv2, point_x);
bn_correct_top(x);
}
if (y != NULL) {
ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
- ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
if (bn_wexpand(y, P256_LIMBS) == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
return 0;
}
y->top = P256_LIMBS;
- ecp_nistz256_from_mont(y->d, y_aff);
+ y->neg = 0;
+ ecp_nistz256_mul_mont(y->d, z_inv3, point_y);
bn_correct_top(y);
}
@@ -576,7 +555,6 @@ const EC_METHOD *EC_GFp_nistz256_method(void) {
static const EC_METHOD ret = {
ec_GFp_mont_group_init,
ec_GFp_mont_group_finish,
- ec_GFp_mont_group_clear_finish,
ec_GFp_mont_group_copy,
ec_GFp_mont_group_set_curve,
ecp_nistz256_get_affine,
@@ -586,7 +564,6 @@ const EC_METHOD *EC_GFp_nistz256_method(void) {
ec_GFp_mont_field_sqr,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
};
return &ret;
diff --git a/src/crypto/ec/simple.c b/src/crypto/ec/simple.c
index cef0e949..4508d83f 100644
--- a/src/crypto/ec/simple.c
+++ b/src/crypto/ec/simple.c
@@ -82,16 +82,16 @@
* field_sqr methods will be used for multiplication, and field_encode and
* field_decode (if defined) will be used for converting between
* representations.
-
- * Functions ec_GFp_simple_points_make_affine() and
- * ec_GFp_simple_point_get_affine_coordinates() specifically assume that if a
- * non-trivial representation is used, it is a Montgomery representation (i.e.
- * 'encoding' means multiplying by some factor R). */
+ *
+ * Functions here specifically assume that if a non-trivial representation is
+ * used, it is a Montgomery representation (i.e. 'encoding' means multiplying
+ * by some factor R). */
int ec_GFp_simple_group_init(EC_GROUP *group) {
BN_init(&group->field);
BN_init(&group->a);
BN_init(&group->b);
+ BN_init(&group->one);
group->a_is_minus3 = 0;
return 1;
}
@@ -100,18 +100,14 @@ void ec_GFp_simple_group_finish(EC_GROUP *group) {
BN_free(&group->field);
BN_free(&group->a);
BN_free(&group->b);
-}
-
-void ec_GFp_simple_group_clear_finish(EC_GROUP *group) {
- BN_clear_free(&group->field);
- BN_clear_free(&group->a);
- BN_clear_free(&group->b);
+ BN_free(&group->one);
}
int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
if (!BN_copy(&dest->field, &src->field) ||
!BN_copy(&dest->a, &src->a) ||
- !BN_copy(&dest->b, &src->b)) {
+ !BN_copy(&dest->b, &src->b) ||
+ !BN_copy(&dest->one, &src->one)) {
return 0;
}
@@ -178,6 +174,14 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
}
group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
+ if (group->meth->field_encode != NULL) {
+ if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) {
+ goto err;
+ }
+ } else if (!BN_copy(&group->one, BN_value_one())) {
+ goto err;
+ }
+
ret = 1;
err:
@@ -230,81 +234,10 @@ unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *group) {
return BN_num_bits(&group->field);
}
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) {
- int ret = 0;
- BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
- const BIGNUM *p = &group->field;
- BN_CTX *new_ctx = NULL;
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- BN_CTX_start(ctx);
- a = BN_CTX_get(ctx);
- b = BN_CTX_get(ctx);
- tmp_1 = BN_CTX_get(ctx);
- tmp_2 = BN_CTX_get(ctx);
- order = BN_CTX_get(ctx);
- if (order == NULL) {
- goto err;
- }
-
- if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, a, &group->a, ctx) ||
- !group->meth->field_decode(group, b, &group->b, ctx)) {
- goto err;
- }
- } else {
- if (!BN_copy(a, &group->a) || !BN_copy(b, &group->b)) {
- goto err;
- }
- }
-
- /* check the discriminant:
- * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
- * 0 =< a, b < p */
- if (BN_is_zero(a)) {
- if (BN_is_zero(b)) {
- goto err;
- }
- } else if (!BN_is_zero(b)) {
- if (!BN_mod_sqr(tmp_1, a, p, ctx) ||
- !BN_mod_mul(tmp_2, tmp_1, a, p, ctx) ||
- !BN_lshift(tmp_1, tmp_2, 2)) {
- goto err;
- }
- /* tmp_1 = 4*a^3 */
-
- if (!BN_mod_sqr(tmp_2, b, p, ctx) ||
- !BN_mul_word(tmp_2, 27)) {
- goto err;
- }
- /* tmp_2 = 27*b^2 */
-
- if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx) ||
- BN_is_zero(a)) {
- goto err;
- }
- }
- ret = 1;
-
-err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- }
- BN_CTX_free(new_ctx);
- return ret;
-}
-
int ec_GFp_simple_point_init(EC_POINT *point) {
BN_init(&point->X);
BN_init(&point->Y);
BN_init(&point->Z);
- point->Z_is_one = 0;
return 1;
}
@@ -319,7 +252,6 @@ void ec_GFp_simple_point_clear_finish(EC_POINT *point) {
BN_clear_free(&point->X);
BN_clear_free(&point->Y);
BN_clear_free(&point->Z);
- point->Z_is_one = 0;
}
int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
@@ -328,18 +260,32 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
!BN_copy(&dest->Z, &src->Z)) {
return 0;
}
- dest->Z_is_one = src->Z_is_one;
return 1;
}
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
EC_POINT *point) {
- point->Z_is_one = 0;
BN_zero(&point->Z);
return 1;
}
+static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out,
+ const BIGNUM *in, BN_CTX *ctx) {
+ if (in == NULL) {
+ return 1;
+ }
+ if (BN_is_negative(in) ||
+ BN_cmp(in, &group->field) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
+ return 0;
+ }
+ if (group->meth->field_encode) {
+ return group->meth->field_encode(group, out, in, ctx);
+ }
+ return BN_copy(out, in) != NULL;
+}
+
int ec_GFp_simple_set_Jprojective_coordinates_GFp(
const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y,
const BIGNUM *z, BN_CTX *ctx) {
@@ -353,43 +299,10 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(
}
}
- if (x != NULL) {
- if (!BN_nnmod(&point->X, x, &group->field, ctx)) {
- goto err;
- }
- if (group->meth->field_encode &&
- !group->meth->field_encode(group, &point->X, &point->X, ctx)) {
- goto err;
- }
- }
-
- if (y != NULL) {
- if (!BN_nnmod(&point->Y, y, &group->field, ctx)) {
- goto err;
- }
- if (group->meth->field_encode &&
- !group->meth->field_encode(group, &point->Y, &point->Y, ctx)) {
- goto err;
- }
- }
-
- if (z != NULL) {
- int Z_is_one;
-
- if (!BN_nnmod(&point->Z, z, &group->field, ctx)) {
- goto err;
- }
- Z_is_one = BN_is_one(&point->Z);
- if (group->meth->field_encode) {
- if (Z_is_one && (group->meth->field_set_to_one != 0)) {
- if (!group->meth->field_set_to_one(group, &point->Z, ctx)) {
- goto err;
- }
- } else if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) {
- goto err;
- }
- }
- point->Z_is_one = Z_is_one;
+ if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) ||
+ !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) ||
+ !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) {
+ goto err;
}
ret = 1;
@@ -455,109 +368,6 @@ int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
BN_value_one(), ctx);
}
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point, BIGNUM *x,
- BIGNUM *y, BN_CTX *ctx) {
- BN_CTX *new_ctx = NULL;
- BIGNUM *Z, *Z_1, *Z_2, *Z_3;
- const BIGNUM *Z_;
- int ret = 0;
-
- if (EC_POINT_is_at_infinity(group, point)) {
- OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
- return 0;
- }
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- }
-
- BN_CTX_start(ctx);
- Z = BN_CTX_get(ctx);
- Z_1 = BN_CTX_get(ctx);
- Z_2 = BN_CTX_get(ctx);
- Z_3 = BN_CTX_get(ctx);
- if (Z == NULL || Z_1 == NULL || Z_2 == NULL || Z_3 == NULL) {
- goto err;
- }
-
- /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
-
- if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
- goto err;
- }
- Z_ = Z;
- } else {
- Z_ = &point->Z;
- }
-
- if (BN_is_one(Z_)) {
- if (group->meth->field_decode) {
- if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
- goto err;
- }
- if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
- goto err;
- }
- } else {
- if (x != NULL && !BN_copy(x, &point->X)) {
- goto err;
- }
- if (y != NULL && !BN_copy(y, &point->Y)) {
- goto err;
- }
- }
- } else {
- if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
- }
-
- if (group->meth->field_encode == 0) {
- /* field_sqr works on standard representation */
- if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
- goto err;
- }
- } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
- goto err;
- }
-
- /* in the Montgomery case, field_mul will cancel out Montgomery factor in
- * X: */
- if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
- goto err;
- }
-
- if (y != NULL) {
- if (group->meth->field_encode == 0) {
- /* field_mul works on standard representation */
- if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
- goto err;
- }
- } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
- goto err;
- }
-
- /* in the Montgomery case, field_mul will cancel out Montgomery factor in
- * Y: */
- if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
- goto err;
- }
- }
- }
-
- ret = 1;
-
-err:
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
- return ret;
-}
-
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx) {
int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
@@ -607,7 +417,9 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
*/
/* n1, n2 */
- if (b->Z_is_one) {
+ int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+ if (b_Z_is_one) {
if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) {
goto end;
}
@@ -628,7 +440,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
}
/* n3, n4 */
- if (a->Z_is_one) {
+ int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+ if (a_Z_is_one) {
if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) {
goto end;
}
@@ -666,7 +479,6 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
} else {
/* a is the inverse of b */
BN_zero(&r->Z);
- r->Z_is_one = 0;
ret = 1;
goto end;
}
@@ -681,16 +493,16 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
/* 'n8' = n2 + n4 */
/* Z_r */
- if (a->Z_is_one && b->Z_is_one) {
+ if (a_Z_is_one && b_Z_is_one) {
if (!BN_copy(&r->Z, n5)) {
goto end;
}
} else {
- if (a->Z_is_one) {
+ if (a_Z_is_one) {
if (!BN_copy(n0, &b->Z)) {
goto end;
}
- } else if (b->Z_is_one) {
+ } else if (b_Z_is_one) {
if (!BN_copy(n0, &a->Z)) {
goto end;
}
@@ -701,7 +513,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
goto end;
}
}
- r->Z_is_one = 0;
+
/* Z_r = Z_a * Z_b * n5 */
/* X_r */
@@ -761,7 +573,6 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (EC_POINT_is_at_infinity(group, a)) {
BN_zero(&r->Z);
- r->Z_is_one = 0;
return 1;
}
@@ -791,7 +602,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
*/
/* n1 */
- if (a->Z_is_one) {
+ if (BN_cmp(&a->Z, &group->one) == 0) {
if (!field_sqr(group, n0, &a->X, ctx) ||
!BN_mod_lshift1_quick(n1, n0, p) ||
!BN_mod_add_quick(n0, n0, n1, p) ||
@@ -824,7 +635,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
}
/* Z_r */
- if (a->Z_is_one) {
+ if (BN_cmp(&a->Z, &group->one) == 0) {
if (!BN_copy(n0, &a->Y)) {
goto err;
}
@@ -834,7 +645,6 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (!BN_mod_lshift1_quick(&r->Z, n0, p)) {
goto err;
}
- r->Z_is_one = 0;
/* Z_r = 2 * Y_a * Z_a */
/* n2 */
@@ -886,7 +696,7 @@ int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
}
int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
- return !point->Z_is_one && BN_is_zero(&point->Z);
+ return BN_is_zero(&point->Z);
}
int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
@@ -897,7 +707,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *rh, *tmp, *Z4, *Z6;
- int ret = -1;
+ int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
return 1;
@@ -910,7 +720,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
- return -1;
+ return 0;
}
}
@@ -938,7 +748,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
goto err;
}
- if (!point->Z_is_one) {
+ if (BN_cmp(&point->Z, &group->one) != 0) {
if (!field_sqr(group, tmp, &point->Z, ctx) ||
!field_sqr(group, Z4, tmp, ctx) ||
!field_mul(group, Z6, Z4, tmp, ctx)) {
@@ -967,8 +777,6 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
goto err;
}
} else {
- /* point->Z_is_one */
-
/* rh := (rh + a)*X */
if (!BN_mod_add_quick(rh, rh, &group->a, p) ||
!field_mul(group, rh, rh, &point->X, ctx)) {
@@ -1017,7 +825,10 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
return 1;
}
- if (a->Z_is_one && b->Z_is_one) {
+ int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+ int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+ if (a_Z_is_one && b_Z_is_one) {
return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
}
@@ -1046,7 +857,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
* (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
*/
- if (!b->Z_is_one) {
+ if (!b_Z_is_one) {
if (!field_sqr(group, Zb23, &b->Z, ctx) ||
!field_mul(group, tmp1, &a->X, Zb23, ctx)) {
goto end;
@@ -1055,7 +866,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
} else {
tmp1_ = &a->X;
}
- if (!a->Z_is_one) {
+ if (!a_Z_is_one) {
if (!field_sqr(group, Za23, &a->Z, ctx) ||
!field_mul(group, tmp2, &b->X, Za23, ctx)) {
goto end;
@@ -1072,7 +883,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
}
- if (!b->Z_is_one) {
+ if (!b_Z_is_one) {
if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) ||
!field_mul(group, tmp1, &a->Y, Zb23, ctx)) {
goto end;
@@ -1081,7 +892,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
} else {
tmp1_ = &a->Y;
}
- if (!a->Z_is_one) {
+ if (!a_Z_is_one) {
if (!field_mul(group, Za23, Za23, &a->Z, ctx) ||
!field_mul(group, tmp2, &b->Y, Za23, ctx)) {
goto end;
@@ -1112,7 +923,8 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
BIGNUM *x, *y;
int ret = 0;
- if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) {
+ if (BN_cmp(&point->Z, &group->one) == 0 ||
+ EC_POINT_is_at_infinity(group, point)) {
return 1;
}
@@ -1134,7 +946,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
}
- if (!point->Z_is_one) {
+ if (BN_cmp(&point->Z, &group->one) != 0) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1193,14 +1005,8 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
goto err;
}
} else {
- if (group->meth->field_set_to_one != 0) {
- if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) {
- goto err;
- }
- } else {
- if (!BN_one(prod_Z[0])) {
- goto err;
- }
+ if (BN_copy(prod_Z[0], &group->one) == NULL) {
+ goto err;
}
}
@@ -1271,16 +1077,9 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
goto err;
}
- if (group->meth->field_set_to_one != NULL) {
- if (!group->meth->field_set_to_one(group, &p->Z, ctx)) {
- goto err;
- }
- } else {
- if (!BN_one(&p->Z)) {
- goto err;
- }
+ if (BN_copy(&p->Z, &group->one) == NULL) {
+ goto err;
}
- p->Z_is_one = 1;
}
}
diff --git a/src/crypto/ec/util-64.c b/src/crypto/ec/util-64.c
index 171b0631..40062712 100644
--- a/src/crypto/ec/util-64.c
+++ b/src/crypto/ec/util-64.c
@@ -21,80 +21,6 @@
#include "internal.h"
-/* Convert an array of points into affine coordinates. (If the point at
- * infinity is found (Z = 0), it remains unchanged.) This function is
- * essentially an equivalent to EC_POINTs_make_affine(), but works with the
- * internal representation of points as used by ecp_nistp###.c rather than
- * with (BIGNUM-based) EC_POINT data structures. point_array is the
- * input/output buffer ('num' points in projective form, i.e. three
- * coordinates each), based on an internal representation of field elements
- * of size 'felem_size'. tmp_felems needs to point to a temporary array of
- * 'num'+1 field elements for storage of intermediate values. */
-void ec_GFp_nistp_points_make_affine_internal(
- size_t num, void *point_array, size_t felem_size, void *tmp_felems,
- void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
- void (*felem_assign)(void *out, const void *in),
- void (*felem_square)(void *out, const void *in),
- void (*felem_mul)(void *out, const void *in1, const void *in2),
- void (*felem_inv)(void *out, const void *in),
- void (*felem_contract)(void *out, const void *in)) {
- int i = 0;
-
-#define tmp_felem(I) (&((char *)tmp_felems)[(I)*felem_size])
-#define X(I) (&((char *)point_array)[3 * (I)*felem_size])
-#define Y(I) (&((char *)point_array)[(3 * (I) + 1) * felem_size])
-#define Z(I) (&((char *)point_array)[(3 * (I) + 2) * felem_size])
-
- if (!felem_is_zero(Z(0))) {
- felem_assign(tmp_felem(0), Z(0));
- } else {
- felem_one(tmp_felem(0));
- }
-
- for (i = 1; i < (int)num; i++) {
- if (!felem_is_zero(Z(i))) {
- felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
- } else {
- felem_assign(tmp_felem(i), tmp_felem(i - 1));
- }
- }
- /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
- * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1. */
-
- felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
- for (i = num - 1; i >= 0; i--) {
- if (i > 0) {
- /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
- * is the inverse of the product of Z(0) .. Z(i). */
- /* 1/Z(i) */
- felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
- } else {
- felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
- }
-
- if (!felem_is_zero(Z(i))) {
- if (i > 0) {
- /* For next iteration, replace tmp_felem(i-1) by its inverse. */
- felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
- }
-
- /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1). */
- felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
- felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
- felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
- felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
- felem_contract(X(i), X(i));
- felem_contract(Y(i), Y(i));
- felem_one(Z(i));
- } else {
- if (i > 0) {
- /* For next iteration, replace tmp_felem(i-1) by its inverse. */
- felem_assign(tmp_felem(i - 1), tmp_felem(i));
- }
- }
- }
-}
-
/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
* significant bit), and recodes them into a signed digit for use in fast point
* multiplication: the use of signed rather than unsigned digits means that
diff --git a/src/crypto/ecdsa/ecdsa.c b/src/crypto/ecdsa/ecdsa.c
index 16760ed6..70cb1189 100644
--- a/src/crypto/ecdsa/ecdsa.c
+++ b/src/crypto/ecdsa/ecdsa.c
@@ -79,10 +79,6 @@ int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
int ret = 0;
uint8_t *der = NULL;
- if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
- return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey);
- }
-
/* Decode the ECDSA signature. */
s = ECDSA_SIG_from_bytes(sig, sig_len);
if (s == NULL) {
@@ -148,11 +144,6 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
const EC_GROUP *group;
const EC_POINT *pub_key;
- if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
- OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
- return 0;
- }
-
/* check input values */
if ((group = EC_KEY_get0_group(eckey)) == NULL ||
(pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
@@ -224,7 +215,7 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
ret = (BN_ucmp(u1, sig->r) == 0);
err:
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(point);
return ret;
diff --git a/src/crypto/ecdsa/ecdsa_asn1.c b/src/crypto/ecdsa/ecdsa_asn1.c
index 3fee191e..d41a5366 100644
--- a/src/crypto/ecdsa/ecdsa_asn1.c
+++ b/src/crypto/ecdsa/ecdsa_asn1.c
@@ -61,6 +61,7 @@
#include <openssl/ec_key.h>
#include <openssl/mem.h>
+#include "../bytestring/internal.h"
#include "../ec/internal.h"
@@ -115,8 +116,8 @@ ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) {
}
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
- !BN_cbs2unsigned(&child, ret->r) ||
- !BN_cbs2unsigned(&child, ret->s) ||
+ !BN_parse_asn1_unsigned(&child, ret->r) ||
+ !BN_parse_asn1_unsigned(&child, ret->s) ||
CBS_len(&child) != 0) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
ECDSA_SIG_free(ret);
@@ -140,8 +141,8 @@ ECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, size_t in_len) {
int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
- !BN_bn2cbb(&child, sig->r) ||
- !BN_bn2cbb(&child, sig->s) ||
+ !BN_marshal_asn1(&child, sig->r) ||
+ !BN_marshal_asn1(&child, sig->s) ||
!CBB_flush(cbb)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
return 0;
@@ -211,30 +212,16 @@ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) {
ECDSA_SIG_free(*out);
*out = ret;
}
- *inp += (size_t)len - CBS_len(&cbs);
+ *inp = CBS_data(&cbs);
return ret;
}
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) {
- uint8_t *der;
- size_t der_len;
- if (!ECDSA_SIG_to_bytes(&der, &der_len, sig)) {
- return -1;
- }
- if (der_len > INT_MAX) {
- OPENSSL_PUT_ERROR(ECDSA, ERR_R_OVERFLOW);
- OPENSSL_free(der);
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !ECDSA_SIG_marshal(&cbb, sig)) {
+ CBB_cleanup(&cbb);
return -1;
}
- if (outp != NULL) {
- if (*outp == NULL) {
- *outp = der;
- der = NULL;
- } else {
- memcpy(*outp, der, der_len);
- *outp += der_len;
- }
- }
- OPENSSL_free(der);
- return (int)der_len;
+ return CBB_finish_i2d(&cbb, outp);
}
diff --git a/src/crypto/ecdsa/ecdsa_test.cc b/src/crypto/ecdsa/ecdsa_test.cc
index a0c8fbd0..8d7827df 100644
--- a/src/crypto/ecdsa/ecdsa_test.cc
+++ b/src/crypto/ecdsa/ecdsa_test.cc
@@ -59,7 +59,7 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include "../test/scoped_types.h"
@@ -340,16 +340,19 @@ static bool TestECDSA_SIG_max_len(size_t order_len) {
return true;
}
+static size_t BitsToBytes(size_t bits) {
+ return (bits / 8) + (7 + (bits % 8)) / 8;
+}
+
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!TestBuiltin(stdout) ||
- !TestECDSA_SIG_max_len(224/8) ||
- !TestECDSA_SIG_max_len(256/8) ||
- !TestECDSA_SIG_max_len(384/8) ||
- !TestECDSA_SIG_max_len(512/8) ||
- !TestECDSA_SIG_max_len(10000)) {
+ !TestECDSA_SIG_max_len(BitsToBytes(224)) ||
+ !TestECDSA_SIG_max_len(BitsToBytes(256)) ||
+ !TestECDSA_SIG_max_len(BitsToBytes(384)) ||
+ !TestECDSA_SIG_max_len(BitsToBytes(521)) ||
+ !TestECDSA_SIG_max_len(BitsToBytes(10000))) {
printf("\nECDSA test failed\n");
ERR_print_errors_fp(stdout);
return 1;
diff --git a/src/crypto/err/asn1.errordata b/src/crypto/err/asn1.errordata
index b1b04375..c304b2ca 100644
--- a/src/crypto/err/asn1.errordata
+++ b/src/crypto/err/asn1.errordata
@@ -6,82 +6,87 @@ ASN1,104,BMPSTRING_IS_WRONG_LENGTH
ASN1,105,BN_LIB
ASN1,106,BOOLEAN_IS_WRONG_LENGTH
ASN1,107,BUFFER_TOO_SMALL
-ASN1,108,DECODE_ERROR
-ASN1,109,DEPTH_EXCEEDED
-ASN1,110,ENCODE_ERROR
-ASN1,111,ERROR_GETTING_TIME
-ASN1,112,EXPECTING_AN_ASN1_SEQUENCE
-ASN1,113,EXPECTING_AN_INTEGER
-ASN1,114,EXPECTING_AN_OBJECT
-ASN1,115,EXPECTING_A_BOOLEAN
-ASN1,116,EXPECTING_A_TIME
-ASN1,117,EXPLICIT_LENGTH_MISMATCH
-ASN1,118,EXPLICIT_TAG_NOT_CONSTRUCTED
-ASN1,119,FIELD_MISSING
-ASN1,120,FIRST_NUM_TOO_LARGE
-ASN1,121,HEADER_TOO_LONG
-ASN1,122,ILLEGAL_BITSTRING_FORMAT
-ASN1,123,ILLEGAL_BOOLEAN
-ASN1,124,ILLEGAL_CHARACTERS
-ASN1,125,ILLEGAL_FORMAT
-ASN1,126,ILLEGAL_HEX
-ASN1,127,ILLEGAL_IMPLICIT_TAG
-ASN1,128,ILLEGAL_INTEGER
-ASN1,129,ILLEGAL_NESTED_TAGGING
-ASN1,130,ILLEGAL_NULL
-ASN1,131,ILLEGAL_NULL_VALUE
-ASN1,132,ILLEGAL_OBJECT
-ASN1,133,ILLEGAL_OPTIONAL_ANY
-ASN1,134,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
-ASN1,135,ILLEGAL_TAGGED_ANY
-ASN1,136,ILLEGAL_TIME_VALUE
-ASN1,137,INTEGER_NOT_ASCII_FORMAT
-ASN1,138,INTEGER_TOO_LARGE_FOR_LONG
-ASN1,139,INVALID_BIT_STRING_BITS_LEFT
-ASN1,140,INVALID_BMPSTRING_LENGTH
-ASN1,141,INVALID_DIGIT
-ASN1,142,INVALID_MODIFIER
-ASN1,143,INVALID_NUMBER
-ASN1,144,INVALID_OBJECT_ENCODING
-ASN1,145,INVALID_SEPARATOR
-ASN1,146,INVALID_TIME_FORMAT
-ASN1,147,INVALID_UNIVERSALSTRING_LENGTH
-ASN1,148,INVALID_UTF8STRING
-ASN1,149,LIST_ERROR
-ASN1,150,MISSING_ASN1_EOS
-ASN1,151,MISSING_EOC
-ASN1,152,MISSING_SECOND_NUMBER
-ASN1,153,MISSING_VALUE
-ASN1,154,MSTRING_NOT_UNIVERSAL
-ASN1,155,MSTRING_WRONG_TAG
-ASN1,156,NESTED_ASN1_ERROR
-ASN1,157,NESTED_ASN1_STRING
-ASN1,158,NON_HEX_CHARACTERS
-ASN1,159,NOT_ASCII_FORMAT
-ASN1,160,NOT_ENOUGH_DATA
-ASN1,161,NO_MATCHING_CHOICE_TYPE
-ASN1,162,NULL_IS_WRONG_LENGTH
-ASN1,163,OBJECT_NOT_ASCII_FORMAT
-ASN1,164,ODD_NUMBER_OF_CHARS
-ASN1,165,SECOND_NUMBER_TOO_LARGE
-ASN1,166,SEQUENCE_LENGTH_MISMATCH
-ASN1,167,SEQUENCE_NOT_CONSTRUCTED
-ASN1,168,SEQUENCE_OR_SET_NEEDS_CONFIG
-ASN1,169,SHORT_LINE
-ASN1,170,STREAMING_NOT_SUPPORTED
-ASN1,171,STRING_TOO_LONG
-ASN1,172,STRING_TOO_SHORT
-ASN1,173,TAG_VALUE_TOO_HIGH
-ASN1,174,TIME_NOT_ASCII_FORMAT
-ASN1,175,TOO_LONG
-ASN1,176,TYPE_NOT_CONSTRUCTED
-ASN1,177,TYPE_NOT_PRIMITIVE
-ASN1,178,UNEXPECTED_EOC
-ASN1,179,UNIVERSALSTRING_IS_WRONG_LENGTH
-ASN1,180,UNKNOWN_FORMAT
-ASN1,181,UNKNOWN_TAG
-ASN1,182,UNSUPPORTED_ANY_DEFINED_BY_TYPE
-ASN1,183,UNSUPPORTED_PUBLIC_KEY_TYPE
-ASN1,184,UNSUPPORTED_TYPE
-ASN1,185,WRONG_TAG
-ASN1,186,WRONG_TYPE
+ASN1,108,CONTEXT_NOT_INITIALISED
+ASN1,109,DECODE_ERROR
+ASN1,110,DEPTH_EXCEEDED
+ASN1,111,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
+ASN1,112,ENCODE_ERROR
+ASN1,113,ERROR_GETTING_TIME
+ASN1,114,EXPECTING_AN_ASN1_SEQUENCE
+ASN1,115,EXPECTING_AN_INTEGER
+ASN1,116,EXPECTING_AN_OBJECT
+ASN1,117,EXPECTING_A_BOOLEAN
+ASN1,118,EXPECTING_A_TIME
+ASN1,119,EXPLICIT_LENGTH_MISMATCH
+ASN1,120,EXPLICIT_TAG_NOT_CONSTRUCTED
+ASN1,121,FIELD_MISSING
+ASN1,122,FIRST_NUM_TOO_LARGE
+ASN1,123,HEADER_TOO_LONG
+ASN1,124,ILLEGAL_BITSTRING_FORMAT
+ASN1,125,ILLEGAL_BOOLEAN
+ASN1,126,ILLEGAL_CHARACTERS
+ASN1,127,ILLEGAL_FORMAT
+ASN1,128,ILLEGAL_HEX
+ASN1,129,ILLEGAL_IMPLICIT_TAG
+ASN1,130,ILLEGAL_INTEGER
+ASN1,131,ILLEGAL_NESTED_TAGGING
+ASN1,132,ILLEGAL_NULL
+ASN1,133,ILLEGAL_NULL_VALUE
+ASN1,134,ILLEGAL_OBJECT
+ASN1,135,ILLEGAL_OPTIONAL_ANY
+ASN1,136,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
+ASN1,137,ILLEGAL_TAGGED_ANY
+ASN1,138,ILLEGAL_TIME_VALUE
+ASN1,139,INTEGER_NOT_ASCII_FORMAT
+ASN1,140,INTEGER_TOO_LARGE_FOR_LONG
+ASN1,141,INVALID_BIT_STRING_BITS_LEFT
+ASN1,142,INVALID_BMPSTRING_LENGTH
+ASN1,143,INVALID_DIGIT
+ASN1,144,INVALID_MODIFIER
+ASN1,145,INVALID_NUMBER
+ASN1,146,INVALID_OBJECT_ENCODING
+ASN1,147,INVALID_SEPARATOR
+ASN1,148,INVALID_TIME_FORMAT
+ASN1,149,INVALID_UNIVERSALSTRING_LENGTH
+ASN1,150,INVALID_UTF8STRING
+ASN1,151,LIST_ERROR
+ASN1,152,MISSING_ASN1_EOS
+ASN1,153,MISSING_EOC
+ASN1,154,MISSING_SECOND_NUMBER
+ASN1,155,MISSING_VALUE
+ASN1,156,MSTRING_NOT_UNIVERSAL
+ASN1,157,MSTRING_WRONG_TAG
+ASN1,158,NESTED_ASN1_ERROR
+ASN1,159,NESTED_ASN1_STRING
+ASN1,160,NON_HEX_CHARACTERS
+ASN1,161,NOT_ASCII_FORMAT
+ASN1,162,NOT_ENOUGH_DATA
+ASN1,163,NO_MATCHING_CHOICE_TYPE
+ASN1,164,NULL_IS_WRONG_LENGTH
+ASN1,165,OBJECT_NOT_ASCII_FORMAT
+ASN1,166,ODD_NUMBER_OF_CHARS
+ASN1,167,SECOND_NUMBER_TOO_LARGE
+ASN1,168,SEQUENCE_LENGTH_MISMATCH
+ASN1,169,SEQUENCE_NOT_CONSTRUCTED
+ASN1,170,SEQUENCE_OR_SET_NEEDS_CONFIG
+ASN1,171,SHORT_LINE
+ASN1,172,STREAMING_NOT_SUPPORTED
+ASN1,173,STRING_TOO_LONG
+ASN1,174,STRING_TOO_SHORT
+ASN1,175,TAG_VALUE_TOO_HIGH
+ASN1,176,TIME_NOT_ASCII_FORMAT
+ASN1,177,TOO_LONG
+ASN1,178,TYPE_NOT_CONSTRUCTED
+ASN1,179,TYPE_NOT_PRIMITIVE
+ASN1,180,UNEXPECTED_EOC
+ASN1,181,UNIVERSALSTRING_IS_WRONG_LENGTH
+ASN1,182,UNKNOWN_FORMAT
+ASN1,183,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
+ASN1,184,UNKNOWN_SIGNATURE_ALGORITHM
+ASN1,185,UNKNOWN_TAG
+ASN1,186,UNSUPPORTED_ANY_DEFINED_BY_TYPE
+ASN1,187,UNSUPPORTED_PUBLIC_KEY_TYPE
+ASN1,188,UNSUPPORTED_TYPE
+ASN1,189,WRONG_PUBLIC_KEY_TYPE
+ASN1,190,WRONG_TAG
+ASN1,191,WRONG_TYPE
diff --git a/src/crypto/err/dsa.errordata b/src/crypto/err/dsa.errordata
index 3c5764a1..6f4bc138 100644
--- a/src/crypto/err/dsa.errordata
+++ b/src/crypto/err/dsa.errordata
@@ -1,4 +1,7 @@
DSA,100,BAD_Q_VALUE
+DSA,104,BAD_VERSION
+DSA,105,DECODE_ERROR
+DSA,106,ENCODE_ERROR
DSA,101,MISSING_PARAMETERS
DSA,102,MODULUS_TOO_LARGE
DSA,103,NEED_NEW_SETUP_VALUES
diff --git a/src/crypto/err/ec.errordata b/src/crypto/err/ec.errordata
index e7b41756..d074afc9 100644
--- a/src/crypto/err/ec.errordata
+++ b/src/crypto/err/ec.errordata
@@ -2,8 +2,11 @@ EC,126,BIGNUM_OUT_OF_RANGE
EC,100,BUFFER_TOO_SMALL
EC,101,COORDINATES_OUT_OF_RANGE
EC,102,D2I_ECPKPARAMETERS_FAILURE
+EC,128,DECODE_ERROR
EC,103,EC_GROUP_NEW_BY_NAME_FAILURE
+EC,129,ENCODE_ERROR
EC,104,GROUP2PKPARAMETERS_FAILURE
+EC,130,GROUP_MISMATCH
EC,105,I2D_ECPKPARAMETERS_FAILURE
EC,106,INCOMPATIBLE_OBJECTS
EC,107,INVALID_COMPRESSED_POINT
diff --git a/src/crypto/err/err_data_generate.go b/src/crypto/err/err_data_generate.go
index 24e0d66f..893ebffe 100644
--- a/src/crypto/err/err_data_generate.go
+++ b/src/crypto/err/err_data_generate.go
@@ -18,6 +18,7 @@ import (
"bufio"
"bytes"
"errors"
+ "flag"
"fmt"
"io"
"os"
@@ -26,6 +27,8 @@ import (
"strings"
)
+var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.")
+
// libraryNames must be kept in sync with the enum in err.h. The generated code
// will contain static assertions to enforce this.
var libraryNames = []string{
@@ -138,7 +141,9 @@ type stringWriter interface {
func (st *stringList) WriteTo(out stringWriter, name string) {
list := st.buildList()
- fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+ if *verbose {
+ fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+ }
values := "kOpenSSL" + name + "Values"
out.WriteString("const uint32_t " + values + "[] = {\n")
@@ -215,6 +220,8 @@ func (e *errorData) readErrorDataFile(filename string) error {
}
func main() {
+ flag.Parse()
+
e := &errorData{
reasons: newStringList(),
libraryMap: make(map[string]uint32),
diff --git a/src/crypto/err/evp.errordata b/src/crypto/err/evp.errordata
index 8f8dd483..a482f769 100644
--- a/src/crypto/err/evp.errordata
+++ b/src/crypto/err/evp.errordata
@@ -1,46 +1,30 @@
-EVP,151,BN_DECODE_ERROR
EVP,100,BUFFER_TOO_SMALL
EVP,101,COMMAND_NOT_SUPPORTED
-EVP,146,CONTEXT_NOT_INITIALISED
-EVP,143,DECODE_ERROR
-EVP,104,DIFFERENT_KEY_TYPES
-EVP,105,DIFFERENT_PARAMETERS
-EVP,147,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
-EVP,107,EXPECTING_AN_EC_KEY_KEY
-EVP,141,EXPECTING_AN_RSA_KEY
-EVP,109,EXPECTING_A_DH_KEY
-EVP,110,EXPECTING_A_DSA_KEY
-EVP,111,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
-EVP,112,INVALID_CURVE
-EVP,113,INVALID_DIGEST_LENGTH
-EVP,114,INVALID_DIGEST_TYPE
-EVP,115,INVALID_KEYBITS
-EVP,116,INVALID_MGF1_MD
-EVP,142,INVALID_OPERATION
-EVP,118,INVALID_PADDING_MODE
-EVP,119,INVALID_PSS_PARAMETERS
-EVP,144,INVALID_PSS_SALTLEN
-EVP,121,INVALID_SALT_LENGTH
-EVP,122,INVALID_TRAILER
-EVP,123,KEYS_NOT_SET
-EVP,124,MISSING_PARAMETERS
-EVP,125,NO_DEFAULT_DIGEST
-EVP,126,NO_KEY_SET
-EVP,127,NO_MDC2_SUPPORT
-EVP,128,NO_NID_FOR_CURVE
-EVP,129,NO_OPERATION_SET
-EVP,130,NO_PARAMETERS_SET
-EVP,131,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
-EVP,132,OPERATON_NOT_INITIALIZED
-EVP,152,PARAMETER_ENCODING_ERROR
-EVP,133,UNKNOWN_DIGEST
-EVP,134,UNKNOWN_MASK_DIGEST
-EVP,150,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
-EVP,145,UNKNOWN_PUBLIC_KEY_TYPE
-EVP,149,UNKNOWN_SIGNATURE_ALGORITHM
-EVP,138,UNSUPPORTED_ALGORITHM
-EVP,139,UNSUPPORTED_MASK_ALGORITHM
-EVP,140,UNSUPPORTED_MASK_PARAMETER
-EVP,153,UNSUPPORTED_PUBLIC_KEY_TYPE
-EVP,154,UNSUPPORTED_SIGNATURE_TYPE
-EVP,148,WRONG_PUBLIC_KEY_TYPE
+EVP,102,DECODE_ERROR
+EVP,103,DIFFERENT_KEY_TYPES
+EVP,104,DIFFERENT_PARAMETERS
+EVP,105,ENCODE_ERROR
+EVP,106,EXPECTING_AN_EC_KEY_KEY
+EVP,107,EXPECTING_AN_RSA_KEY
+EVP,108,EXPECTING_A_DSA_KEY
+EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
+EVP,110,INVALID_DIGEST_LENGTH
+EVP,111,INVALID_DIGEST_TYPE
+EVP,112,INVALID_KEYBITS
+EVP,113,INVALID_MGF1_MD
+EVP,114,INVALID_OPERATION
+EVP,115,INVALID_PADDING_MODE
+EVP,116,INVALID_PSS_SALTLEN
+EVP,117,KEYS_NOT_SET
+EVP,118,MISSING_PARAMETERS
+EVP,119,NO_DEFAULT_DIGEST
+EVP,120,NO_KEY_SET
+EVP,121,NO_MDC2_SUPPORT
+EVP,122,NO_NID_FOR_CURVE
+EVP,123,NO_OPERATION_SET
+EVP,124,NO_PARAMETERS_SET
+EVP,125,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
+EVP,126,OPERATON_NOT_INITIALIZED
+EVP,127,UNKNOWN_PUBLIC_KEY_TYPE
+EVP,128,UNSUPPORTED_ALGORITHM
+EVP,129,UNSUPPORTED_PUBLIC_KEY_TYPE
diff --git a/src/crypto/err/rsa.errordata b/src/crypto/err/rsa.errordata
index c19f73c7..62d286cc 100644
--- a/src/crypto/err/rsa.errordata
+++ b/src/crypto/err/rsa.errordata
@@ -1,46 +1,46 @@
-RSA,143,BAD_ENCODING
-RSA,100,BAD_E_VALUE
-RSA,101,BAD_FIXED_HEADER_DECRYPT
-RSA,102,BAD_PAD_BYTE_COUNT
-RSA,103,BAD_RSA_PARAMETERS
-RSA,104,BAD_SIGNATURE
-RSA,145,BAD_VERSION
-RSA,105,BLOCK_TYPE_IS_NOT_01
-RSA,106,BN_NOT_INITIALIZED
-RSA,142,CANNOT_RECOVER_MULTI_PRIME_KEY
-RSA,107,CRT_PARAMS_ALREADY_GIVEN
-RSA,108,CRT_VALUES_INCORRECT
-RSA,109,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
-RSA,110,DATA_TOO_LARGE
-RSA,111,DATA_TOO_LARGE_FOR_KEY_SIZE
-RSA,112,DATA_TOO_LARGE_FOR_MODULUS
-RSA,113,DATA_TOO_SMALL
-RSA,114,DATA_TOO_SMALL_FOR_KEY_SIZE
-RSA,115,DIGEST_TOO_BIG_FOR_RSA_KEY
-RSA,116,D_E_NOT_CONGRUENT_TO_1
-RSA,117,EMPTY_PUBLIC_KEY
-RSA,144,ENCODE_ERROR
-RSA,118,FIRST_OCTET_INVALID
-RSA,119,INCONSISTENT_SET_OF_CRT_VALUES
-RSA,120,INTERNAL_ERROR
-RSA,121,INVALID_MESSAGE_LENGTH
-RSA,122,KEY_SIZE_TOO_SMALL
-RSA,123,LAST_OCTET_INVALID
-RSA,124,MODULUS_TOO_LARGE
-RSA,141,MUST_HAVE_AT_LEAST_TWO_PRIMES
-RSA,125,NO_PUBLIC_EXPONENT
-RSA,126,NULL_BEFORE_BLOCK_MISSING
-RSA,127,N_NOT_EQUAL_P_Q
-RSA,128,OAEP_DECODING_ERROR
-RSA,129,ONLY_ONE_OF_P_Q_GIVEN
-RSA,130,OUTPUT_BUFFER_TOO_SMALL
-RSA,131,PADDING_CHECK_FAILED
-RSA,132,PKCS_DECODING_ERROR
-RSA,133,SLEN_CHECK_FAILED
-RSA,134,SLEN_RECOVERY_FAILED
-RSA,135,TOO_LONG
-RSA,136,TOO_MANY_ITERATIONS
-RSA,137,UNKNOWN_ALGORITHM_TYPE
-RSA,138,UNKNOWN_PADDING_TYPE
-RSA,139,VALUE_MISSING
-RSA,140,WRONG_SIGNATURE_LENGTH
+RSA,100,BAD_ENCODING
+RSA,101,BAD_E_VALUE
+RSA,102,BAD_FIXED_HEADER_DECRYPT
+RSA,103,BAD_PAD_BYTE_COUNT
+RSA,104,BAD_RSA_PARAMETERS
+RSA,105,BAD_SIGNATURE
+RSA,106,BAD_VERSION
+RSA,107,BLOCK_TYPE_IS_NOT_01
+RSA,108,BN_NOT_INITIALIZED
+RSA,109,CANNOT_RECOVER_MULTI_PRIME_KEY
+RSA,110,CRT_PARAMS_ALREADY_GIVEN
+RSA,111,CRT_VALUES_INCORRECT
+RSA,112,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+RSA,113,DATA_TOO_LARGE
+RSA,114,DATA_TOO_LARGE_FOR_KEY_SIZE
+RSA,115,DATA_TOO_LARGE_FOR_MODULUS
+RSA,116,DATA_TOO_SMALL
+RSA,117,DATA_TOO_SMALL_FOR_KEY_SIZE
+RSA,118,DIGEST_TOO_BIG_FOR_RSA_KEY
+RSA,119,D_E_NOT_CONGRUENT_TO_1
+RSA,120,EMPTY_PUBLIC_KEY
+RSA,121,ENCODE_ERROR
+RSA,122,FIRST_OCTET_INVALID
+RSA,123,INCONSISTENT_SET_OF_CRT_VALUES
+RSA,124,INTERNAL_ERROR
+RSA,125,INVALID_MESSAGE_LENGTH
+RSA,126,KEY_SIZE_TOO_SMALL
+RSA,127,LAST_OCTET_INVALID
+RSA,128,MODULUS_TOO_LARGE
+RSA,129,MUST_HAVE_AT_LEAST_TWO_PRIMES
+RSA,130,NO_PUBLIC_EXPONENT
+RSA,131,NULL_BEFORE_BLOCK_MISSING
+RSA,132,N_NOT_EQUAL_P_Q
+RSA,133,OAEP_DECODING_ERROR
+RSA,134,ONLY_ONE_OF_P_Q_GIVEN
+RSA,135,OUTPUT_BUFFER_TOO_SMALL
+RSA,136,PADDING_CHECK_FAILED
+RSA,137,PKCS_DECODING_ERROR
+RSA,138,SLEN_CHECK_FAILED
+RSA,139,SLEN_RECOVERY_FAILED
+RSA,140,TOO_LONG
+RSA,141,TOO_MANY_ITERATIONS
+RSA,142,UNKNOWN_ALGORITHM_TYPE
+RSA,143,UNKNOWN_PADDING_TYPE
+RSA,144,VALUE_MISSING
+RSA,145,WRONG_SIGNATURE_LENGTH
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index 3766bb98..dfe4ac81 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -108,6 +108,7 @@ SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
SSL,207,SERVERHELLO_TLSEXT
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
SSL,209,SESSION_MAY_NOT_BE_CREATED
+SSL,250,SHUTDOWN_WHILE_IN_INIT
SSL,210,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER
SSL,211,SRTP_COULD_NOT_ALLOCATE_PROFILES
SSL,212,SRTP_UNKNOWN_PROTECTION_PROFILE
diff --git a/src/crypto/err/x509.errordata b/src/crypto/err/x509.errordata
index f4828ce8..a1d49b71 100644
--- a/src/crypto/err/x509.errordata
+++ b/src/crypto/err/x509.errordata
@@ -10,28 +10,26 @@ X509,108,IDP_MISMATCH
X509,109,INVALID_BIT_STRING_BITS_LEFT
X509,110,INVALID_DIRECTORY
X509,111,INVALID_FIELD_NAME
-X509,112,INVALID_TRUST
-X509,113,ISSUER_MISMATCH
-X509,114,KEY_TYPE_MISMATCH
-X509,115,KEY_VALUES_MISMATCH
-X509,116,LOADING_CERT_DIR
-X509,117,LOADING_DEFAULTS
-X509,118,METHOD_NOT_SUPPORTED
+X509,112,INVALID_PSS_PARAMETERS
+X509,113,INVALID_TRUST
+X509,114,ISSUER_MISMATCH
+X509,115,KEY_TYPE_MISMATCH
+X509,116,KEY_VALUES_MISMATCH
+X509,117,LOADING_CERT_DIR
+X509,118,LOADING_DEFAULTS
X509,119,NEWER_CRL_NOT_NEWER
X509,120,NOT_PKCS7_SIGNED_DATA
X509,121,NO_CERTIFICATES_INCLUDED
X509,122,NO_CERT_SET_FOR_US_TO_VERIFY
-X509,136,NO_CRLS_INCLUDED
-X509,123,NO_CRL_NUMBER
-X509,124,PUBLIC_KEY_DECODE_ERROR
-X509,125,PUBLIC_KEY_ENCODE_ERROR
-X509,126,SHOULD_RETRY
-X509,127,UNABLE_TO_FIND_PARAMETERS_IN_CHAIN
-X509,128,UNABLE_TO_GET_CERTS_PUBLIC_KEY
-X509,129,UNKNOWN_KEY_TYPE
-X509,130,UNKNOWN_NID
-X509,131,UNKNOWN_PURPOSE_ID
-X509,132,UNKNOWN_TRUST_ID
-X509,133,UNSUPPORTED_ALGORITHM
-X509,134,WRONG_LOOKUP_TYPE
-X509,135,WRONG_TYPE
+X509,123,NO_CRLS_INCLUDED
+X509,124,NO_CRL_NUMBER
+X509,125,PUBLIC_KEY_DECODE_ERROR
+X509,126,PUBLIC_KEY_ENCODE_ERROR
+X509,127,SHOULD_RETRY
+X509,128,UNKNOWN_KEY_TYPE
+X509,129,UNKNOWN_NID
+X509,130,UNKNOWN_PURPOSE_ID
+X509,131,UNKNOWN_TRUST_ID
+X509,132,UNSUPPORTED_ALGORITHM
+X509,133,WRONG_LOOKUP_TYPE
+X509,134,WRONG_TYPE
diff --git a/src/crypto/evp/CMakeLists.txt b/src/crypto/evp/CMakeLists.txt
index 000f0762..ca1b5112 100644
--- a/src/crypto/evp/CMakeLists.txt
+++ b/src/crypto/evp/CMakeLists.txt
@@ -5,7 +5,6 @@ add_library(
OBJECT
- algorithm.c
digestsign.c
evp.c
evp_asn1.c
@@ -16,6 +15,7 @@ add_library(
p_rsa.c
p_rsa_asn1.c
pbkdf.c
+ print.c
sign.c
)
diff --git a/src/crypto/evp/evp.c b/src/crypto/evp/evp.c
index afe5c38a..79993aab 100644
--- a/src/crypto/evp/evp.c
+++ b/src/crypto/evp/evp.c
@@ -59,12 +59,11 @@
#include <assert.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rsa.h>
#include <openssl/thread.h>
@@ -195,11 +194,12 @@ int EVP_PKEY_id(const EVP_PKEY *pkey) {
return pkey->type;
}
-/* TODO(fork): remove the first argument. */
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
+/* evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which
+ * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
+ * unknown. */
+static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
switch (nid) {
case EVP_PKEY_RSA:
- case EVP_PKEY_RSA2:
return &rsa_asn1_meth;
case EVP_PKEY_EC:
return &ec_asn1_meth;
@@ -211,7 +211,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
}
int EVP_PKEY_type(int nid) {
- const EVP_PKEY_ASN1_METHOD *meth = EVP_PKEY_asn1_find(NULL, nid);
+ const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid);
if (meth == NULL) {
return NID_undef;
}
@@ -310,19 +310,6 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
return key != NULL;
}
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pengine,
- const char *name,
- size_t len) {
- if (len == 3 && memcmp(name, "RSA", 3) == 0) {
- return &rsa_asn1_meth;
- } if (len == 2 && memcmp(name, "EC", 2) == 0) {
- return &ec_asn1_meth;
- } else if (len == 3 && memcmp(name, "DSA", 3) == 0) {
- return &dsa_asn1_meth;
- }
- return NULL;
-}
-
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
const EVP_PKEY_ASN1_METHOD *ameth;
@@ -330,10 +317,10 @@ int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
free_it(pkey);
}
- ameth = EVP_PKEY_asn1_find(NULL, type);
+ ameth = evp_pkey_asn1_find(type);
if (ameth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
- ERR_add_error_dataf("algorithm %d (%s)", type, OBJ_nid2sn(type));
+ ERR_add_error_dataf("algorithm %d", type);
return 0;
}
@@ -357,41 +344,6 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
return -2;
}
-static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
- const char *kstr) {
- BIO_indent(out, indent, 128);
- BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
- OBJ_nid2ln(pkey->type));
- return 1;
-}
-
-int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->pub_print) {
- return pkey->ameth->pub_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Public Key");
-}
-
-int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->priv_print) {
- return pkey->ameth->priv_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Private Key");
-}
-
-int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->param_print) {
- return pkey->ameth->param_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Parameters");
-}
-
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
(void *)md);
diff --git a/src/crypto/evp/evp_asn1.c b/src/crypto/evp/evp_asn1.c
index c57f4113..3681d4fc 100644
--- a/src/crypto/evp/evp_asn1.c
+++ b/src/crypto/evp/evp_asn1.c
@@ -56,112 +56,269 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/dsa.h>
+#include <openssl/ec_key.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
+#include <openssl/rsa.h>
#include "internal.h"
-EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
- long len) {
- EVP_PKEY *ret;
+static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
+ &rsa_asn1_meth,
+ &ec_asn1_meth,
+ &dsa_asn1_meth,
+};
- if (out == NULL || *out == NULL) {
- ret = EVP_PKEY_new();
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EVP_LIB);
- return NULL;
+static int parse_key_type(CBS *cbs, int *out_type) {
+ CBS oid;
+ if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
+ return 0;
+ }
+
+ unsigned i;
+ for (i = 0; i < sizeof(kASN1Methods)/sizeof(kASN1Methods[0]); i++) {
+ const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
+ if (CBS_len(&oid) == method->oid_len &&
+ memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
+ *out_type = method->pkey_id;
+ return 1;
}
- } else {
- ret = *out;
}
- if (!EVP_PKEY_set_type(ret, type)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
+ return 0;
+}
+
+EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
+ /* Parse the SubjectPublicKeyInfo. */
+ CBS spki, algorithm, key;
+ int type;
+ uint8_t padding;
+ if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !parse_key_type(&algorithm, &type) ||
+ !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
+ CBS_len(&spki) != 0 ||
+ /* Every key type defined encodes the key as a byte string with the same
+ * conversion to BIT STRING. */
+ !CBS_get_u8(&key, &padding) ||
+ padding != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ /* Set up an |EVP_PKEY| of the appropriate type. */
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL ||
+ !EVP_PKEY_set_type(ret, type)) {
+ goto err;
+ }
+
+ /* Call into the type-specific SPKI decoding function. */
+ if (ret->ameth->pub_decode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+ if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
+ if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+
+ return key->ameth->pub_encode(cbb, key);
+}
+
+EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
+ /* Parse the PrivateKeyInfo. */
+ CBS pkcs8, algorithm, key;
+ uint64_t version;
+ int type;
+ if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&pkcs8, &version) ||
+ version != 0 ||
+ !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !parse_key_type(&algorithm, &type) ||
+ !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */
+
+ /* Set up an |EVP_PKEY| of the appropriate type. */
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL ||
+ !EVP_PKEY_set_type(ret, type)) {
goto err;
}
- const uint8_t *in = *inp;
- if (!ret->ameth->old_priv_decode ||
- !ret->ameth->old_priv_decode(ret, &in, len)) {
- if (ret->ameth->priv_decode) {
- /* Reset |in| in case |old_priv_decode| advanced it on error. */
- in = *inp;
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &in, len);
- if (!p8) {
+ /* Call into the type-specific PrivateKeyInfo decoding function. */
+ if (ret->ameth->priv_decode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+ if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
+ if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+
+ return key->ameth->priv_encode(cbb, key);
+}
+
+static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ switch (type) {
+ case EVP_PKEY_EC: {
+ EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
+ if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
+ EC_KEY_free(ec_key);
goto err;
}
- EVP_PKEY_free(ret);
- ret = EVP_PKCS82PKEY(p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (ret == NULL) {
+ return ret;
+ }
+ case EVP_PKEY_DSA: {
+ DSA *dsa = DSA_parse_private_key(cbs);
+ if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
+ DSA_free(dsa);
+ goto err;
+ }
+ return ret;
+ }
+ case EVP_PKEY_RSA: {
+ RSA *rsa = RSA_parse_private_key(cbs);
+ if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
+ RSA_free(rsa);
goto err;
}
- } else {
- OPENSSL_PUT_ERROR(EVP, ERR_R_ASN1_LIB);
+ return ret;
+ }
+ default:
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
+ }
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
+ long len) {
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ /* Parse with the legacy format. */
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EVP_PKEY *ret = old_priv_decode(&cbs, type);
+ if (ret == NULL) {
+ /* Try again with PKCS#8. */
+ ERR_clear_error();
+ CBS_init(&cbs, *inp, (size_t)len);
+ ret = EVP_parse_private_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (ret->type != type) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ EVP_PKEY_free(ret);
+ return NULL;
}
}
if (out != NULL) {
+ EVP_PKEY_free(*out);
*out = ret;
}
- *inp = in;
+ *inp = CBS_data(&cbs);
return ret;
+}
-err:
- if (out == NULL || *out != ret) {
- EVP_PKEY_free(ret);
+/* num_elements parses one SEQUENCE from |in| and returns the number of elements
+ * in it. On parse error, it returns zero. */
+static size_t num_elements(const uint8_t *in, size_t in_len) {
+ CBS cbs, sequence;
+ CBS_init(&cbs, in, (size_t)in_len);
+
+ if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
+ return 0;
}
- return NULL;
+
+ size_t count = 0;
+ while (CBS_len(&sequence) > 0) {
+ if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
+ return 0;
+ }
+
+ count++;
+ }
+
+ return count;
}
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
- STACK_OF(ASN1_TYPE) *inkey;
- const uint8_t *p;
- int keytype;
- p = *inp;
-
- /* Dirty trick: read in the ASN1 data into out STACK_OF(ASN1_TYPE):
- * by analyzing it we can determine the passed structure: this
- * assumes the input is surrounded by an ASN1 SEQUENCE. */
- inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, len);
- /* Since we only need to discern "traditional format" RSA and DSA
- * keys we can just count the elements. */
- if (sk_ASN1_TYPE_num(inkey) == 6) {
- keytype = EVP_PKEY_DSA;
- } else if (sk_ASN1_TYPE_num(inkey) == 4) {
- keytype = EVP_PKEY_EC;
- } else if (sk_ASN1_TYPE_num(inkey) == 3) {
- /* This seems to be PKCS8, not traditional format */
- p = *inp;
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
- EVP_PKEY *ret;
-
- sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
- if (!p8) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return NULL;
- }
- ret = EVP_PKCS82PKEY(p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (ret == NULL) {
- return NULL;
- }
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
- *inp = p;
- if (out) {
+ /* Parse the input as a PKCS#8 PrivateKeyInfo. */
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+ if (ret != NULL) {
+ if (out != NULL) {
+ EVP_PKEY_free(*out);
*out = ret;
}
+ *inp = CBS_data(&cbs);
return ret;
- } else {
- keytype = EVP_PKEY_RSA;
}
+ ERR_clear_error();
+
+ /* Count the elements to determine the legacy key format. */
+ switch (num_elements(*inp, (size_t)len)) {
+ case 4:
+ return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
+
+ case 6:
+ return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
- sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
- return d2i_PrivateKey(keytype, out, inp, len);
+ default:
+ return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
+ }
}
int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
diff --git a/src/crypto/evp/evp_ctx.c b/src/crypto/evp/evp_ctx.c
index 9e038cd2..f510f6c7 100644
--- a/src/crypto/evp/evp_ctx.c
+++ b/src/crypto/evp/evp_ctx.c
@@ -56,12 +56,10 @@
#include <openssl/evp.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include "internal.h"
@@ -98,8 +96,7 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
if (pmeth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
- const char *name = OBJ_nid2sn(id);
- ERR_add_error_dataf("algorithm %d (%s)", id, name);
+ ERR_add_error_dataf("algorithm %d", id);
return NULL;
}
@@ -193,12 +190,6 @@ err:
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
-void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) {
- ctx->app_data = data;
-}
-
-void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) { return ctx->app_data; }
-
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
int p1, void *p2) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
@@ -229,15 +220,6 @@ int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) {
}
ctx->operation = EVP_PKEY_OP_SIGN;
- if (!ctx->pmeth->sign_init) {
- return 1;
- }
-
- if (!ctx->pmeth->sign_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return 0;
- }
-
return 1;
}
@@ -260,14 +242,6 @@ int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) {
return 0;
}
ctx->operation = EVP_PKEY_OP_VERIFY;
- if (!ctx->pmeth->verify_init) {
- return 1;
- }
- if (!ctx->pmeth->verify_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return 0;
- }
-
return 1;
}
@@ -290,13 +264,6 @@ int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) {
return 0;
}
ctx->operation = EVP_PKEY_OP_ENCRYPT;
- if (!ctx->pmeth->encrypt_init) {
- return 1;
- }
- if (!ctx->pmeth->encrypt_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return 0;
- }
return 1;
}
@@ -319,13 +286,6 @@ int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) {
return 0;
}
ctx->operation = EVP_PKEY_OP_DECRYPT;
- if (!ctx->pmeth->decrypt_init) {
- return 1;
- }
- if (!ctx->pmeth->decrypt_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return 0;
- }
return 1;
}
@@ -342,19 +302,34 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
}
-int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) {
- if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
- ctx->operation = EVP_PKEY_OP_DERIVE;
- if (!ctx->pmeth->derive_init) {
- return 1;
+ ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
+ return 1;
+}
+
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
+ const uint8_t *sig, size_t sig_len) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
}
- if (!ctx->pmeth->derive_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return ctx->pmeth->verify_recover(ctx, out, out_len, sig, sig_len);
+}
+
+int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
+ ctx->operation = EVP_PKEY_OP_DERIVE;
return 1;
}
@@ -436,13 +411,6 @@ int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) {
return 0;
}
ctx->operation = EVP_PKEY_OP_KEYGEN;
- if (!ctx->pmeth->keygen_init) {
- return 1;
- }
- if (!ctx->pmeth->keygen_init(ctx)) {
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return 0;
- }
return 1;
}
diff --git a/src/crypto/evp/evp_extra_test.cc b/src/crypto/evp/evp_extra_test.cc
index fe7a0024..9bc36ad8 100644
--- a/src/crypto/evp/evp_extra_test.cc
+++ b/src/crypto/evp/evp_extra_test.cc
@@ -15,6 +15,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <utility>
#include <vector>
@@ -25,7 +26,6 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "../test/scoped_types.h"
@@ -177,142 +177,6 @@ static const uint8_t kSignature[] = {
0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
};
-// kExamplePSSCert is an example self-signed certificate, signed with
-// kExampleRSAKeyDER using RSA-PSS with default hash functions.
-static const uint8_t kExamplePSSCert[] = {
- 0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
- 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
- 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02, 0x01, 0x6a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
- 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
- 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
- 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
- 0x34, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39, 0x35, 0x35, 0x5a,
- 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39,
- 0x35, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
- 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
- 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
- 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
- 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
- 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4,
- 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d,
- 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83,
- 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c,
- 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf,
- 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33,
- 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7,
- 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77,
- 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52,
- 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c,
- 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64,
- 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e,
- 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd0,
- 0x41, 0xfb, 0x89, 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49,
- 0x11, 0xf9, 0x55, 0x81, 0x78, 0x1f, 0x13, 0x30, 0x1f, 0x06, 0x03, 0x55,
- 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd0, 0x41, 0xfb, 0x89,
- 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49, 0x11, 0xf9, 0x55,
- 0x81, 0x78, 0x1f, 0x13, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
- 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02,
- 0x01, 0x6a, 0x03, 0x81, 0x81, 0x00, 0x49, 0x4c, 0xb6, 0x45, 0x97, 0x20,
- 0x35, 0xb3, 0x50, 0x64, 0x0d, 0x3f, 0xec, 0x5f, 0x95, 0xd5, 0x84, 0xcb,
- 0x11, 0x7c, 0x03, 0xd7, 0xa6, 0xe6, 0xfa, 0x24, 0x95, 0x9f, 0x31, 0xb0,
- 0xb5, 0xec, 0x66, 0x41, 0x51, 0x18, 0x21, 0x91, 0xbb, 0xe0, 0xaf, 0xf0,
- 0xc5, 0xb7, 0x59, 0x41, 0xd4, 0xdb, 0xa4, 0xd2, 0x64, 0xa7, 0x54, 0x0f,
- 0x8c, 0xf7, 0xe1, 0xd3, 0x3b, 0x1a, 0xb7, 0x0e, 0x9d, 0x9a, 0xde, 0x50,
- 0xa1, 0x9f, 0x0a, 0xf0, 0xda, 0x34, 0x0e, 0x34, 0x7d, 0x76, 0x07, 0xfe,
- 0x5a, 0xfb, 0xf9, 0x58, 0x9b, 0xc9, 0x50, 0x84, 0x01, 0xa0, 0x05, 0x4d,
- 0x67, 0x42, 0x0b, 0xf8, 0xe4, 0x05, 0xcf, 0xaf, 0x8b, 0x71, 0x31, 0xf1,
- 0x0f, 0x6e, 0xc9, 0x24, 0x27, 0x9b, 0xac, 0x04, 0xd7, 0x64, 0x0d, 0x30,
- 0x4e, 0x11, 0x93, 0x40, 0x39, 0xbb, 0x72, 0xb2, 0xfe, 0x6b, 0xe4, 0xae,
- 0x8c, 0x16,
-};
-
-// kBadPSSCert is an example RSA-PSS certificate with bad parameters.
-static const uint8_t kBadPSSCert[] = {
- 0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x02, 0x3a, 0xa0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x09, 0x00, 0xd7, 0x30, 0x64, 0xbc, 0x9f, 0x12, 0xfe, 0xc3,
- 0x30, 0x3e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
- 0x0a, 0x30, 0x31, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
- 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x1a, 0x30, 0x18, 0x06, 0x09,
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0b, 0x06,
- 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa2, 0x04,
- 0x02, 0x02, 0x00, 0xde, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03,
- 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6e,
- 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63, 0x65,
- 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17,
- 0x0d, 0x31, 0x35, 0x31, 0x31, 0x30, 0x34, 0x31, 0x36, 0x30, 0x32, 0x33,
- 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x32, 0x30, 0x34, 0x31, 0x36,
- 0x30, 0x32, 0x33, 0x35, 0x5a, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49,
- 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63,
- 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x82,
- 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
- 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0xda, 0x33, 0xb5, 0x87,
- 0xa9, 0x50, 0x80, 0x18, 0x02, 0x00, 0xfb, 0x32, 0xf5, 0x29, 0x6b, 0xef,
- 0x01, 0x24, 0xeb, 0x86, 0x5a, 0xbe, 0xd5, 0xe3, 0xdd, 0x3b, 0xbc, 0x2c,
- 0xad, 0x65, 0xf6, 0x2a, 0x26, 0x28, 0x4d, 0x8a, 0xc9, 0x61, 0x39, 0xf1,
- 0x84, 0xb9, 0xe7, 0xd3, 0x0a, 0xc7, 0xa8, 0x0a, 0x6d, 0xef, 0xd9, 0xcb,
- 0x20, 0x11, 0xbb, 0x71, 0xf4, 0xa1, 0xc9, 0x9a, 0x85, 0x1c, 0xe6, 0x3f,
- 0x23, 0x39, 0x58, 0x3c, 0xc5, 0x6d, 0xfa, 0x03, 0xe8, 0xdb, 0xdd, 0xe0,
- 0xc3, 0xde, 0x85, 0x76, 0xce, 0x49, 0x06, 0xc8, 0xe1, 0x8e, 0x4c, 0x86,
- 0x9c, 0xec, 0xab, 0xf4, 0xe5, 0x27, 0xb4, 0x5a, 0xaf, 0xc4, 0x36, 0xd3,
- 0x20, 0x81, 0x54, 0xee, 0x8f, 0x48, 0x77, 0x10, 0xf8, 0x79, 0xd6, 0xaa,
- 0x8d, 0x1b, 0xfe, 0x7d, 0xe8, 0x15, 0x13, 0xe0, 0x7b, 0xf6, 0x90, 0xe4,
- 0xe2, 0xcd, 0x2e, 0x8e, 0xc9, 0x3a, 0x75, 0x42, 0xed, 0x0a, 0x0f, 0x51,
- 0xb2, 0xdd, 0x2e, 0x70, 0x61, 0x68, 0xd7, 0xd9, 0xab, 0xf9, 0xbe, 0xe4,
- 0x75, 0xb7, 0xe7, 0xf2, 0x96, 0x7b, 0xd9, 0x93, 0x43, 0x24, 0xfb, 0x9e,
- 0x55, 0xda, 0xd4, 0x01, 0x6c, 0x3d, 0xa2, 0x59, 0x7a, 0xd5, 0x47, 0x18,
- 0x7e, 0x4e, 0xf9, 0x5d, 0xda, 0xcb, 0x93, 0xa2, 0x65, 0x2f, 0x8d, 0x46,
- 0xad, 0x81, 0xdc, 0xf0, 0xa9, 0x5f, 0x5d, 0xfe, 0x37, 0x80, 0x64, 0x2a,
- 0x41, 0xfa, 0xe9, 0x1e, 0x48, 0x38, 0x22, 0x1d, 0x9c, 0x23, 0xa5, 0xad,
- 0xda, 0x78, 0x45, 0x18, 0x0c, 0xeb, 0x95, 0xca, 0x2b, 0xcc, 0xb9, 0x62,
- 0x40, 0x85, 0x09, 0x44, 0x88, 0x4c, 0xf2, 0x1e, 0x08, 0x80, 0x37, 0xe9,
- 0x06, 0x96, 0x8f, 0x75, 0x54, 0x0b, 0xa9, 0x2d, 0xa9, 0x15, 0xb5, 0xda,
- 0xe5, 0xe4, 0x23, 0xaa, 0x2c, 0x89, 0xc1, 0xa9, 0x36, 0xbc, 0x9f, 0x02,
- 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03,
- 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78,
- 0xa0, 0x65, 0x2d, 0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6,
- 0xe1, 0x5f, 0x7b, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
- 0x30, 0x16, 0x80, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78, 0xa0, 0x65, 0x2d,
- 0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6, 0xe1, 0x5f, 0x7b,
- 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01,
- 0x01, 0xff, 0x30, 0x31, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x0a, 0x30, 0x24, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x0d, 0x30, 0x0b,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0xa2,
- 0x04, 0x02, 0x02, 0x00, 0xde, 0x03, 0x82, 0x01, 0x01, 0x00, 0x08, 0xc1,
- 0xb6, 0x6f, 0x74, 0x94, 0x6c, 0x60, 0x75, 0xd8, 0xdc, 0xe1, 0x7b, 0xbf,
- 0x9d, 0xb5, 0xd7, 0x14, 0x75, 0x6c, 0xdb, 0x35, 0x5c, 0x1e, 0xff, 0xe6,
- 0xa8, 0xe6, 0x68, 0x42, 0x41, 0x81, 0xf6, 0xbf, 0xc1, 0x56, 0x02, 0xdb,
- 0xc6, 0x11, 0xeb, 0x15, 0x9d, 0xa9, 0x1c, 0x61, 0x25, 0x6d, 0x46, 0x0f,
- 0x7e, 0x27, 0xdd, 0x4b, 0xdc, 0xed, 0x07, 0xbd, 0xde, 0xd5, 0xde, 0x09,
- 0xf8, 0xfd, 0xbd, 0xa3, 0x4c, 0x81, 0xa9, 0xf7, 0x78, 0xff, 0x01, 0x80,
- 0x73, 0xf2, 0x40, 0xf2, 0xa8, 0x27, 0xe8, 0x00, 0x04, 0x3b, 0xf5, 0xe7,
- 0xa6, 0x58, 0x45, 0x79, 0x34, 0x49, 0x42, 0xd2, 0xd9, 0x56, 0x5e, 0xf9,
- 0x0a, 0x41, 0xd7, 0x81, 0x41, 0x94, 0x77, 0x78, 0x7e, 0x00, 0x3b, 0xca,
- 0xb5, 0xc0, 0x6e, 0x5b, 0xd7, 0x52, 0x52, 0x77, 0x1a, 0x52, 0xb8, 0x0d,
- 0x29, 0x1f, 0x2e, 0xfe, 0x1f, 0xf6, 0xb0, 0xc1, 0xb7, 0xf1, 0x15, 0x98,
- 0x0f, 0x30, 0x5d, 0x74, 0x2f, 0xfa, 0xe9, 0x84, 0xda, 0xde, 0xbe, 0xca,
- 0x91, 0x55, 0x1f, 0x5b, 0xbc, 0xaa, 0x45, 0x07, 0xc4, 0x2e, 0x21, 0x8a,
- 0x75, 0xc9, 0xbe, 0x6e, 0x39, 0x53, 0x10, 0xcb, 0x2f, 0x4b, 0xe1, 0x21,
- 0x1e, 0xea, 0x7d, 0x0b, 0x36, 0xe9, 0xa0, 0x2c, 0x76, 0x17, 0x1f, 0x69,
- 0x34, 0xfb, 0x45, 0x63, 0x7c, 0x84, 0x39, 0xb4, 0x21, 0x98, 0xbd, 0x49,
- 0xca, 0x80, 0x91, 0x5a, 0xa0, 0x44, 0xef, 0x91, 0xb3, 0x14, 0xf6, 0xd1,
- 0x6a, 0x2b, 0xb1, 0xe5, 0x4a, 0x44, 0x92, 0x7b, 0x3e, 0x8b, 0x7b, 0x6b,
- 0x90, 0x6b, 0x2c, 0x67, 0x3b, 0x0e, 0xb9, 0x5a, 0x87, 0x35, 0x33, 0x59,
- 0x94, 0x2f, 0x7e, 0xf6, 0x13, 0xc7, 0x22, 0x87, 0x3d, 0x50, 0xc9, 0x80,
- 0x40, 0xda, 0x35, 0xbc, 0x62, 0x16, 0xdc, 0xd5, 0x95, 0xa1, 0xe1, 0x9b,
- 0x68, 0x9f,
-};
-
// kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
// PrivateKeyInfo.
static const uint8_t kExampleRSAKeyPKCS8[] = {
@@ -387,6 +251,61 @@ static const uint8_t kExampleECKeyDER[] = {
0xc1,
};
+// kExampleECKeyPKCS8 is a sample EC private key encoded as a PKCS#8
+// PrivateKeyInfo.
+static const uint8_t kExampleECKeyPKCS8[] = {
+ 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+ 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf,
+ 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab,
+ 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42,
+ 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5,
+ 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90,
+ 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba,
+ 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73,
+ 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7,
+ 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
+
+// kExampleECKeySpecifiedCurvePKCS8 is a sample EC private key encoded as a
+// PKCS#8 PrivateKeyInfo with P-256's parameters spelled out rather than using
+// the curve OID.
+static const uint8_t kExampleECKeySpecifiedCurvePKCS8[] = {
+ 0x30, 0x82, 0x01, 0x79, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x03, 0x06,
+ 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02,
+ 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
+ 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
+ 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+ 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
+ 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
+ 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
+ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
+ 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
+ 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
+ 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
+ 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
+ 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
+ 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
+ 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01,
+ 0x01, 0x04, 0x20, 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8,
+ 0xfa, 0x16, 0xdf, 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47,
+ 0x91, 0x95, 0xab, 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1,
+ 0x44, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f,
+ 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7,
+ 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38,
+ 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5,
+ 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b,
+ 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
+
// kExampleBadECKeyDER is a sample EC private key encoded as an ECPrivateKey
// structure. The private key is equal to the order and will fail to import.
static const uint8_t kExampleBadECKeyDER[] = {
@@ -502,179 +421,81 @@ static bool TestEVP_DigestVerifyInit(void) {
return true;
}
-// TestAlgorithmRoundtrip signs a message using an already-initialized
-// |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
-// AlgorithmIdentifier to verify the signature.
-static bool TestAlgorithmRoundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
- if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
- return false;
- }
-
- // Save the algorithm.
- ScopedX509_ALGOR algor(X509_ALGOR_new());
- if (!algor || !EVP_DigestSignAlgorithm(md_ctx, algor.get())) {
- return false;
- }
-
- // Determine the size of the signature.
- size_t sig_len = 0;
- if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
- return false;
- }
- // Sanity check for testing.
- if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
- fprintf(stderr, "sig_len mismatch\n");
- return false;
- }
-
- std::vector<uint8_t> sig;
- sig.resize(sig_len);
- if (!EVP_DigestSignFinal(md_ctx, sig.data(), &sig_len)) {
- return false;
- }
- sig.resize(sig_len);
-
- // Ensure that the signature round-trips.
- ScopedEVP_MD_CTX md_ctx_verify;
- if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx_verify.get(), algor.get(),
- pkey) ||
- !EVP_DigestVerifyUpdate(md_ctx_verify.get(), kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(md_ctx_verify.get(), sig.data(), sig_len)) {
- return false;
- }
-
- return true;
-}
-
-static bool TestEVP_DigestSignAlgorithm(void) {
+static bool TestVerifyRecover() {
ScopedEVP_PKEY pkey = LoadExampleRSAKey();
-
- // Test a simple AlgorithmIdentifier.
- ScopedEVP_MD_CTX md_ctx;
- if (!pkey ||
- !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
- !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
- fprintf(stderr, "RSA with SHA-256 failed\n");
+ if (!pkey) {
return false;
}
- // Test RSA-PSS with custom parameters.
- md_ctx.Reset();
- EVP_PKEY_CTX *pkey_ctx;
- if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
- pkey.get()) ||
- !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
- !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
- fprintf(stderr, "RSA-PSS failed\n");
+ ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
+ if (!rsa) {
return false;
}
- return true;
-}
+ const uint8_t kDummyHash[32] = {0};
+ uint8_t sig[2048/8];
+ unsigned sig_len = sizeof(sig);
-static bool ParseCertificate(CBS *out_tbs_cert,
- ScopedEVP_PKEY *out_pubkey,
- ScopedX509_ALGOR *out_algor,
- CBS *out_signature,
- const CBS *in_) {
- CBS in = *in_;
- CBS cert_body, tbs_cert, algorithm, signature;
- if (!CBS_get_asn1(&in, &cert_body, CBS_ASN1_SEQUENCE) ||
- CBS_len(&in) != 0 ||
- !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
- !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
- CBS_len(&cert_body) != 0) {
+ if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len,
+ rsa.get())) {
+ fprintf(stderr, "RSA_sign failed.\n");
+ ERR_print_errors_fp(stderr);
return false;
}
- CBS tbs_cert_copy = tbs_cert;
- CBS tbs_cert_body, discard, spki;
- if (!CBS_get_asn1(&tbs_cert_copy, &tbs_cert_body, CBS_ASN1_SEQUENCE) ||
- CBS_len(&tbs_cert_copy) != 0 ||
- !CBS_get_optional_asn1(
- &tbs_cert_body, &discard, NULL,
- CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* serialNumber */,
- CBS_ASN1_INTEGER) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* signature */,
- CBS_ASN1_SEQUENCE) ||
- !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* issuer */,
- NULL, NULL) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* validity */,
- CBS_ASN1_SEQUENCE) ||
- !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* subject */,
- NULL, NULL) ||
- !CBS_get_asn1_element(&tbs_cert_body, &spki, CBS_ASN1_SEQUENCE)) {
+ size_t out_len;
+ ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
+ if (!EVP_PKEY_verify_recover_init(ctx.get()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) ||
+ !EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) {
+ fprintf(stderr, "verify_recover failed will nullptr buffer.\n");
+ ERR_print_errors_fp(stderr);
return false;
}
- const uint8_t *derp = CBS_data(&spki);
- ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &derp, CBS_len(&spki)));
- if (!pubkey || derp != CBS_data(&spki) + CBS_len(&spki)) {
- return false;
- }
+ std::vector<uint8_t> recovered;
+ recovered.resize(out_len);
- derp = CBS_data(&algorithm);
- ScopedX509_ALGOR algor(d2i_X509_ALGOR(NULL, &derp, CBS_len(&algorithm)));
- if (!algor || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
+ if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
+ sig_len)) {
+ fprintf(stderr, "verify_recover failed.\n");
+ ERR_print_errors_fp(stderr);
return false;
}
- // Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
- // leading phase byte is just a zero.
- uint8_t padding;
- if (!CBS_get_u8(&signature, &padding) || padding != 0) {
+ if (out_len != sizeof(kDummyHash)) {
+ fprintf(stderr, "verify_recover length is %u, expected %u.\n",
+ static_cast<unsigned>(out_len),
+ static_cast<unsigned>(sizeof(kDummyHash)));
return false;
}
- *out_tbs_cert = tbs_cert;
- *out_pubkey = std::move(pubkey);
- *out_algor = std::move(algor);
- *out_signature = signature;
- return true;
-}
-
-static bool TestEVP_DigestVerifyInitFromAlgorithm(void) {
- CBS in, tbs_cert, signature;
- ScopedEVP_PKEY pkey;
- ScopedX509_ALGOR algor;
- CBS_init(&in, kExamplePSSCert, sizeof(kExamplePSSCert));
- if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
- fprintf(stderr, "Failed to parse certificate\n");
+ if (memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) {
+ fprintf(stderr, "verify_recover got wrong value.\n");
+ ERR_print_errors_fp(stderr);
return false;
}
- ScopedEVP_MD_CTX md_ctx;
- if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
- pkey.get()) ||
- !EVP_DigestVerifyUpdate(md_ctx.get(), CBS_data(&tbs_cert),
- CBS_len(&tbs_cert)) ||
- !EVP_DigestVerifyFinal(md_ctx.get(), CBS_data(&signature),
- CBS_len(&signature))) {
+ out_len = recovered.size();
+ if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) ||
+ !EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
+ sig_len)) {
+ fprintf(stderr, "verify_recover failed with NULL MD.\n");
+ ERR_print_errors_fp(stderr);
return false;
}
- return true;
-}
-static bool TestBadPSSParameters(void) {
- CBS in, tbs_cert, signature;
- ScopedEVP_PKEY pkey;
- ScopedX509_ALGOR algor;
- CBS_init(&in, kBadPSSCert, sizeof(kBadPSSCert));
- if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
- fprintf(stderr, "Failed to parse certificate\n");
+ /* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
+ * bytes. */
+ static const size_t kExpectedASN1Size = 51;
+ if (out_len != kExpectedASN1Size) {
+ fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n",
+ static_cast<unsigned>(out_len),
+ static_cast<unsigned>(kExpectedASN1Size));
return false;
}
- ScopedEVP_MD_CTX md_ctx;
- if (EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
- pkey.get())) {
- fprintf(stderr, "Unexpectedly processed bad signature parameters\n");
- return false;
- }
- ERR_clear_error();
return true;
}
@@ -714,6 +535,20 @@ static bool Testd2i_AutoPrivateKey() {
return false;
}
+ if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
+ EVP_PKEY_EC)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n");
+ return false;
+ }
+
+ if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
+ sizeof(kExampleECKeySpecifiedCurvePKCS8),
+ EVP_PKEY_EC)) {
+ fprintf(stderr,
+ "d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n");
+ return false;
+ }
+
if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
EVP_PKEY_DSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
@@ -751,6 +586,25 @@ static bool TestEVP_PKCS82PKEY(void) {
return true;
}
+// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key.
+static bool TestEVPMarshalEmptyPublicKey(void) {
+ ScopedEVP_PKEY empty(EVP_PKEY_new());
+ if (!empty) {
+ return false;
+ }
+ ScopedCBB cbb;
+ if (EVP_marshal_public_key(cbb.get(), empty.get())) {
+ fprintf(stderr, "Marshalled empty public key.\n");
+ return false;
+ }
+ if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) {
+ fprintf(stderr, "Marshalling an empty public key gave wrong error.\n");
+ return false;
+ }
+ ERR_clear_error();
+ return true;
+}
+
// Testd2i_PrivateKey tests |d2i_PrivateKey|.
static bool Testd2i_PrivateKey(void) {
const uint8_t *derp = kExampleRSAKeyDER;
@@ -805,12 +659,20 @@ static bool Testd2i_PrivateKey(void) {
}
ERR_clear_error();
+ derp = kExampleRSAKeyPKCS8;
+ pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
+ sizeof(kExampleRSAKeyPKCS8)));
+ if (pkey) {
+ fprintf(stderr, "Imported RSA key as EC key.\n");
+ return false;
+ }
+ ERR_clear_error();
+
return true;
}
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!TestEVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
@@ -824,20 +686,8 @@ int main(void) {
return 1;
}
- if (!TestEVP_DigestSignAlgorithm()) {
- fprintf(stderr, "EVP_DigestSignInit failed\n");
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- if (!TestEVP_DigestVerifyInitFromAlgorithm()) {
- fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- if (!TestBadPSSParameters()) {
- fprintf(stderr, "TestBadPSSParameters failed\n");
+ if (!TestVerifyRecover()) {
+ fprintf(stderr, "EVP_PKEY_verify_recover failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
@@ -854,6 +704,12 @@ int main(void) {
return 1;
}
+ if (!TestEVPMarshalEmptyPublicKey()) {
+ fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n");
+ ERR_print_errors_fp(stderr);
+ return 1;
+ }
+
if (!Testd2i_PrivateKey()) {
fprintf(stderr, "Testd2i_PrivateKey failed\n");
ERR_print_errors_fp(stderr);
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
index 7fedc152..a7dac2bf 100644
--- a/src/crypto/evp/evp_test.cc
+++ b/src/crypto/evp/evp_test.cc
@@ -63,18 +63,18 @@
#include <map>
#include <string>
+#include <utility>
#include <vector>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
-#include <openssl/bio.h>
+#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#include <openssl/pem.h>
#include "../test/file_test.h"
#include "../test/scoped_types.h"
@@ -103,34 +103,86 @@ static const EVP_MD *GetDigest(FileTest *t, const std::string &name) {
return nullptr;
}
-using KeyMap = std::map<std::string, EVP_PKEY*>;
+static int GetKeyType(FileTest *t, const std::string &name) {
+ if (name == "RSA") {
+ return EVP_PKEY_RSA;
+ }
+ if (name == "EC") {
+ return EVP_PKEY_EC;
+ }
+ if (name == "DSA") {
+ return EVP_PKEY_DSA;
+ }
+ t->PrintLine("Unknown key type: '%s'", name.c_str());
+ return EVP_PKEY_NONE;
+}
-// ImportPrivateKey evaluates a PrivateKey test in |t| and writes the resulting
-// private key to |key_map|.
-static bool ImportPrivateKey(FileTest *t, KeyMap *key_map) {
- const std::string &key_name = t->GetParameter();
- if (key_map->count(key_name) > 0) {
- t->PrintLine("Duplicate key '%s'.", key_name.c_str());
+using KeyMap = std::map<std::string, ScopedEVP_PKEY>;
+
+static bool ImportKey(FileTest *t, KeyMap *key_map,
+ EVP_PKEY *(*parse_func)(CBS *cbs),
+ int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) {
+ std::vector<uint8_t> input;
+ if (!t->GetBytes(&input, "Input")) {
return false;
}
- const std::string &block = t->GetBlock();
- ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(block.data()), block.size()));
- if (!bio) {
+
+ CBS cbs;
+ CBS_init(&cbs, input.data(), input.size());
+ ScopedEVP_PKEY pkey(parse_func(&cbs));
+ if (!pkey) {
return false;
}
- ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, 0, nullptr));
- if (!pkey) {
- t->PrintLine("Error reading private key.");
+
+ std::string key_type;
+ if (!t->GetAttribute(&key_type, "Type")) {
+ return false;
+ }
+ if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) {
+ t->PrintLine("Bad key type.");
+ return false;
+ }
+
+ // The key must re-encode correctly.
+ ScopedCBB cbb;
+ uint8_t *der;
+ size_t der_len;
+ if (!CBB_init(cbb.get(), 0) ||
+ !marshal_func(cbb.get(), pkey.get()) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
+ return false;
+ }
+ ScopedOpenSSLBytes free_der(der);
+
+ std::vector<uint8_t> output = input;
+ if (t->HasAttribute("Output") &&
+ !t->GetBytes(&output, "Output")) {
+ return false;
+ }
+ if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) {
+ t->PrintLine("Re-encoding the key did not match.");
+ return false;
+ }
+
+ // Save the key for future tests.
+ const std::string &key_name = t->GetParameter();
+ if (key_map->count(key_name) > 0) {
+ t->PrintLine("Duplicate key '%s'.", key_name.c_str());
return false;
}
- (*key_map)[key_name] = pkey.release();
+ (*key_map)[key_name] = std::move(pkey);
return true;
}
static bool TestEVP(FileTest *t, void *arg) {
KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
if (t->GetType() == "PrivateKey") {
- return ImportPrivateKey(t, key_map);
+ return ImportKey(t, key_map, EVP_parse_private_key,
+ EVP_marshal_private_key);
+ }
+
+ if (t->GetType() == "PublicKey") {
+ return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
}
int (*key_op_init)(EVP_PKEY_CTX *ctx);
@@ -156,7 +208,7 @@ static bool TestEVP(FileTest *t, void *arg) {
t->PrintLine("Could not find key '%s'.", key_name.c_str());
return false;
}
- EVP_PKEY *key = (*key_map)[key_name];
+ EVP_PKEY *key = (*key_map)[key_name].get();
std::vector<uint8_t> input, output;
if (!t->GetBytes(&input, "Input") ||
@@ -212,11 +264,5 @@ int main(int argc, char **argv) {
}
KeyMap map;
- int ret = FileTestMain(TestEVP, &map, argv[1]);
- // TODO(davidben): When we can rely on a move-aware std::map, make KeyMap a
- // map of ScopedEVP_PKEY instead.
- for (const auto &pair : map) {
- EVP_PKEY_free(pair.second);
- }
- return ret;
+ return FileTestMain(TestEVP, &map, argv[1]);
}
diff --git a/src/crypto/evp/evp_tests.txt b/src/crypto/evp/evp_tests.txt
index 97ddaa0e..7c316d81 100644
--- a/src/crypto/evp/evp_tests.txt
+++ b/src/crypto/evp/evp_tests.txt
@@ -1,47 +1,79 @@
# Public key algorithm tests
-# Private keys used for PKEY operations.
+# Keys used for PKEY operations.
# RSA 2048 bit key.
-
PrivateKey = RSA-2048
------BEGIN PRIVATE KEY-----
-MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNAIHqeyrh6gbV
-n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW
-B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP
-6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr
-LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7
-yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt
-A95H4cRPAgMBAAECggEAYCl6x5kbFnoG1rJHWLjL4gi+ubLZ7Jc4vYD5Ci41AF3X
-ziktnim6iFvTFv7x8gkTvArJDWsICLJBTYIQREHYYkozzgIzyPeApIs3Wv8C12cS
-IopwJITbP56+zM+77hcJ26GCgA2Unp5CFuC/81WDiPi9kNo3Oh2CdD7D+90UJ/0W
-glplejFpEuhpU2URfKL4RckJQF/KxV+JX8FdIDhsJu54yemQdQKaF4psHkzwwgDo
-qc+yfp0Vb4bmwq3CKxqEoc1cpbJ5CHXXlAfISzUjlcuBzD/tW7BDtp7eDAcgRVAC
-XO6MX0QBcLYSC7SOD3R7zY9SIRCFDfBDxCjf0YcFMQKBgQD2+WG0fLwDXTrt68fe
-hQqVa2Xs25z2B2QGPxWqSFU8WNly/mZ1BW413f3De/O58vYi7icTNyVoScm+8hdv
-6PfD+LuRujdN1TuvPeyBTSvewQwf3IjN0Wh28mse36PwlBl+301C/x+ylxEDuJjK
-hZxCcocIaoQqtBC7ac8tNa9r4wKBgQDUfnJKf/QQSLJwwlJKQQGHi3MVm7c9PbwY
-eyIOY1s1NPluJDoYTZP4YLa/u2txwe2aHh9FhYMCPDAelqaSwaCLU9DsnKkQEA2A
-RR47fcagG6xK7O+N95iEa8I1oIy7os9MBoBMwRIZ6VYIxxTj8UMNSR+tu6MqV1Gg
-T5d0WDTJpQKBgCHyRSu5uV39AoyRS/eZ8cp36JqV1Q08FtOE+EVfi9evnrPfo9WR
-2YQt7yNfdjCo5IwIj/ZkLhAXlFNakz4el2+oUJ/HKLLaDEoaCNf883q6rh/zABrK
-HcG7sF2d/7qhoJ9/se7zgjfZ68zHIrkzhDbd5xGREnmMJoCcGo3sQyBhAoGAH3UQ
-qmLC2N5KPFMoJ4H0HgLQ6LQCrnhDLkScSBEBYaEUA/AtAYgKjcyTgVLXlyGkcRpg
-esRHHr+WSBD5W+R6ReYEmeKfTJdzyDdzQE9gZjdyjC0DUbsDwybIu3OnIef6VEDq
-IXK7oUZfzDDcsNn4mTDoFaoff5cpqFfgDgM43VkCgYBNHw11b+d+AQmaZS9QqIt7
-aF3FvwCYHV0jdv0Mb+Kc1bY4c0R5MFpzrTwVmdOerjuuA1+9b+0Hwo3nBZM4eaBu
-SOamA2hu2OJWCl9q8fLCT69KqWDjghhvFe7c6aJJGucwaA3Uz3eLcPqoaCarMiNH
-fMkTd7GabVourqIZdgvu1Q==
------END PRIVATE KEY-----
+Type = RSA
+Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5
-# EC P-256 key
+# The public half of the same key encoded as a SubjectPublicKeyInfo.
+PublicKey = RSA-2048-SPKI
+Type = RSA
+Input = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+
+# The same key but with missing parameters rather than a NULL.
+PublicKey = RSA-2048-SPKI-Invalid
+Input = 30820120300b06092a864886f70d0101010382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+Error = DECODE_ERROR
+
+# The same key but with an incorrectly-encoded length prefix.
+PublicKey = RSA-2048-SPKI-Invalid2
+Input = 3083000122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+Error = DECODE_ERROR
+# EC P-256 key
PrivateKey = P-256
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiocvtiiTxNH/xbnw
-+RdYBp+DUuCPoFpJ+NuSbLVyhyWhRANCAAQsFQ9CnOcPIWwlLPXgYs4fY5zV0WXH
-+JQkBywnGX14szuSDpXNtmTpkNzwz+oNlOKo5q+dDlgFbmUxBJJbn+bJ
------END PRIVATE KEY-----
+Type = EC
+Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key as above with the optional public key omitted.
+PrivateKey = P-256-MissingPublic
+Type = EC
+Input = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
+
+# The same key as above with redundant parameters.
+PrivateKey = P-256-ExtraParameters
+Type = EC
+Input = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+# The key re-encodes with the parameters removed.
+Output = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key, but with the redundant parameters in the ECPrivateKey mismatched.
+PrivateKey = P-256-BadInnerParameters
+Input = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = GROUP_MISMATCH
+
+# The public half of the same key encoded as a PublicKey.
+PublicKey = P-256-SPKI
+Type = EC
+Input = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same as above, but with the curve explicitly spelled out.
+PublicKey = P-256-SPKI
+Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = DECODE_ERROR
+
+# The same as above, but with trailing data after the curve name.
+PublicKey = P-256-SPKI
+Input = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = DECODE_ERROR
+
+# A DSA private key.
+PrivateKey = DSA-1024
+Type = DSA
+Input = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e
+
+# A DSA public key.
+PublicKey = DSA-1024-SPKI
+Type = DSA
+Input = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
+
+# The same key as above, but without the parameters.
+PublicKey = DSA-1024-SPKI-No-Params
+Type = DSA
+Input = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
+
# RSA tests
@@ -55,6 +87,11 @@ Digest = SHA1
Input = "0123456789ABCDEF1234"
Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+Verify = RSA-2048-SPKI
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+
# Digest too long
Sign = RSA-2048
Digest = SHA1
@@ -125,6 +162,11 @@ Digest = SHA1
Input = "0123456789ABCDEF1234"
Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+Verify = P-256-SPKI
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+
# Digest too long
Verify = P-256
Digest = SHA1
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
index aa52d535..0783143d 100644
--- a/src/crypto/evp/internal.h
+++ b/src/crypto/evp/internal.h
@@ -59,47 +59,42 @@
#include <openssl/base.h>
+#include <openssl/rsa.h>
+
#if defined(__cplusplus)
extern "C" {
#endif
-/* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
-
-/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
- * EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
- * AlgorithmIdentifier. */
-#define ASN1_PKEY_SIGPARAM_NULL 0x1
-
-/* evp_digest_sign_algorithm_result_t is the return value of the
- * digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
-typedef enum {
- /* EVP_DIGEST_SIGN_ALGORITHM_ERROR signals an error. */
- EVP_DIGEST_SIGN_ALGORITHM_ERROR = 0,
- /* EVP_DIGEST_SIGN_ALGORITHM_SUCCESS signals that the parameters were
- * serialized in the AlgorithmIdentifier. */
- EVP_DIGEST_SIGN_ALGORITHM_SUCCESS = 1,
- /* EVP_DIGEST_SIGN_ALGORITHM_DEFAULT signals that the parameters are
- * serialized using the default behavior. */
- EVP_DIGEST_SIGN_ALGORITHM_DEFAULT = 2,
-} evp_digest_sign_algorithm_result_t;
-
struct evp_pkey_asn1_method_st {
int pkey_id;
- int pkey_base_id;
- unsigned long pkey_flags;
+ uint8_t oid[9];
+ uint8_t oid_len;
+
+ /* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo
+ * and writes the result into |out|. It returns one on success and zero on
+ * error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER
+ * type field, and |key| is the contents of the subjectPublicKey with the
+ * leading padding byte checked and removed. Although X.509 uses BIT STRINGs
+ * to represent SubjectPublicKeyInfo, every key type defined encodes the key
+ * as a byte string with the same conversion to BIT STRING. */
+ int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key);
+
+ /* pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result
+ * to |out|. It returns one on success and zero on error. */
+ int (*pub_encode)(CBB *out, const EVP_PKEY *key);
- const char *pem_str;
-
- int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub);
- int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk);
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
- int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
- int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
- int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
- int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx);
+ /* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
+ * result into |out|. It returns one on success and zero on error. |params| is
+ * the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key|
+ * is the contents of the OCTET STRING privateKey field. */
+ int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key);
+
+ /* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to
+ * |out|. It returns one on success and zero on error. */
+ int (*priv_encode)(CBB *out, const EVP_PKEY *key);
/* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
* custom implementations which do not expose key material and parameters.*/
@@ -114,40 +109,15 @@ struct evp_pkey_asn1_method_st {
int (*pkey_size)(const EVP_PKEY *pk);
int (*pkey_bits)(const EVP_PKEY *pk);
- int (*param_decode)(EVP_PKEY *pkey, const uint8_t **pder, int derlen);
- int (*param_encode)(const EVP_PKEY *pkey, uint8_t **pder);
int (*param_missing)(const EVP_PKEY *pk);
int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
- int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx);
- int (*sig_print)(BIO *out, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
- int indent, ASN1_PCTX *pctx);
-
void (*pkey_free)(EVP_PKEY *pkey);
-
- /* Legacy functions for old PEM */
-
- int (*old_priv_decode)(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen);
- int (*old_priv_encode)(const EVP_PKEY *pkey, uint8_t **pder);
-
- /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
- int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
- X509_ALGOR *algor,
- EVP_PKEY *pkey);
- evp_digest_sign_algorithm_result_t (*digest_sign_algorithm)(
- EVP_MD_CTX *ctx,
- X509_ALGOR *algor);
-
} /* EVP_PKEY_ASN1_METHOD */;
-typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
-
#define EVP_PKEY_OP_UNDEFINED 0
-#define EVP_PKEY_OP_PARAMGEN (1 << 1)
#define EVP_PKEY_OP_KEYGEN (1 << 2)
#define EVP_PKEY_OP_SIGN (1 << 3)
#define EVP_PKEY_OP_VERIFY (1 << 4)
@@ -156,7 +126,7 @@ typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
#define EVP_PKEY_OP_DECRYPT (1 << 7)
#define EVP_PKEY_OP_DERIVE (1 << 8)
-#define EVP_PKEY_OP_TYPE_SIG \
+#define EVP_PKEY_OP_TYPE_SIG \
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER)
#define EVP_PKEY_OP_TYPE_CRYPT (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
@@ -164,7 +134,7 @@ typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
#define EVP_PKEY_OP_TYPE_NOGEN \
(EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
-#define EVP_PKEY_OP_TYPE_GEN (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
+#define EVP_PKEY_OP_TYPE_GEN EVP_PKEY_OP_KEYGEN
/* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
* arguments can be -1 to specify that any type and operation are acceptable,
@@ -208,8 +178,6 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
-#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
-
struct evp_pkey_ctx_st {
/* Method associated with this operation */
const EVP_PKEY_METHOD *pmeth;
@@ -223,41 +191,32 @@ struct evp_pkey_ctx_st {
int operation;
/* Algorithm specific data */
void *data;
- /* Application specific data */
- void *app_data;
} /* EVP_PKEY_CTX */;
struct evp_pkey_method_st {
int pkey_id;
- int flags;
int (*init)(EVP_PKEY_CTX *ctx);
int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
void (*cleanup)(EVP_PKEY_CTX *ctx);
- int (*paramgen_init)(EVP_PKEY_CTX *ctx);
- int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
-
- int (*keygen_init)(EVP_PKEY_CTX *ctx);
int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
- int (*sign_init)(EVP_PKEY_CTX *ctx);
int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
const uint8_t *tbs, size_t tbslen);
- int (*verify_init)(EVP_PKEY_CTX *ctx);
int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
const uint8_t *tbs, size_t tbslen);
- int (*encrypt_init)(EVP_PKEY_CTX *ctx);
+ int (*verify_recover)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
+ const uint8_t *sig, size_t sig_len);
+
int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen);
- int (*decrypt_init)(EVP_PKEY_CTX *ctx);
int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen);
- int (*derive_init)(EVP_PKEY_CTX *ctx);
int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen);
int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
index c92068f8..1f022f1a 100644
--- a/src/crypto/evp/p_dsa_asn1.c
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -55,290 +55,139 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
#include <openssl/digest.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
-#include "../dsa/internal.h"
#include "internal.h"
-static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
- const uint8_t *p, *pm;
- int pklen, pmlen;
- int ptype;
- void *pval;
- ASN1_STRING *pstr;
- X509_ALGOR *palg;
- ASN1_INTEGER *public_key = NULL;
+static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See RFC 3279, section 2.3.2. */
- DSA *dsa = NULL;
-
- if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
- return 0;
- }
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- if (ptype == V_ASN1_SEQUENCE) {
- pstr = pval;
- pm = pstr->data;
- pmlen = pstr->length;
-
- dsa = d2i_DSAparams(NULL, &pm, pmlen);
- if (dsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto err;
- }
- } else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
+ /* Parameters may or may not be present. */
+ DSA *dsa;
+ if (CBS_len(params) == 0) {
dsa = DSA_new();
if (dsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
} else {
- OPENSSL_PUT_ERROR(EVP, EVP_R_PARAMETER_ENCODING_ERROR);
- goto err;
+ dsa = DSA_parse_parameters(params);
+ if (dsa == NULL || CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ goto err;
+ }
}
- public_key = d2i_ASN1_INTEGER(NULL, &p, pklen);
- if (public_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ dsa->pub_key = BN_new();
+ if (dsa->pub_key == NULL) {
goto err;
}
- dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL);
- if (dsa->pub_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_BN_DECODE_ERROR);
+ if (!BN_parse_asn1_unsigned(key, dsa->pub_key) ||
+ CBS_len(key) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
- ASN1_INTEGER_free(public_key);
- EVP_PKEY_assign_DSA(pkey, dsa);
+ EVP_PKEY_assign_DSA(out, dsa);
return 1;
err:
- ASN1_INTEGER_free(public_key);
DSA_free(dsa);
return 0;
}
-static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
- DSA *dsa;
- ASN1_STRING *pval = NULL;
- uint8_t *penc = NULL;
- int penclen;
-
- dsa = pkey->pkey.dsa;
- dsa->write_params = 0;
-
- int ptype;
- if (dsa->p && dsa->q && dsa->g) {
- pval = ASN1_STRING_new();
- if (!pval) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- pval->length = i2d_DSAparams(dsa, &pval->data);
- if (pval->length <= 0) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ptype = V_ASN1_SEQUENCE;
- } else {
- ptype = V_ASN1_UNDEF;
- }
-
- penclen = i2d_DSAPublicKey(dsa, &penc);
- if (penclen <= 0) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), ptype, pval,
- penc, penclen)) {
- return 1;
- }
-
-err:
- OPENSSL_free(penc);
- ASN1_STRING_free(pval);
-
- return 0;
-}
-
-static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p, *pm;
- int pklen, pmlen;
- int ptype;
- void *pval;
- ASN1_STRING *pstr;
- X509_ALGOR *palg;
- ASN1_INTEGER *privkey = NULL;
- BN_CTX *ctx = NULL;
-
- /* In PKCS#8 DSA: you just get a private key integer and parameters in the
- * AlgorithmIdentifier the pubkey must be recalculated. */
-
- STACK_OF(ASN1_TYPE) *ndsa = NULL;
- DSA *dsa = NULL;
-
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
+ const DSA *dsa = key->pkey.dsa;
+ const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
+
+ /* See RFC 5480, section 2. */
+ CBB spki, algorithm, oid, key_bitstring;
+ if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+ (has_params &&
+ !DSA_marshal_parameters(&algorithm, dsa)) ||
+ !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+ !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+ !BN_marshal_asn1(&key_bitstring, dsa->pub_key) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- /* Check for broken DSA PKCS#8, UGH! */
- if (*p == (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
- ASN1_TYPE *t1, *t2;
- ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen);
- if (ndsa == NULL) {
- goto decerr;
- }
- if (sk_ASN1_TYPE_num(ndsa) != 2) {
- goto decerr;
- }
- /* Handle Two broken types:
- * SEQUENCE {parameters, priv_key}
- * SEQUENCE {pub_key, priv_key}. */
-
- t1 = sk_ASN1_TYPE_value(ndsa, 0);
- t2 = sk_ASN1_TYPE_value(ndsa, 1);
- if (t1->type == V_ASN1_SEQUENCE) {
- p8->broken = PKCS8_EMBEDDED_PARAM;
- pval = t1->value.ptr;
- } else if (ptype == V_ASN1_SEQUENCE) {
- p8->broken = PKCS8_NS_DB;
- } else {
- goto decerr;
- }
+ return 1;
+}
- if (t2->type != V_ASN1_INTEGER) {
- goto decerr;
- }
+static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See PKCS#11, v2.40, section 2.5. */
- privkey = t2->value.integer;
- } else {
- const uint8_t *q = p;
- privkey = d2i_ASN1_INTEGER(NULL, &p, pklen);
- if (privkey == NULL) {
- goto decerr;
- }
- if (privkey->type == V_ASN1_NEG_INTEGER) {
- p8->broken = PKCS8_NEG_PRIVKEY;
- ASN1_INTEGER_free(privkey);
- privkey = d2i_ASN1_UINTEGER(NULL, &q, pklen);
- if (privkey == NULL) {
- goto decerr;
- }
- }
- if (ptype != V_ASN1_SEQUENCE) {
- goto decerr;
- }
+ /* Decode parameters. */
+ BN_CTX *ctx = NULL;
+ DSA *dsa = DSA_parse_parameters(params);
+ if (dsa == NULL || CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ goto err;
}
- pstr = pval;
- pm = pstr->data;
- pmlen = pstr->length;
- dsa = d2i_DSAparams(NULL, &pm, pmlen);
- if (dsa == NULL) {
- goto decerr;
- }
- /* We have parameters. Now set private key */
- dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL);
- if (dsa->priv_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto dsaerr;
- }
- /* Calculate public key. */
+ dsa->priv_key = BN_new();
dsa->pub_key = BN_new();
- if (dsa->pub_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
+ if (dsa->priv_key == NULL || dsa->pub_key == NULL) {
+ goto err;
}
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
+
+ /* Decode the key. */
+ if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
+ CBS_len(key) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ goto err;
}
- if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto dsaerr;
+ /* Calculate the public key. */
+ ctx = BN_CTX_new();
+ if (ctx == NULL ||
+ !BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
+ goto err;
}
- EVP_PKEY_assign_DSA(pkey, dsa);
BN_CTX_free(ctx);
- sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
- ASN1_INTEGER_free(privkey);
-
+ EVP_PKEY_assign_DSA(out, dsa);
return 1;
-decerr:
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-
-dsaerr:
+err:
BN_CTX_free(ctx);
- ASN1_INTEGER_free(privkey);
- sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
DSA_free(dsa);
return 0;
}
-static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- ASN1_STRING *params = NULL;
- ASN1_INTEGER *prkey = NULL;
- uint8_t *dp = NULL;
- int dplen;
-
- if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
+static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+ const DSA *dsa = key->pkey.dsa;
+ if (dsa == NULL || dsa->priv_key == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
- goto err;
- }
-
- params = ASN1_STRING_new();
- if (!params) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
- if (params->length <= 0) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- params->type = V_ASN1_SEQUENCE;
-
- /* Get private key into integer. */
- prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
-
- if (!prkey) {
- OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
- goto err;
+ return 0;
}
- dplen = i2d_ASN1_INTEGER(prkey, &dp);
-
- ASN1_INTEGER_free(prkey);
- prkey = NULL;
-
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_dsa), 0,
- V_ASN1_SEQUENCE, params, dp, dplen)) {
- goto err;
+ /* See PKCS#11, v2.40, section 2.5. */
+ CBB pkcs8, algorithm, oid, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+ !DSA_marshal_parameters(&algorithm, dsa) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !BN_marshal_asn1(&private_key, dsa->priv_key) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
+ return 0;
}
return 1;
-
-err:
- OPENSSL_free(dp);
- ASN1_STRING_free(params);
- ASN1_INTEGER_free(prkey);
- return 0;
}
static int int_dsa_size(const EVP_PKEY *pkey) {
@@ -393,177 +242,17 @@ static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
- size_t i;
-
- if (!b) {
- return;
- }
- i = BN_num_bytes(b);
- if (*pbuflen < i) {
- *pbuflen = i;
- }
-}
-
-static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
- uint8_t *m = NULL;
- int ret = 0;
- size_t buf_len = 0;
- const char *ktype = NULL;
-
- const BIGNUM *priv_key, *pub_key;
-
- priv_key = NULL;
- if (ptype == 2) {
- priv_key = x->priv_key;
- }
-
- pub_key = NULL;
- if (ptype > 0) {
- pub_key = x->pub_key;
- }
-
- ktype = "DSA-Parameters";
- if (ptype == 2) {
- ktype = "Private-Key";
- } else if (ptype == 1) {
- ktype = "Public-Key";
- }
-
- update_buflen(x->p, &buf_len);
- update_buflen(x->q, &buf_len);
- update_buflen(x->g, &buf_len);
- update_buflen(priv_key, &buf_len);
- update_buflen(pub_key, &buf_len);
-
- m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (priv_key) {
- if (!BIO_indent(bp, off, 128) ||
- BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
- goto err;
- }
- }
-
- if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
- !ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
- !ASN1_bn_print(bp, "P: ", x->p, m, off) ||
- !ASN1_bn_print(bp, "Q: ", x->q, m, off) ||
- !ASN1_bn_print(bp, "G: ", x->g, m, off)) {
- goto err;
- }
- ret = 1;
-
-err:
- OPENSSL_free(m);
- return ret;
-}
-
-static int dsa_param_decode(EVP_PKEY *pkey, const uint8_t **pder, int derlen) {
- DSA *dsa;
- dsa = d2i_DSAparams(NULL, pder, derlen);
- if (dsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_DSA_LIB);
- return 0;
- }
- EVP_PKEY_assign_DSA(pkey, dsa);
- return 1;
-}
-
-static int dsa_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
- return i2d_DSAparams(pkey->pkey.dsa, pder);
-}
-
-static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
-}
-
-static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
-}
-
-static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
-}
-
-static int old_dsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- DSA *dsa;
- dsa = d2i_DSAPrivateKey(NULL, pder, derlen);
- if (dsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_DSA_LIB);
- return 0;
- }
- EVP_PKEY_assign_DSA(pkey, dsa);
- return 1;
-}
-
-static int old_dsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
- return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
-}
-
-static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
- const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
- DSA_SIG *dsa_sig;
- const uint8_t *p;
-
- if (!sig) {
- return BIO_puts(bp, "\n") > 0;
- }
-
- p = sig->data;
- dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
- if (dsa_sig == NULL) {
- return X509_signature_dump(bp, sig, indent);
- }
-
- int rv = 0;
- size_t buf_len = 0;
- uint8_t *m = NULL;
-
- update_buflen(dsa_sig->r, &buf_len);
- update_buflen(dsa_sig->s, &buf_len);
- m = OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (BIO_write(bp, "\n", 1) != 1 ||
- !ASN1_bn_print(bp, "r: ", dsa_sig->r, m, indent) ||
- !ASN1_bn_print(bp, "s: ", dsa_sig->s, m, indent)) {
- goto err;
- }
- rv = 1;
-
-err:
- OPENSSL_free(m);
- DSA_SIG_free(dsa_sig);
- return rv;
-}
-
const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
EVP_PKEY_DSA,
- EVP_PKEY_DSA,
- 0,
-
- "DSA",
+ /* 1.2.840.10040.4.1 */
+ {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
dsa_pub_decode,
dsa_pub_encode,
dsa_pub_cmp,
- dsa_pub_print,
dsa_priv_decode,
dsa_priv_encode,
- dsa_priv_print,
NULL /* pkey_opaque */,
NULL /* pkey_supports_digest */,
@@ -571,18 +260,9 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
int_dsa_size,
dsa_bits,
- dsa_param_decode,
- dsa_param_encode,
dsa_missing_parameters,
dsa_copy_parameters,
dsa_cmp_parameters,
- dsa_param_print,
- dsa_sig_print,
int_dsa_free,
- old_dsa_priv_decode,
- old_dsa_priv_encode,
-
- NULL /* digest_verify_init_from_algorithm */,
- NULL /* digest_sign_algorithm */,
};
diff --git a/src/crypto/evp/p_ec.c b/src/crypto/evp/p_ec.c
index 77f213db..f92c87cf 100644
--- a/src/crypto/evp/p_ec.c
+++ b/src/crypto/evp/p_ec.c
@@ -57,7 +57,6 @@
#include <string.h>
-#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/digest.h>
@@ -67,15 +66,13 @@
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
#include "../ec/internal.h"
typedef struct {
- /* Key and paramgen group */
- EC_GROUP *gen_group;
/* message digest */
const EVP_MD *md;
} EC_PKEY_CTX;
@@ -102,12 +99,6 @@ static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
sctx = src->data;
dctx = dst->data;
- if (sctx->gen_group) {
- dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
- if (!dctx->gen_group) {
- return 0;
- }
- }
dctx->md = sctx->md;
return 1;
@@ -119,7 +110,6 @@ static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
return;
}
- EC_GROUP_free(dctx->gen_group);
OPENSSL_free(dctx);
}
@@ -185,19 +175,8 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
EC_PKEY_CTX *dctx = ctx->data;
- EC_GROUP *group;
switch (type) {
- case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
- group = EC_GROUP_new_by_curve_name(p1);
- if (group == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CURVE);
- return 0;
- }
- EC_GROUP_free(dctx->gen_group);
- dctx->gen_group = group;
- return 1;
-
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
@@ -225,59 +204,33 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
}
}
-static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
- EC_KEY *ec = NULL;
- EC_PKEY_CTX *dctx = ctx->data;
- int ret = 0;
-
- if (dctx->gen_group == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
- return 0;
- }
- ec = EC_KEY_new();
- if (!ec) {
- return 0;
- }
- ret = EC_KEY_set_group(ec, dctx->gen_group);
- if (ret) {
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- } else {
- EC_KEY_free(ec);
- }
- return ret;
-}
-
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
- EC_KEY *ec = NULL;
- EC_PKEY_CTX *dctx = ctx->data;
- if (ctx->pkey == NULL && dctx->gen_group == NULL) {
+ if (ctx->pkey == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
return 0;
}
- ec = EC_KEY_new();
- if (!ec) {
+ EC_KEY *ec = EC_KEY_new();
+ if (ec == NULL ||
+ !EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) ||
+ !EC_KEY_generate_key(ec)) {
+ EC_KEY_free(ec);
return 0;
}
EVP_PKEY_assign_EC_KEY(pkey, ec);
- if (ctx->pkey) {
- /* Note: if error return, pkey is freed by parent routine */
- if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) {
- return 0;
- }
- } else {
- if (!EC_KEY_set_group(ec, dctx->gen_group)) {
- return 0;
- }
- }
- return EC_KEY_generate_key(pkey->pkey.ec);
+ return 1;
}
const EVP_PKEY_METHOD ec_pkey_meth = {
- EVP_PKEY_EC, 0 /* flags */, pkey_ec_init,
- pkey_ec_copy, pkey_ec_cleanup, 0 /* paramgen_init */,
- pkey_ec_paramgen, 0 /* keygen_init */, pkey_ec_keygen,
- 0 /* sign_init */, pkey_ec_sign, 0 /* verify_init */,
- pkey_ec_verify, 0 /* encrypt_init */, 0 /* encrypt */,
- 0 /* decrypt_init */, 0 /* decrypt */, 0 /* derive_init */,
- pkey_ec_derive, pkey_ec_ctrl,
+ EVP_PKEY_EC,
+ pkey_ec_init,
+ pkey_ec_copy,
+ pkey_ec_cleanup,
+ pkey_ec_keygen,
+ pkey_ec_sign,
+ pkey_ec_verify,
+ 0 /* verify_recover */,
+ 0 /* encrypt */,
+ 0 /* decrypt */,
+ pkey_ec_derive,
+ pkey_ec_ctrl,
};
diff --git a/src/crypto/evp/p_ec_asn1.c b/src/crypto/evp/p_ec_asn1.c
index f40b9764..8d44dcdc 100644
--- a/src/crypto/evp/p_ec_asn1.c
+++ b/src/crypto/evp/p_ec_asn1.c
@@ -55,145 +55,73 @@
#include <openssl/evp.h>
-#include <openssl/asn1t.h>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
#include "internal.h"
-static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) {
- const EC_GROUP *group;
- int nid;
-
- if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
- return 0;
- }
-
- nid = EC_GROUP_get_curve_name(group);
- if (nid == NID_undef) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
+static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
+ const EC_KEY *ec_key = key->pkey.ec;
+ const EC_GROUP *group = EC_KEY_get0_group(ec_key);
+ const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
+
+ /* See RFC 5480, section 2. */
+ CBB spki, algorithm, oid, key_bitstring;
+ if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+ !EC_KEY_marshal_curve_name(&algorithm, group) ||
+ !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+ !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+ !EC_POINT_point2cbb(&key_bitstring, group, public_key,
+ POINT_CONVERSION_UNCOMPRESSED, NULL) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
- *ppval = (void*) OBJ_nid2obj(nid);
- *pptype = V_ASN1_OBJECT;
return 1;
}
-static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
- EC_KEY *ec_key = pkey->pkey.ec;
- void *pval = NULL;
- int ptype;
- uint8_t *penc = NULL, *p;
- int penclen;
-
- if (!eckey_param2type(&ptype, &pval, ec_key)) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- penclen = i2o_ECPublicKey(ec_key, NULL);
- if (penclen <= 0) {
- goto err;
- }
- penc = OPENSSL_malloc(penclen);
- if (!penc) {
- goto err;
- }
- p = penc;
- penclen = i2o_ECPublicKey(ec_key, &p);
- if (penclen <= 0) {
- goto err;
- }
- if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc,
- penclen)) {
- return 1;
- }
-
-err:
- if (ptype == V_ASN1_OBJECT) {
- ASN1_OBJECT_free(pval);
- } else {
- ASN1_STRING_free(pval);
- }
- if (penc) {
- OPENSSL_free(penc);
- }
- return 0;
-}
+static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See RFC 5480, section 2. */
-static EC_KEY *eckey_type2param(int ptype, void *pval) {
+ /* The parameters are a named curve. */
+ EC_POINT *point = NULL;
EC_KEY *eckey = NULL;
-
- if (ptype == V_ASN1_SEQUENCE) {
- ASN1_STRING *pstr = pval;
- const uint8_t *pm = pstr->data;
- int pmlen = pstr->length;
-
- eckey = d2i_ECParameters(NULL, &pm, pmlen);
- if (eckey == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto err;
- }
- } else if (ptype == V_ASN1_OBJECT) {
- ASN1_OBJECT *poid = pval;
-
- /* type == V_ASN1_OBJECT => the parameters are given
- * by an asn1 OID */
- eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid(poid));
- if (eckey == NULL) {
- goto err;
- }
- } else {
+ EC_GROUP *group = EC_KEY_parse_curve_name(params);
+ if (group == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
- return eckey;
-
-err:
- if (eckey) {
- EC_KEY_free(eckey);
- }
- return NULL;
-}
-
-static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
- const uint8_t *p = NULL;
- void *pval;
- int ptype, pklen;
- EC_KEY *eckey = NULL;
- X509_ALGOR *palg;
-
- if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
- return 0;
- }
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- eckey = eckey_type2param(ptype, pval);
- if (!eckey) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
+ eckey = EC_KEY_new();
+ if (eckey == NULL || !EC_KEY_set_group(eckey, group)) {
+ goto err;
}
- /* We have parameters now set public key */
- if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ point = EC_POINT_new(group);
+ if (point == NULL ||
+ !EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) ||
+ !EC_KEY_set_public_key(eckey, point)) {
goto err;
}
- EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ EC_GROUP_free(group);
+ EC_POINT_free(point);
+ EVP_PKEY_assign_EC_KEY(out, eckey);
return 1;
err:
- if (eckey) {
- EC_KEY_free(eckey);
- }
+ EC_GROUP_free(group);
+ EC_POINT_free(point);
+ EC_KEY_free(eckey);
return 0;
}
@@ -212,120 +140,48 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
}
}
-static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p = NULL;
- void *pval;
- int ptype, pklen;
- EC_KEY *eckey = NULL;
- X509_ALGOR *palg;
-
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See RFC 5915. */
+ EC_GROUP *group = EC_KEY_parse_parameters(params);
+ if (group == NULL || CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ EC_GROUP_free(group);
return 0;
}
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- eckey = eckey_type2param(ptype, pval);
- if (!eckey) {
- goto ecliberr;
- }
-
- /* We have parameters now set private key */
- if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+ EC_KEY *ec_key = EC_KEY_parse_private_key(key, group);
+ EC_GROUP_free(group);
+ if (ec_key == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- goto ecerr;
- }
-
- /* calculate public key (if necessary) */
- if (EC_KEY_get0_public_key(eckey) == NULL) {
- const BIGNUM *priv_key;
- const EC_GROUP *group;
- EC_POINT *pub_key;
- /* the public key was not included in the SEC1 private
- * key => calculate the public key */
- group = EC_KEY_get0_group(eckey);
- pub_key = EC_POINT_new(group);
- if (pub_key == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- goto ecliberr;
- }
- if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
- EC_POINT_free(pub_key);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- goto ecliberr;
- }
- priv_key = EC_KEY_get0_private_key(eckey);
- if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
- EC_POINT_free(pub_key);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- goto ecliberr;
- }
- if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
- EC_POINT_free(pub_key);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- goto ecliberr;
- }
- EC_POINT_free(pub_key);
+ EC_KEY_free(ec_key);
+ return 0;
}
- EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ EVP_PKEY_assign_EC_KEY(out, ec_key);
return 1;
-
-ecliberr:
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-ecerr:
- if (eckey) {
- EC_KEY_free(eckey);
- }
- return 0;
}
-static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- EC_KEY *ec_key;
- uint8_t *ep, *p;
- int eplen, ptype;
- void *pval;
- unsigned int tmp_flags, old_flags;
-
- ec_key = pkey->pkey.ec;
-
- if (!eckey_param2type(&ptype, &pval, ec_key)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- return 0;
- }
-
- /* set the private key */
-
- /* do not include the parameters in the SEC1 private key
- * see PKCS#11 12.11 */
- old_flags = EC_KEY_get_enc_flags(ec_key);
- tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
- EC_KEY_set_enc_flags(ec_key, tmp_flags);
- eplen = i2d_ECPrivateKey(ec_key, NULL);
- if (!eplen) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- ep = (uint8_t *)OPENSSL_malloc(eplen);
- if (!ep) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- p = ep;
- if (!i2d_ECPrivateKey(ec_key, &p)) {
- EC_KEY_set_enc_flags(ec_key, old_flags);
- OPENSSL_free(ep);
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- /* restore old encoding flags */
- EC_KEY_set_enc_flags(ec_key, old_flags);
-
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
- 0, ptype, pval, ep, eplen)) {
- OPENSSL_free(ep);
+static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
+ const EC_KEY *ec_key = key->pkey.ec;
+
+ /* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
+ * aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
+ * means. Both OpenSSL and NSS omit the redundant parameters, so we omit them
+ * as well. */
+ unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
+
+ /* See RFC 5915. */
+ CBB pkcs8, algorithm, oid, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+ !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
@@ -371,173 +227,21 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
-static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
- uint8_t *buffer = NULL;
- const char *ecstr;
- size_t buf_len = 0, i;
- int ret = 0, reason = ERR_R_BIO_LIB;
- BN_CTX *ctx = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- const BIGNUM *priv_key;
- uint8_t *pub_key_bytes = NULL;
- size_t pub_key_bytes_len = 0;
-
- if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
- reason = ERR_R_PASSED_NULL_PARAMETER;
- goto err;
- }
-
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
-
- if (ktype > 0) {
- public_key = EC_KEY_get0_public_key(x);
- if (public_key != NULL) {
- pub_key_bytes_len = EC_POINT_point2oct(
- group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
- if (pub_key_bytes_len == 0) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
- if (pub_key_bytes == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- pub_key_bytes_len =
- EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
- pub_key_bytes, pub_key_bytes_len, ctx);
- if (pub_key_bytes_len == 0) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- buf_len = pub_key_bytes_len;
- }
- }
-
- if (ktype == 2) {
- priv_key = EC_KEY_get0_private_key(x);
- if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
- buf_len = i;
- }
- } else {
- priv_key = NULL;
- }
-
- if (ktype > 0) {
- buf_len += 10;
- if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- }
- if (ktype == 2) {
- ecstr = "Private-Key";
- } else if (ktype == 1) {
- ecstr = "Public-Key";
- } else {
- ecstr = "ECDSA-Parameters";
- }
-
- if (!BIO_indent(bp, off, 128)) {
- goto err;
- }
- const BIGNUM *order = EC_GROUP_get0_order(group);
- if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
- goto err;
- }
-
- if ((priv_key != NULL) &&
- !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
- goto err;
- }
- if (pub_key_bytes != NULL) {
- BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
- }
- /* TODO(fork): implement */
- /*
- if (!ECPKParameters_print(bp, group, off))
- goto err; */
- ret = 1;
-
-err:
- if (!ret) {
- OPENSSL_PUT_ERROR(EVP, reason);
- }
- OPENSSL_free(pub_key_bytes);
- BN_CTX_free(ctx);
- OPENSSL_free(buffer);
- return ret;
-}
-
-static int eckey_param_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- EC_KEY *eckey;
- if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
- return 0;
- }
- EVP_PKEY_assign_EC_KEY(pkey, eckey);
- return 1;
-}
-
-static int eckey_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
- return i2d_ECParameters(pkey->pkey.ec, pder);
-}
-
-static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
-}
-
-static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
-}
-
-
-static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
-}
-
static int eckey_opaque(const EVP_PKEY *pkey) {
return EC_KEY_is_opaque(pkey->pkey.ec);
}
-static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- EC_KEY *ec;
- if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- return 0;
- }
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- return 1;
-}
-
-static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
- return i2d_ECPrivateKey(pkey->pkey.ec, pder);
-}
-
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
EVP_PKEY_EC,
- EVP_PKEY_EC,
- 0,
- "EC",
+ /* 1.2.840.10045.2.1 */
+ {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7,
eckey_pub_decode,
eckey_pub_encode,
eckey_pub_cmp,
- eckey_pub_print,
eckey_priv_decode,
eckey_priv_encode,
- eckey_priv_print,
eckey_opaque,
0 /* pkey_supports_digest */,
@@ -545,18 +249,9 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
int_ec_size,
ec_bits,
- eckey_param_decode,
- eckey_param_encode,
ec_missing_parameters,
ec_copy_parameters,
ec_cmp_parameters,
- eckey_param_print,
- 0,
int_ec_free,
- old_ec_priv_decode,
- old_ec_priv_encode,
-
- NULL /* digest_verify_init_from_algorithm */,
- NULL /* digest_sign_algorithm */,
};
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index 895d3513..a2106572 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -64,7 +64,7 @@
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rsa.h>
#include "../rsa/internal.h"
@@ -256,6 +256,81 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
return 1;
}
+static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out,
+ size_t *out_len, const uint8_t *sig,
+ size_t sig_len) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+ if (out == NULL) {
+ *out_len = key_len;
+ return 1;
+ }
+
+ if (*out_len < key_len) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!setup_tbuf(rctx, ctx)) {
+ return 0;
+ }
+
+ if (rctx->md == NULL) {
+ const int ret = RSA_public_decrypt(sig_len, sig, rctx->tbuf,
+ ctx->pkey->pkey.rsa, rctx->pad_mode);
+ if (ret < 0) {
+ return 0;
+ }
+ *out_len = ret;
+ memcpy(out, rctx->tbuf, *out_len);
+ return 1;
+ }
+
+ if (rctx->pad_mode != RSA_PKCS1_PADDING) {
+ return 0;
+ }
+
+ uint8_t *asn1_prefix;
+ size_t asn1_prefix_len;
+ int asn1_prefix_allocated;
+ if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len,
+ &asn1_prefix_allocated, EVP_MD_type(rctx->md), NULL,
+ 0)) {
+ return 0;
+ }
+
+ size_t rslen;
+ int ok = 1;
+ if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len,
+ RSA_PKCS1_PADDING) ||
+ rslen < asn1_prefix_len ||
+ CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len) != 0) {
+ ok = 0;
+ }
+
+ if (asn1_prefix_allocated) {
+ OPENSSL_free(asn1_prefix);
+ }
+
+ if (!ok) {
+ return 0;
+ }
+
+ const size_t result_len = rslen - asn1_prefix_len;
+ if (result_len != EVP_MD_size(rctx->md)) {
+ return 0;
+ }
+
+ if (out != NULL) {
+ memcpy(out, rctx->tbuf + asn1_prefix_len, result_len);
+ }
+ *out_len = result_len;
+
+ return 1;
+}
+
static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen) {
RSA_PKEY_CTX *rctx = ctx->data;
@@ -503,13 +578,18 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
}
const EVP_PKEY_METHOD rsa_pkey_meth = {
- EVP_PKEY_RSA, 0 /* flags */, pkey_rsa_init,
- pkey_rsa_copy, pkey_rsa_cleanup, 0 /* paramgen_init */,
- 0 /* paramgen */, 0 /* keygen_init */, pkey_rsa_keygen,
- 0 /* sign_init */, pkey_rsa_sign, 0 /* verify_init */,
- pkey_rsa_verify, 0 /* encrypt_init */, pkey_rsa_encrypt,
- 0 /* decrypt_init */, pkey_rsa_decrypt, 0 /* derive_init */,
- 0 /* derive */, pkey_rsa_ctrl,
+ EVP_PKEY_RSA,
+ pkey_rsa_init,
+ pkey_rsa_copy,
+ pkey_rsa_cleanup,
+ pkey_rsa_keygen,
+ pkey_rsa_sign,
+ pkey_rsa_verify,
+ pkey_rsa_verify_recover,
+ pkey_rsa_encrypt,
+ pkey_rsa_decrypt,
+ 0 /* derive */,
+ pkey_rsa_ctrl,
};
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) {
@@ -566,15 +646,14 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
}
-int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
+int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label,
size_t label_len) {
- int label_len_int = label_len;
- if (((size_t) label_len_int) != label_len) {
+ if (label_len > INT_MAX) {
return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
- EVP_PKEY_CTRL_RSA_OAEP_LABEL, label_len,
+ EVP_PKEY_CTRL_RSA_OAEP_LABEL, (int)label_len,
(void *)label);
}
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
index db38d5cf..2c4b266d 100644
--- a/src/crypto/evp/p_rsa_asn1.c
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -55,40 +55,45 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "../rsa/internal.h"
#include "internal.h"
-static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
- uint8_t *encoded;
- size_t encoded_len;
- if (!RSA_public_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
- return 0;
- }
-
- if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL,
- encoded, encoded_len)) {
- OPENSSL_free(encoded);
+static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
+ /* See RFC 3279, section 2.3.1. */
+ CBB spki, algorithm, oid, null, key_bitstring;
+ if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+ !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+ !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+ !RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
-static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
- const uint8_t *p;
- int pklen;
- if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) {
+static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* See RFC 3279, section 2.3.1. */
+
+ /* The parameters must be NULL. */
+ CBS null;
+ if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
+ CBS_len(&null) != 0 ||
+ CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
@@ -98,16 +103,14 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
* TODO(davidben): Switch this to the strict version in March 2016 or when
* Chromium can force client certificates down a different codepath, whichever
* comes first. */
- CBS cbs;
- CBS_init(&cbs, p, pklen);
- RSA *rsa = RSA_parse_public_key_buggy(&cbs);
- if (rsa == NULL || CBS_len(&cbs) != 0) {
+ RSA *rsa = RSA_parse_public_key_buggy(key);
+ if (rsa == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
RSA_free(rsa);
return 0;
}
- EVP_PKEY_assign_RSA(pkey, rsa);
+ EVP_PKEY_assign_RSA(out, rsa);
return 1;
}
@@ -116,39 +119,42 @@ static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
}
-static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
- uint8_t *encoded;
- size_t encoded_len;
- if (!RSA_private_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
- return 0;
- }
-
- /* TODO(fork): const correctness in next line. */
- if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
- V_ASN1_NULL, NULL, encoded, encoded_len)) {
- OPENSSL_free(encoded);
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+ CBB pkcs8, algorithm, oid, null, private_key;
+ if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+ !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+ !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+ !RSA_marshal_private_key(&private_key, key->pkey.rsa) ||
+ !CBB_flush(out)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
-static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
- const uint8_t *p;
- int pklen;
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+ /* Per RFC 3447, A.1, the parameters have type NULL. */
+ CBS null;
+ if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
+ CBS_len(&null) != 0 ||
+ CBS_len(params) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
- RSA *rsa = RSA_private_key_from_bytes(p, pklen);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
+ RSA *rsa = RSA_parse_private_key(key);
+ if (rsa == NULL || CBS_len(key) != 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ RSA_free(rsa);
return 0;
}
- EVP_PKEY_assign_RSA(pkey, rsa);
+ EVP_PKEY_assign_RSA(out, rsa);
return 1;
}
@@ -170,553 +176,17 @@ static int rsa_bits(const EVP_PKEY *pkey) {
static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
- size_t i;
-
- if (!b) {
- return;
- }
-
- i = BN_num_bytes(b);
- if (*pbuflen < i) {
- *pbuflen = i;
- }
-}
-
-static int do_rsa_print(BIO *out, const RSA *rsa, int off,
- int include_private) {
- char *str;
- const char *s;
- uint8_t *m = NULL;
- int ret = 0, mod_len = 0;
- size_t buf_len = 0;
-
- update_buflen(rsa->n, &buf_len);
- update_buflen(rsa->e, &buf_len);
-
- if (include_private) {
- update_buflen(rsa->d, &buf_len);
- update_buflen(rsa->p, &buf_len);
- update_buflen(rsa->q, &buf_len);
- update_buflen(rsa->dmp1, &buf_len);
- update_buflen(rsa->dmq1, &buf_len);
- update_buflen(rsa->iqmp, &buf_len);
-
- if (rsa->additional_primes != NULL) {
- size_t i;
-
- for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
- i++) {
- const RSA_additional_prime *ap =
- sk_RSA_additional_prime_value(rsa->additional_primes, i);
- update_buflen(ap->prime, &buf_len);
- update_buflen(ap->exp, &buf_len);
- update_buflen(ap->coeff, &buf_len);
- }
- }
- }
-
- m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (rsa->n != NULL) {
- mod_len = BN_num_bits(rsa->n);
- }
-
- if (!BIO_indent(out, off, 128)) {
- goto err;
- }
-
- if (include_private && rsa->d) {
- if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
- goto err;
- }
- str = "modulus:";
- s = "publicExponent:";
- } else {
- if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
- goto err;
- }
- str = "Modulus:";
- s = "Exponent:";
- }
- if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
- !ASN1_bn_print(out, s, rsa->e, m, off)) {
- goto err;
- }
-
- if (include_private) {
- if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
- !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
- !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
- !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
- !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
- !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
- goto err;
- }
-
- if (rsa->additional_primes != NULL &&
- sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
- size_t i;
-
- if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
- goto err;
- }
- for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
- i++) {
- const RSA_additional_prime *ap =
- sk_RSA_additional_prime_value(rsa->additional_primes, i);
-
- if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
- (unsigned)(i + 3)) <= 0 ||
- !ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
- !ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
- !ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
- goto err;
- }
- }
- }
- }
- ret = 1;
-
-err:
- OPENSSL_free(m);
- return ret;
-}
-
-static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
-}
-
-
-static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
-}
-
-/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
-static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
- const uint8_t *p;
- int plen;
-
- if (alg == NULL || alg->parameter == NULL ||
- OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
- alg->parameter->type != V_ASN1_SEQUENCE) {
- return NULL;
- }
-
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- return d2i_X509_ALGOR(NULL, &p, plen);
-}
-
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
- X509_ALGOR **pmaskHash) {
- const uint8_t *p;
- int plen;
- RSA_PSS_PARAMS *pss;
-
- *pmaskHash = NULL;
-
- if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) {
- return NULL;
- }
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
-
- if (!pss) {
- return NULL;
- }
-
- *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
-
- return pss;
-}
-
-static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
- X509_ALGOR *maskHash, int indent) {
- int rv = 0;
-
- if (!pss) {
- if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
- return 0;
- }
- return 1;
- }
-
- if (BIO_puts(bp, "\n") <= 0 ||
- !BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Hash Algorithm: ") <= 0) {
- goto err;
- }
-
- if (pss->hashAlgorithm) {
- if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
- goto err;
- }
-
- if (BIO_puts(bp, "\n") <= 0 ||
- !BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Mask Algorithm: ") <= 0) {
- goto err;
- }
-
- if (pss->maskGenAlgorithm) {
- if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
- BIO_puts(bp, " with ") <= 0) {
- goto err;
- }
-
- if (maskHash) {
- if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "INVALID") <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- if (!BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Salt Length: 0x") <= 0) {
- goto err;
- }
-
- if (pss->saltLength) {
- if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "14 (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- if (!BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Trailer Field: 0x") <= 0) {
- goto err;
- }
-
- if (pss->trailerField) {
- if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "BC (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- rv = 1;
-
-err:
- return rv;
-}
-
-static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
- const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
- if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
- int rv;
- RSA_PSS_PARAMS *pss;
- X509_ALGOR *maskHash;
-
- pss = rsa_pss_decode(sigalg, &maskHash);
- rv = rsa_pss_param_print(bp, pss, maskHash, indent);
- RSA_PSS_PARAMS_free(pss);
- X509_ALGOR_free(maskHash);
- if (!rv) {
- return 0;
- }
- } else if (!sig && BIO_puts(bp, "\n") <= 0) {
- return 0;
- }
-
- if (sig) {
- return X509_signature_dump(bp, sig, indent);
- }
- return 1;
-}
-
-static int old_rsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
- return 0;
- }
- EVP_PKEY_assign_RSA(pkey, rsa);
- return 1;
-}
-
-static int old_rsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
- return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
-}
-
-/* allocate and set algorithm ID from EVP_MD, default SHA1 */
-static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
- if (EVP_MD_type(md) == NID_sha1) {
- return 1;
- }
- *palg = X509_ALGOR_new();
- if (!*palg) {
- return 0;
- }
- X509_ALGOR_set_md(*palg, md);
- return 1;
-}
-
-/* Allocate and set MGF1 algorithm ID from EVP_MD */
-static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
- X509_ALGOR *algtmp = NULL;
- ASN1_STRING *stmp = NULL;
- *palg = NULL;
-
- if (EVP_MD_type(mgf1md) == NID_sha1) {
- return 1;
- }
- /* need to embed algorithm ID inside another */
- if (!rsa_md_to_algor(&algtmp, mgf1md) ||
- !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
- goto err;
- }
- *palg = X509_ALGOR_new();
- if (!*palg) {
- goto err;
- }
- X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
- stmp = NULL;
-
-err:
- ASN1_STRING_free(stmp);
- X509_ALGOR_free(algtmp);
- if (*palg) {
- return 1;
- }
-
- return 0;
-}
-
-/* convert algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
- const EVP_MD *md;
- if (!alg) {
- return EVP_sha1();
- }
- md = EVP_get_digestbyobj(alg->algorithm);
- if (md == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_DIGEST);
- }
- return md;
-}
-
-/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
- const EVP_MD *md;
- if (!alg) {
- return EVP_sha1();
- }
- /* Check mask and lookup mask hash algorithm */
- if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_ALGORITHM);
- return NULL;
- }
- if (!maskHash) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_PARAMETER);
- return NULL;
- }
- md = EVP_get_digestbyobj(maskHash->algorithm);
- if (md == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MASK_DIGEST);
- return NULL;
- }
- return md;
-}
-
-/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding
- * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */
-static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
- const EVP_MD *sigmd, *mgf1md;
- RSA_PSS_PARAMS *pss = NULL;
- ASN1_STRING *os = NULL;
- EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
- int saltlen, rv = 0;
-
- if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) ||
- !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) ||
- !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
- goto err;
- }
-
- if (saltlen == -1) {
- saltlen = EVP_MD_size(sigmd);
- } else if (saltlen == -2) {
- saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
- if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
- saltlen--;
- }
- } else {
- goto err;
- }
-
- pss = RSA_PSS_PARAMS_new();
- if (!pss) {
- goto err;
- }
-
- if (saltlen != 20) {
- pss->saltLength = ASN1_INTEGER_new();
- if (!pss->saltLength ||
- !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
- goto err;
- }
- }
-
- if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
- !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
- goto err;
- }
-
- /* Finally create string with pss parameter encoding. */
- if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
- goto err;
- }
- rv = 1;
-
-err:
- if (pss) {
- RSA_PSS_PARAMS_free(pss);
- }
- if (rv) {
- return os;
- }
- if (os) {
- ASN1_STRING_free(os);
- }
- return NULL;
-}
-
-/* From PSS AlgorithmIdentifier set public key parameters. */
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
- int ret = 0;
- int saltlen;
- const EVP_MD *mgf1md = NULL, *md = NULL;
- RSA_PSS_PARAMS *pss;
- X509_ALGOR *maskHash;
- EVP_PKEY_CTX *pkctx;
-
- /* Sanity check: make sure it is PSS */
- if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
- return 0;
- }
- /* Decode PSS parameters */
- pss = rsa_pss_decode(sigalg, &maskHash);
- if (pss == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_PARAMETERS);
- goto err;
- }
-
- mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
- if (!mgf1md) {
- goto err;
- }
- md = rsa_algor_to_md(pss->hashAlgorithm);
- if (!md) {
- goto err;
- }
-
- saltlen = 20;
- if (pss->saltLength) {
- saltlen = ASN1_INTEGER_get(pss->saltLength);
-
- /* Could perform more salt length sanity checks but the main
- * RSA routines will trap other invalid values anyway. */
- if (saltlen < 0) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SALT_LENGTH);
- goto err;
- }
- }
-
- /* low-level routines support only trailer field 0xbc (value 1)
- * and PKCS#1 says we should reject any other value anyway. */
- if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_TRAILER);
- goto err;
- }
-
- if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
- !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
- !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
- goto err;
- }
-
- ret = 1;
-
-err:
- RSA_PSS_PARAMS_free(pss);
- if (maskHash) {
- X509_ALGOR_free(maskHash);
- }
- return ret;
-}
-
-/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
- * is encountered requiring special handling. We currently only handle PSS. */
-static int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
- X509_ALGOR *sigalg,
- EVP_PKEY *pkey) {
- /* Sanity check: make sure it is PSS */
- if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
- return 0;
- }
- return rsa_pss_to_ctx(ctx, sigalg, pkey);
-}
-
-static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
- EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
- int pad_mode;
- EVP_PKEY_CTX *pkctx = ctx->pctx;
- if (!EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode)) {
- return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
- }
- if (pad_mode == RSA_PKCS1_PSS_PADDING) {
- ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
- if (!os1) {
- return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
- }
- X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
- return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
- }
-
- /* Other padding schemes use the default behavior. */
- return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
-}
-
const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
EVP_PKEY_RSA,
- EVP_PKEY_RSA,
- ASN1_PKEY_SIGPARAM_NULL,
-
- "RSA",
+ /* 1.2.840.113549.1.1.1 */
+ {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9,
rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
- rsa_pub_print,
rsa_priv_decode,
rsa_priv_encode,
- rsa_priv_print,
rsa_opaque,
rsa_supports_digest,
@@ -724,14 +194,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
int_rsa_size,
rsa_bits,
- 0,0,0,0,0,0,
+ 0,0,0,
- rsa_sig_print,
int_rsa_free,
-
- old_rsa_priv_decode,
- old_rsa_priv_encode,
-
- rsa_digest_verify_init_from_algorithm,
- rsa_digest_sign_algorithm,
};
diff --git a/src/crypto/evp/pbkdf_test.cc b/src/crypto/evp/pbkdf_test.cc
index a39189f5..438ab644 100644
--- a/src/crypto/evp/pbkdf_test.cc
+++ b/src/crypto/evp/pbkdf_test.cc
@@ -15,7 +15,6 @@
#include <stdio.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -189,7 +188,6 @@ static bool TestZeroIterations() {
int main(void) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!TestEmptyPassword()) {
fprintf(stderr, "TestEmptyPassword failed\n");
diff --git a/src/crypto/evp/print.c b/src/crypto/evp/print.c
new file mode 100644
index 00000000..56521ec5
--- /dev/null
+++ b/src/crypto/evp/print.c
@@ -0,0 +1,527 @@
+/* ====================================================================
+ * Copyright (c) 2006 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/evp.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/mem.h>
+#include <openssl/rsa.h>
+
+#include "../rsa/internal.h"
+
+
+static int bn_print(BIO *bp, const char *number, const BIGNUM *num,
+ uint8_t *buf, int off) {
+ if (num == NULL) {
+ return 1;
+ }
+
+ if (!BIO_indent(bp, off, 128)) {
+ return 0;
+ }
+ if (BN_is_zero(num)) {
+ if (BIO_printf(bp, "%s 0\n", number) <= 0) {
+ return 0;
+ }
+ return 1;
+ }
+
+ if (BN_num_bytes(num) <= sizeof(long)) {
+ const char *neg = BN_is_negative(num) ? "-" : "";
+ if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
+ (unsigned long)num->d[0], neg,
+ (unsigned long)num->d[0]) <= 0) {
+ return 0;
+ }
+ } else {
+ buf[0] = 0;
+ if (BIO_printf(bp, "%s%s", number,
+ (BN_is_negative(num)) ? " (Negative)" : "") <= 0) {
+ return 0;
+ }
+ int n = BN_bn2bin(num, &buf[1]);
+
+ if (buf[1] & 0x80) {
+ n++;
+ } else {
+ buf++;
+ }
+
+ int i;
+ for (i = 0; i < n; i++) {
+ if ((i % 15) == 0) {
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, off + 4, 128)) {
+ return 0;
+ }
+ }
+ if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) {
+ return 0;
+ }
+ }
+ if (BIO_write(bp, "\n", 1) <= 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
+ size_t i;
+
+ if (!b) {
+ return;
+ }
+
+ i = BN_num_bytes(b);
+ if (*pbuflen < i) {
+ *pbuflen = i;
+ }
+}
+
+/* RSA keys. */
+
+static int do_rsa_print(BIO *out, const RSA *rsa, int off,
+ int include_private) {
+ const char *s, *str;
+ uint8_t *m = NULL;
+ int ret = 0, mod_len = 0;
+ size_t buf_len = 0;
+
+ update_buflen(rsa->n, &buf_len);
+ update_buflen(rsa->e, &buf_len);
+
+ if (include_private) {
+ update_buflen(rsa->d, &buf_len);
+ update_buflen(rsa->p, &buf_len);
+ update_buflen(rsa->q, &buf_len);
+ update_buflen(rsa->dmp1, &buf_len);
+ update_buflen(rsa->dmq1, &buf_len);
+ update_buflen(rsa->iqmp, &buf_len);
+
+ if (rsa->additional_primes != NULL) {
+ size_t i;
+
+ for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
+ i++) {
+ const RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+ update_buflen(ap->prime, &buf_len);
+ update_buflen(ap->exp, &buf_len);
+ update_buflen(ap->coeff, &buf_len);
+ }
+ }
+ }
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (rsa->n != NULL) {
+ mod_len = BN_num_bits(rsa->n);
+ }
+
+ if (!BIO_indent(out, off, 128)) {
+ goto err;
+ }
+
+ if (include_private && rsa->d) {
+ if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "modulus:";
+ s = "publicExponent:";
+ } else {
+ if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "Modulus:";
+ s = "Exponent:";
+ }
+ if (!bn_print(out, str, rsa->n, m, off) ||
+ !bn_print(out, s, rsa->e, m, off)) {
+ goto err;
+ }
+
+ if (include_private) {
+ if (!bn_print(out, "privateExponent:", rsa->d, m, off) ||
+ !bn_print(out, "prime1:", rsa->p, m, off) ||
+ !bn_print(out, "prime2:", rsa->q, m, off) ||
+ !bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
+ !bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
+ !bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
+ goto err;
+ }
+
+ if (rsa->additional_primes != NULL &&
+ sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
+ size_t i;
+
+ if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
+ goto err;
+ }
+ for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
+ i++) {
+ const RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+
+ if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
+ (unsigned)(i + 3)) <= 0 ||
+ !bn_print(out, "prime:", ap->prime, m, off) ||
+ !bn_print(out, "exponent:", ap->exp, m, off) ||
+ !bn_print(out, "coeff:", ap->coeff, m, off)) {
+ goto err;
+ }
+ }
+ }
+ }
+ ret = 1;
+
+err:
+ OPENSSL_free(m);
+ return ret;
+}
+
+static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
+}
+
+static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
+}
+
+
+/* DSA keys. */
+
+static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
+ uint8_t *m = NULL;
+ int ret = 0;
+ size_t buf_len = 0;
+ const char *ktype = NULL;
+
+ const BIGNUM *priv_key, *pub_key;
+
+ priv_key = NULL;
+ if (ptype == 2) {
+ priv_key = x->priv_key;
+ }
+
+ pub_key = NULL;
+ if (ptype > 0) {
+ pub_key = x->pub_key;
+ }
+
+ ktype = "DSA-Parameters";
+ if (ptype == 2) {
+ ktype = "Private-Key";
+ } else if (ptype == 1) {
+ ktype = "Public-Key";
+ }
+
+ update_buflen(x->p, &buf_len);
+ update_buflen(x->q, &buf_len);
+ update_buflen(x->g, &buf_len);
+ update_buflen(priv_key, &buf_len);
+ update_buflen(pub_key, &buf_len);
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (priv_key) {
+ if (!BIO_indent(bp, off, 128) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
+ goto err;
+ }
+ }
+
+ if (!bn_print(bp, "priv:", priv_key, m, off) ||
+ !bn_print(bp, "pub: ", pub_key, m, off) ||
+ !bn_print(bp, "P: ", x->p, m, off) ||
+ !bn_print(bp, "Q: ", x->q, m, off) ||
+ !bn_print(bp, "G: ", x->g, m, off)) {
+ goto err;
+ }
+ ret = 1;
+
+err:
+ OPENSSL_free(m);
+ return ret;
+}
+
+static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
+}
+
+static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
+}
+
+static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
+}
+
+
+/* EC keys. */
+
+static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
+ uint8_t *buffer = NULL;
+ const char *ecstr;
+ size_t buf_len = 0, i;
+ int ret = 0, reason = ERR_R_BIO_LIB;
+ BIGNUM *order = NULL;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ const BIGNUM *priv_key;
+ uint8_t *pub_key_bytes = NULL;
+ size_t pub_key_bytes_len = 0;
+
+ if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
+ reason = ERR_R_PASSED_NULL_PARAMETER;
+ goto err;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+
+ if (ktype > 0) {
+ public_key = EC_KEY_get0_public_key(x);
+ if (public_key != NULL) {
+ pub_key_bytes_len = EC_POINT_point2oct(
+ group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
+ if (pub_key_bytes == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes_len =
+ EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
+ pub_key_bytes, pub_key_bytes_len, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ buf_len = pub_key_bytes_len;
+ }
+ }
+
+ if (ktype == 2) {
+ priv_key = EC_KEY_get0_private_key(x);
+ if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
+ buf_len = i;
+ }
+ } else {
+ priv_key = NULL;
+ }
+
+ if (ktype > 0) {
+ buf_len += 10;
+ if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ }
+ if (ktype == 2) {
+ ecstr = "Private-Key";
+ } else if (ktype == 1) {
+ ecstr = "Public-Key";
+ } else {
+ ecstr = "ECDSA-Parameters";
+ }
+
+ if (!BIO_indent(bp, off, 128)) {
+ goto err;
+ }
+ order = BN_new();
+ if (order == NULL || !EC_GROUP_get_order(group, order, NULL) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
+ goto err;
+ }
+
+ if ((priv_key != NULL) &&
+ !bn_print(bp, "priv:", priv_key, buffer, off)) {
+ goto err;
+ }
+ if (pub_key_bytes != NULL) {
+ BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
+ }
+ /* TODO(fork): implement */
+ /*
+ if (!ECPKParameters_print(bp, group, off))
+ goto err; */
+ ret = 1;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(EVP, reason);
+ }
+ OPENSSL_free(pub_key_bytes);
+ BN_free(order);
+ BN_CTX_free(ctx);
+ OPENSSL_free(buffer);
+ return ret;
+}
+
+static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+}
+
+static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+}
+
+
+static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+}
+
+
+typedef struct {
+ int type;
+ int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
+ int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx);
+ int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx);
+} EVP_PKEY_PRINT_METHOD;
+
+static EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
+ {
+ EVP_PKEY_RSA,
+ rsa_pub_print,
+ rsa_priv_print,
+ NULL /* param_print */,
+ },
+ {
+ EVP_PKEY_DSA,
+ dsa_pub_print,
+ dsa_priv_print,
+ dsa_param_print,
+ },
+ {
+ EVP_PKEY_EC,
+ eckey_pub_print,
+ eckey_priv_print,
+ eckey_param_print,
+ },
+};
+
+static size_t kPrintMethodsLen =
+ sizeof(kPrintMethods) / sizeof(kPrintMethods[0]);
+
+static EVP_PKEY_PRINT_METHOD *find_method(int type) {
+ size_t i;
+ for (i = 0; i < kPrintMethodsLen; i++) {
+ if (kPrintMethods[i].type == type) {
+ return &kPrintMethods[i];
+ }
+ }
+ return NULL;
+}
+
+static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
+ const char *kstr) {
+ BIO_indent(out, indent, 128);
+ BIO_printf(out, "%s algorithm unsupported\n", kstr);
+ return 1;
+}
+
+int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->pub_print != NULL) {
+ return method->pub_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Public Key");
+}
+
+int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->priv_print != NULL) {
+ return method->priv_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Private Key");
+}
+
+int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->param_print != NULL) {
+ return method->param_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Parameters");
+}
diff --git a/src/crypto/hkdf/hkdf_test.c b/src/crypto/hkdf/hkdf_test.c
index 63070dc4..b11061ae 100644
--- a/src/crypto/hkdf/hkdf_test.c
+++ b/src/crypto/hkdf/hkdf_test.c
@@ -20,6 +20,8 @@
#include <openssl/err.h>
#include <openssl/hkdf.h>
+#include "../test/test_util.h"
+
typedef struct {
const EVP_MD *(*md_func)(void);
@@ -216,7 +218,6 @@ int main(void) {
size_t i;
CRYPTO_library_init();
- ERR_load_crypto_strings();
for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) {
const hkdf_test_vector_t *test = &kTests[i];
@@ -227,8 +228,9 @@ int main(void) {
return 1;
}
if (memcmp(buf, test->out, test->out_len) != 0) {
- fprintf(stderr, "%u: Resulting key material does not match test vector\n",
- (unsigned)i);
+ fprintf(stderr, "%" OPENSSL_PR_SIZE_T
+ ": Resulting key material does not match test vector\n",
+ i);
return 1;
}
}
diff --git a/src/crypto/hmac/hmac.c b/src/crypto/hmac/hmac.c
index be2dccec..bccc5c02 100644
--- a/src/crypto/hmac/hmac.c
+++ b/src/crypto/hmac/hmac.c
@@ -59,6 +59,7 @@
#include <assert.h>
#include <string.h>
+#include <openssl/digest.h>
#include <openssl/mem.h>
@@ -115,8 +116,8 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
* case. Fix to API to avoid this. */
if (md != ctx->md || key != NULL) {
size_t i;
- uint8_t pad[HMAC_MAX_MD_CBLOCK];
- uint8_t key_block[HMAC_MAX_MD_CBLOCK];
+ uint8_t pad[EVP_MAX_MD_BLOCK_SIZE];
+ uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE];
unsigned key_block_len;
size_t block_size = EVP_MD_block_size(md);
@@ -134,11 +135,11 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
key_block_len = (unsigned)key_len;
}
/* Keys are then padded with zeros. */
- if (key_block_len != HMAC_MAX_MD_CBLOCK) {
+ if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) {
memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len);
}
- for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+ for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
pad[i] = 0x36 ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) ||
@@ -146,7 +147,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
return 0;
}
- for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+ for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
pad[i] = 0x5c ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) ||
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index bf45349e..ded43fe2 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -112,6 +112,15 @@
#include <openssl/ex_data.h>
#include <openssl/thread.h>
+#if defined(_MSC_VER)
+#if !defined(__cplusplus) || _MSC_VER < 1900
+#define alignas(x) __declspec(align(x))
+#define alignof __alignof
+#endif
+#else
+#include <stdalign.h>
+#endif
+
#if defined(OPENSSL_NO_THREADS)
#elif defined(OPENSSL_WINDOWS)
#pragma warning(push, 3)
@@ -126,48 +135,6 @@ extern "C" {
#endif
-/* MSVC's C4701 warning about the use of *potentially*--as opposed to
- * *definitely*--uninitialized values sometimes has false positives. Usually
- * the false positives can and should be worked around by simplifying the
- * control flow. When that is not practical, annotate the function containing
- * the code that triggers the warning with
- * OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS after its parameters:
- *
- * void f() OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS {
- * ...
- * }
- *
- * Note that MSVC's control flow analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS \
- __pragma(warning(suppress:4701))
-#else
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-#endif
-
-/* MSVC will sometimes correctly detect unreachable code and issue a warning,
- * which breaks the build since we treat errors as warnings, in some rare cases
- * where we want to allow the dead code to continue to exist. In these
- * situations, annotate the function containing the unreachable code with
- * OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS after its parameters:
- *
- * void f() OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
- * ...
- * }
- *
- * Note that MSVC's reachability analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS \
- __pragma(warning(suppress:4702))
-#else
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS
-#endif
-
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
defined(OPENSSL_AARCH64)
/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
@@ -179,6 +146,12 @@ void OPENSSL_cpuid_setup(void);
#endif
+#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT)
+typedef __int128_t int128_t;
+typedef __uint128_t uint128_t;
+#endif
+
+
/* Constant-time utility functions.
*
* The following methods return a bitmask of all ones (0xff...f) for true and 0
@@ -321,12 +294,22 @@ static inline int constant_time_select_int(unsigned int mask, int a, int b) {
/* Thread-safe initialisation. */
+/* Android's mingw-w64 has some prototypes for INIT_ONCE, but is missing
+ * others. Work around the missing ones.
+ *
+ * TODO(davidben): Remove this once Android's mingw-w64 is upgraded. See
+ * b/26523949. */
+#if defined(__MINGW32__) && !defined(INIT_ONCE_STATIC_INIT)
+typedef RTL_RUN_ONCE INIT_ONCE;
+#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
+#endif
+
#if defined(OPENSSL_NO_THREADS)
typedef uint32_t CRYPTO_once_t;
#define CRYPTO_ONCE_INIT 0
#elif defined(OPENSSL_WINDOWS)
-typedef LONG CRYPTO_once_t;
-#define CRYPTO_ONCE_INIT 0
+typedef INIT_ONCE CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT INIT_ONCE_STATIC_INIT
#else
typedef pthread_once_t CRYPTO_once_t;
#define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT
@@ -380,8 +363,10 @@ OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count);
* automatically by |CRYPTO_STATIC_MUTEX_lock_*|. */
#if defined(OPENSSL_NO_THREADS)
-struct CRYPTO_STATIC_MUTEX {};
-#define CRYPTO_STATIC_MUTEX_INIT {}
+struct CRYPTO_STATIC_MUTEX {
+ char padding; /* Empty structs have different sizes in C and C++. */
+};
+#define CRYPTO_STATIC_MUTEX_INIT { 0 }
#elif defined(OPENSSL_WINDOWS)
struct CRYPTO_STATIC_MUTEX {
CRYPTO_once_t once;
diff --git a/src/crypto/md4/md4.c b/src/crypto/md4/md4.c
index 86a540b4..f79da9fd 100644
--- a/src/crypto/md4/md4.c
+++ b/src/crypto/md4/md4.c
@@ -60,6 +60,15 @@
#include <string.h>
+uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out) {
+ MD4_CTX ctx;
+ MD4_Init(&ctx);
+ MD4_Update(&ctx, data, len);
+ MD4_Final(out, &ctx);
+
+ return out;
+}
+
/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */
int MD4_Init(MD4_CTX *md4) {
diff --git a/src/crypto/mem.c b/src/crypto/mem.c
index edd14a81..df8e0e33 100644
--- a/src/crypto/mem.c
+++ b/src/crypto/mem.c
@@ -104,9 +104,9 @@ void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size) {
void OPENSSL_cleanse(void *ptr, size_t len) {
#if defined(OPENSSL_WINDOWS)
- SecureZeroMemory(ptr, len);
+ SecureZeroMemory(ptr, len);
#else
- memset(ptr, 0, len);
+ memset(ptr, 0, len);
#if !defined(OPENSSL_NO_ASM)
/* As best as we can tell, this is sufficient to break any optimisations that
diff --git a/src/crypto/modes/asm/aesni-gcm-x86_64.pl b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
index 0ca89c7d..5d58bbbb 100644
--- a/src/crypto/modes/asm/aesni-gcm-x86_64.pl
+++ b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -41,11 +41,12 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+# This must be kept in sync with |$avx| in ghash-x86_64.pl; otherwise tags will
+# be computed incorrectly.
+#
# In upstream, this is controlled by shelling out to the compiler to check
# versions, but BoringSSL is intended to be used with pre-generated perlasm
# output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
$avx = 0;
open OUT,"| \"$^X\" $xlate $flavour $output";
@@ -96,6 +97,23 @@ _aesni_ctr32_ghash_6x:
vpxor $rndkey,$inout3,$inout3
vmovups 0x10-0x80($key),$T2 # borrow $T2 for $rndkey
vpclmulqdq \$0x01,$Hkey,$Z3,$Z2
+
+ # At this point, the current block of 96 (0x60) bytes has already been
+ # loaded into registers. Concurrently with processing it, we want to
+ # load the next 96 bytes of input for the next round. Obviously, we can
+ # only do this if there are at least 96 more bytes of input beyond the
+ # input we're currently processing, or else we'd read past the end of
+ # the input buffer. Here, we set |%r12| to 96 if there are at least 96
+ # bytes of input beyond the 96 bytes we're already processing, and we
+ # set |%r12| to 0 otherwise. In the case where we set |%r12| to 96,
+ # we'll read in the next block so that it is in registers for the next
+ # loop iteration. In the case where we set |%r12| to 0, we'll re-read
+ # the current block and then ignore what we re-read.
+ #
+ # At this point, |$in0| points to the current (already read into
+ # registers) block, and |$end0| points to 2*96 bytes before the end of
+ # the input. Thus, |$in0| > |$end0| means that we do not have the next
+ # 96-byte block to read in, and |$in0| <= |$end0| means we do.
xor %r12,%r12
cmp $in0,$end0
@@ -388,6 +406,9 @@ $code.=<<___;
.align 32
aesni_gcm_decrypt:
xor $ret,$ret
+
+ # We call |_aesni_ctr32_ghash_6x|, which requires at least 96 (0x60)
+ # bytes of input.
cmp \$0x60,$len # minimal accepted length
jb .Lgcm_dec_abort
@@ -442,7 +463,15 @@ $code.=<<___;
vmovdqu 0x50($inp),$Z3 # I[5]
lea ($inp),$in0
vmovdqu 0x40($inp),$Z0
+
+ # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+ # bytes before the end of the input. Note, in particular, that this is
+ # correct even if |$len| is not an even multiple of 96 or 16. XXX: This
+ # seems to require that |$inp| + |$len| >= 2*96 (0xc0); i.e. |$inp| must
+ # not be near the very beginning of the address space when |$len| < 2*96
+ # (0xc0).
lea -0xc0($inp,$len),$end0
+
vmovdqu 0x30($inp),$Z1
shr \$4,$len
xor $ret,$ret
@@ -477,7 +506,7 @@ $code.=<<___;
___
$code.=<<___ if ($win64);
movaps -0xd8(%rax),%xmm6
- movaps -0xd8(%rax),%xmm7
+ movaps -0xc8(%rax),%xmm7
movaps -0xb8(%rax),%xmm8
movaps -0xa8(%rax),%xmm9
movaps -0x98(%rax),%xmm10
@@ -598,6 +627,10 @@ _aesni_ctr32_6x:
.align 32
aesni_gcm_encrypt:
xor $ret,$ret
+
+ # We call |_aesni_ctr32_6x| twice, each call consuming 96 bytes of
+ # input. Then we call |_aesni_ctr32_ghash_6x|, which requires at
+ # least 96 more bytes of input.
cmp \$0x60*3,$len # minimal accepted length
jb .Lgcm_enc_abort
@@ -647,7 +680,16 @@ $code.=<<___;
.Lenc_no_key_aliasing:
lea ($out),$in0
+
+ # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+ # bytes before the end of the input. Note, in particular, that this is
+ # correct even if |$len| is not an even multiple of 96 or 16. Unlike in
+ # the decryption case, there's no caveat that |$out| must not be near
+ # the very beginning of the address space, because we know that
+ # |$len| >= 3*96 from the check above, and so we know
+ # |$out| + |$len| >= 2*96 (0xc0).
lea -0xc0($out,$len),$end0
+
shr \$4,$len
call _aesni_ctr32_6x
diff --git a/src/crypto/modes/asm/ghash-armv4.pl b/src/crypto/modes/asm/ghash-armv4.pl
index d3288223..bb0dba5f 100644
--- a/src/crypto/modes/asm/ghash-armv4.pl
+++ b/src/crypto/modes/asm/ghash-armv4.pl
@@ -163,7 +163,6 @@ rem_4bit_get:
.size rem_4bit_get,.-rem_4bit_get
.global gcm_ghash_4bit
-.hidden gcm_ghash_4bit
.type gcm_ghash_4bit,%function
gcm_ghash_4bit:
sub r12,pc,#8
@@ -260,7 +259,6 @@ $code.=<<___;
.size gcm_ghash_4bit,.-gcm_ghash_4bit
.global gcm_gmult_4bit
-.hidden gcm_gmult_4bit
.type gcm_gmult_4bit,%function
gcm_gmult_4bit:
stmdb sp!,{r4-r11,lr}
@@ -391,7 +389,6 @@ $code.=<<___;
.fpu neon
.global gcm_init_neon
-.hidden gcm_init_neon
.type gcm_init_neon,%function
.align 4
gcm_init_neon:
@@ -413,7 +410,6 @@ gcm_init_neon:
.size gcm_init_neon,.-gcm_init_neon
.global gcm_gmult_neon
-.hidden gcm_gmult_neon
.type gcm_gmult_neon,%function
.align 4
gcm_gmult_neon:
@@ -432,7 +428,6 @@ gcm_gmult_neon:
.size gcm_gmult_neon,.-gcm_gmult_neon
.global gcm_ghash_neon
-.hidden gcm_ghash_neon
.type gcm_ghash_neon,%function
.align 4
gcm_ghash_neon:
diff --git a/src/crypto/modes/asm/ghash-x86_64.pl b/src/crypto/modes/asm/ghash-x86_64.pl
index e42ca321..5a11fb94 100644
--- a/src/crypto/modes/asm/ghash-x86_64.pl
+++ b/src/crypto/modes/asm/ghash-x86_64.pl
@@ -90,11 +90,12 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+# This must be kept in sync with |$avx| in aesni-gcm-x86_64.pl; otherwise tags
+# will be computed incorrectly.
+#
# In upstream, this is controlled by shelling out to the compiler to check
# versions, but BoringSSL is intended to be used with pre-generated perlasm
# output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
$avx = 0;
open OUT,"| \"$^X\" $xlate $flavour $output";
diff --git a/src/crypto/modes/cfb.c b/src/crypto/modes/cfb.c
index c58614ba..51b883e8 100644
--- a/src/crypto/modes/cfb.c
+++ b/src/crypto/modes/cfb.c
@@ -57,14 +57,13 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num, int enc,
- block128_f block) {
- unsigned int n;
+ const void *key, uint8_t ivec[16], unsigned *num,
+ int enc, block128_f block) {
size_t l = 0;
assert(in && out && key && ivec && num);
- n = *num;
+ unsigned n = *num;
if (enc) {
while (n && len) {
@@ -199,7 +198,7 @@ static void cfbr_encrypt_block(const uint8_t *in, uint8_t *out, unsigned nbits,
/* N.B. This expects the input to be packed, MS bit first */
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block) {
size_t n;
uint8_t c[1], d[1];
@@ -217,7 +216,7 @@ void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const void *key,
- unsigned char ivec[16], int *num, int enc,
+ unsigned char ivec[16], unsigned *num, int enc,
block128_f block) {
size_t n;
diff --git a/src/crypto/modes/ctr.c b/src/crypto/modes/ctr.c
index 52ff048f..b84e72c5 100644
--- a/src/crypto/modes/ctr.c
+++ b/src/crypto/modes/ctr.c
@@ -59,17 +59,13 @@
/* increment counter (128-bit int) by 1 */
static void ctr128_inc(uint8_t *counter) {
- uint32_t n = 16;
- uint8_t c;
+ uint32_t n = 16, c = 1;
do {
--n;
- c = counter[n];
- ++c;
- counter[n] = c;
- if (c) {
- return;
- }
+ c += counter[n];
+ counter[n] = (uint8_t) c;
+ c >>= 8;
} while (n);
}
@@ -104,7 +100,7 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
}
#if STRICT_ALIGNMENT
- if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ if (((size_t)in | (size_t)out | (size_t)ecount_buf) % sizeof(size_t) != 0) {
size_t l = 0;
while (l < len) {
if (n == 0) {
@@ -124,8 +120,9 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
while (len >= 16) {
(*block)(ivec, ecount_buf, key);
ctr128_inc(ivec);
- for (; n < 16; n += sizeof(size_t)) {
- *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n);
+ for (n = 0; n < 16; n += sizeof(size_t)) {
+ *(size_t *)(out + n) = *(const size_t *)(in + n) ^
+ *(const size_t *)(ecount_buf + n);
}
len -= 16;
out += 16;
@@ -145,17 +142,13 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
/* increment upper 96 bits of 128-bit counter by 1 */
static void ctr96_inc(uint8_t *counter) {
- uint32_t n = 12;
- uint8_t c;
+ uint32_t n = 12, c = 1;
do {
--n;
- c = counter[n];
- ++c;
- counter[n] = c;
- if (c) {
- return;
- }
+ c += counter[n];
+ counter[n] = (uint8_t) c;
+ c >>= 8;
} while (n);
}
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
index 65451a6c..b8571313 100644
--- a/src/crypto/modes/gcm.c
+++ b/src/crypto/modes/gcm.c
@@ -55,6 +55,7 @@
#include <openssl/cpu.h>
#include "internal.h"
+#include "../internal.h"
#if !defined(OPENSSL_NO_ASM) && \
@@ -337,7 +338,18 @@ void gcm_ghash_clmul(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
#else
void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]);
void gcm_gmult_avx(uint64_t Xi[2], const u128 Htable[16]);
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len);
+void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
+ size_t len);
+#define AESNI_GCM
+static int aesni_gcm_enabled(GCM128_CONTEXT *ctx, ctr128_f stream) {
+ return stream == aesni_ctr32_encrypt_blocks &&
+ ctx->ghash == gcm_ghash_avx;
+}
+
+size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
+size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
#endif
#if defined(OPENSSL_X86)
@@ -380,14 +392,14 @@ void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
static int neon_capable(void) {
return 0;
}
-void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
+static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
abort();
}
-void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
+static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
abort();
}
-void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
- size_t len) {
+static void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16],
+ const uint8_t *inp, size_t len) {
abort();
}
#endif
@@ -405,17 +417,6 @@ void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
#endif
#endif
-GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key, block128_f block) {
- GCM128_CONTEXT *ret;
-
- ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT));
- if (ret != NULL) {
- CRYPTO_gcm128_init(ret, key, block);
- }
-
- return ret;
-}
-
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
block128_f block) {
const union {
@@ -606,7 +607,8 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
}
#ifdef GHASH
- if ((i = (len & (size_t) - 16))) {
+ i = len & kSizeTWithoutLower4Bits;
+ if (i != 0) {
GHASH(ctx, aad, i);
aad += i;
len -= i;
@@ -895,7 +897,8 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key,
}
len -= GHASH_CHUNK;
}
- if ((i = (len & (size_t) - 16))) {
+ i = len & kSizeTWithoutLower4Bits;
+ if (i != 0) {
GHASH(ctx, in, i);
while (len >= 16) {
size_t *out_t = (size_t *)out;
@@ -989,12 +992,6 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
-
n = ctx->mres;
if (n) {
while (n && len) {
@@ -1009,6 +1006,24 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
return 1;
}
}
+
+#if defined(AESNI_GCM)
+ if (aesni_gcm_enabled(ctx, stream)) {
+ /* |aesni_gcm_encrypt| may not process all the input given to it. It may
+ * not process *any* of its input if it is deemed too small. */
+ size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+ in += bulk;
+ out += bulk;
+ len -= bulk;
+ }
+#endif
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
(*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
@@ -1098,12 +1113,6 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
-
n = ctx->mres;
if (n) {
while (n && len) {
@@ -1120,6 +1129,24 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
return 1;
}
}
+
+#if defined(AESNI_GCM)
+ if (aesni_gcm_enabled(ctx, stream)) {
+ /* |aesni_gcm_decrypt| may not process all the input given to it. It may
+ * not process *any* of its input if it is deemed too small. */
+ size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+ in += bulk;
+ out += bulk;
+ len -= bulk;
+ }
+#endif
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
GHASH(ctx, in, GHASH_CHUNK);
@@ -1233,13 +1260,6 @@ void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len) {
memcpy(tag, ctx->Xi.c, len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
}
-void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx) {
- if (ctx) {
- OPENSSL_cleanse(ctx, sizeof(*ctx));
- OPENSSL_free(ctx);
- }
-}
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
int crypto_gcm_clmul_enabled(void) {
#ifdef GHASH_ASM
diff --git a/src/crypto/modes/gcm_test.c b/src/crypto/modes/gcm_test.c
index 9414ac6e..56639e6e 100644
--- a/src/crypto/modes/gcm_test.c
+++ b/src/crypto/modes/gcm_test.c
@@ -282,8 +282,10 @@ static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
uint8_t v, v2;
if (!from_hex(&v, in[i]) ||
!from_hex(&v2, in[i+1])) {
- fprintf(stderr, "%u: invalid hex digit in %s around offset %u.\n",
- test_num, description, (unsigned)i);
+ fprintf(stderr,
+ "%u: invalid hex digit in %s around offset %" OPENSSL_PR_SIZE_T
+ ".\n",
+ test_num, description, i);
goto err;
}
buf[i/2] = (v << 4) | v2;
@@ -336,7 +338,7 @@ static int run_test_case(unsigned test_num, const struct test_case *test) {
}
out = OPENSSL_malloc(plaintext_len);
- if (out == NULL) {
+ if (plaintext_len != 0 && out == NULL) {
goto out;
}
if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
diff --git a/src/crypto/modes/internal.h b/src/crypto/modes/internal.h
index 7255a7ca..b46e8369 100644
--- a/src/crypto/modes/internal.h
+++ b/src/crypto/modes/internal.h
@@ -179,16 +179,6 @@ struct gcm128_context {
block128_f block;
};
-struct ccm128_context {
- union {
- uint64_t u[2];
- uint8_t c[16];
- } nonce, cmac;
- uint64_t blocks;
- block128_f block;
- void *key;
-};
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
/* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is
* used. */
@@ -210,7 +200,7 @@ typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks,
* incremented by this function. */
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const void *key, uint8_t ivec[16],
- uint8_t ecount_buf[16], unsigned int *num,
+ uint8_t ecount_buf[16], unsigned *num,
block128_f block);
/* CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes
@@ -219,7 +209,7 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
* function. */
void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
const void *key, uint8_t ivec[16],
- uint8_t ecount_buf[16], unsigned int *num,
+ uint8_t ecount_buf[16], unsigned *num,
ctr128_f ctr);
@@ -232,11 +222,6 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
typedef struct gcm128_context GCM128_CONTEXT;
-/* CRYPTO_gcm128_new allocates a fresh |GCM128_CONTEXT| and calls
- * |CRYPTO_gcm128_init|. It returns the new context, or NULL on error. */
-OPENSSL_EXPORT GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key,
- block128_f block);
-
/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with
* the given key. */
OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
@@ -297,9 +282,6 @@ OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag,
OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag,
size_t len);
-/* CRYPTO_gcm128_release clears and frees |ctx|. */
-OPENSSL_EXPORT void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
-
/* CBC. */
@@ -331,7 +313,7 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
* call. */
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
size_t len, const void *key, uint8_t ivec[16],
- int *num, block128_f block);
+ unsigned *num, block128_f block);
/* CFB. */
@@ -341,21 +323,21 @@ void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
* |len| be a multiple of any value and any partial blocks are stored in |ivec|
* and |*num|, the latter must be zero before the initial call. */
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num, int enc,
- block128_f block);
+ const void *key, uint8_t ivec[16], unsigned *num,
+ int enc, block128_f block);
/* CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
* from |in| to |out| using |block| in CFB-8 mode. Prior to the first call
* |num| should be set to zero. */
void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block);
/* CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
* from |in| to |out| using |block| in CFB-1 mode. Prior to the first call
* |num| should be set to zero. */
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block);
size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
@@ -363,6 +345,12 @@ size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
block128_f block);
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec);
+#endif
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/src/crypto/modes/ofb.c b/src/crypto/modes/ofb.c
index 63c3165a..2c5bdc9a 100644
--- a/src/crypto/modes/ofb.c
+++ b/src/crypto/modes/ofb.c
@@ -56,13 +56,11 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
block128_f block) {
- unsigned int n;
-
assert(in && out && key && ivec && num);
- n = *num;
+ unsigned n = *num;
while (n && len) {
*(out++) = *(in++) ^ ivec[n];
diff --git a/src/crypto/newhope/CMakeLists.txt b/src/crypto/newhope/CMakeLists.txt
new file mode 100644
index 00000000..385cd6a7
--- /dev/null
+++ b/src/crypto/newhope/CMakeLists.txt
@@ -0,0 +1,22 @@
+add_library(
+ newhope
+
+ OBJECT
+
+ error_correction.c
+ newhope.c
+ ntt.c
+ poly.c
+ precomp.c
+ reduce.c
+)
+
+add_executable(
+ newhope_test
+
+ newhope_test.c
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(newhope_test crypto)
+add_dependencies(all_tests newhope_test)
diff --git a/src/crypto/newhope/error_correction.c b/src/crypto/newhope/error_correction.c
new file mode 100644
index 00000000..e4ac1c26
--- /dev/null
+++ b/src/crypto/newhope/error_correction.c
@@ -0,0 +1,134 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string.h>
+
+#include <openssl/base.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+/* See paper for details on the error reconciliation */
+
+static int32_t abs_32(int32_t v) {
+ int32_t mask = v >> 31;
+ return (v ^ mask) - mask;
+}
+
+static int32_t f(int32_t* v0, int32_t* v1, int32_t x) {
+ int32_t xit, t, r, b;
+
+ /* Next 6 lines compute t = x/PARAM_Q */
+ b = x * 2730;
+ t = b >> 25;
+ b = x - t * 12289;
+ b = 12288 - b;
+ b >>= 31;
+ t -= b;
+
+ r = t & 1;
+ xit = (t >> 1);
+ *v0 = xit + r; /* v0 = round(x/(2*PARAM_Q)) */
+
+ t -= 1;
+ r = t & 1;
+ *v1 = (t >> 1) + r;
+
+ return abs_32(x - ((*v0) * 2 * PARAM_Q));
+}
+
+static int32_t g(int32_t x) {
+ int32_t t, c, b;
+
+ /* Next 6 lines compute t = x/(4*PARAM_Q); */
+ b = x * 2730;
+ t = b >> 27;
+ b = x - t * 49156;
+ b = 49155 - b;
+ b >>= 31;
+ t -= b;
+
+ c = t & 1;
+ t = (t >> 1) + c; /* t = round(x/(8*PARAM_Q)) */
+
+ t *= 8 * PARAM_Q;
+
+ return abs_32(t - x);
+}
+
+static int16_t LDDecode(int32_t xi0, int32_t xi1, int32_t xi2, int32_t xi3) {
+ int32_t t;
+
+ t = g(xi0);
+ t += g(xi1);
+ t += g(xi2);
+ t += g(xi3);
+
+ t -= 8 * PARAM_Q;
+ t >>= 31;
+ return t & 1;
+}
+
+void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v) {
+ int32_t v0[4], v1[4], v_tmp[4], k;
+ uint8_t rbit;
+ uint8_t rand[32];
+ unsigned i;
+
+ /* The reference implementation calls ChaCha20 here. */
+ RAND_bytes(rand, sizeof(rand));
+
+ for (i = 0; i < 256; i++) {
+ rbit = (rand[i >> 3] >> (i & 7)) & 1;
+
+ k = f(v0 + 0, v1 + 0, 8 * v->coeffs[0 + i] + 4 * rbit);
+ k += f(v0 + 1, v1 + 1, 8 * v->coeffs[256 + i] + 4 * rbit);
+ k += f(v0 + 2, v1 + 2, 8 * v->coeffs[512 + i] + 4 * rbit);
+ k += f(v0 + 3, v1 + 3, 8 * v->coeffs[768 + i] + 4 * rbit);
+
+ k = (2 * PARAM_Q - 1 - k) >> 31;
+
+ v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]);
+ v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]);
+ v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]);
+ v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]);
+
+ c->coeffs[0 + i] = (v_tmp[0] - v_tmp[3]) & 3;
+ c->coeffs[256 + i] = (v_tmp[1] - v_tmp[3]) & 3;
+ c->coeffs[512 + i] = (v_tmp[2] - v_tmp[3]) & 3;
+ c->coeffs[768 + i] = (-k + 2 * v_tmp[3]) & 3;
+ }
+}
+
+void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v,
+ const NEWHOPE_POLY* c) {
+ int i;
+ int32_t tmp[4];
+
+ memset(key, 0, KEY_LENGTH);
+
+ for (i = 0; i < 256; i++) {
+ tmp[0] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[0 + i] -
+ PARAM_Q * (2 * c->coeffs[0 + i] + c->coeffs[768 + i]);
+ tmp[1] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[256 + i] -
+ PARAM_Q * (2 * c->coeffs[256 + i] + c->coeffs[768 + i]);
+ tmp[2] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[512 + i] -
+ PARAM_Q * (2 * c->coeffs[512 + i] + c->coeffs[768 + i]);
+ tmp[3] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[768 + i] -
+ PARAM_Q * (c->coeffs[768 + i]);
+
+ key[i >> 3] |= LDDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7);
+ }
+}
diff --git a/src/crypto/newhope/internal.h b/src/crypto/newhope/internal.h
new file mode 100644
index 00000000..a5473d8e
--- /dev/null
+++ b/src/crypto/newhope/internal.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_NEWHOPE_INTERNAL_H
+#define OPENSSL_HEADER_NEWHOPE_INTERNAL_H
+
+#include <openssl/newhope.h>
+#include <openssl/sha.h>
+
+#include "../internal.h"
+
+
+/* The number of polynomial coefficients. */
+#define PARAM_N 1024
+
+/* The width the noise distribution. */
+#define PARAM_K 16
+
+/* Modulus. */
+#define PARAM_Q 12289
+
+/* KEY_LENGTH is the size of the result of the key agreement. This result is
+ * not exposed to callers: instead, it is whitened with SHA-256, whose output
+ * happens to be the same size. */
+#define KEY_LENGTH 32
+
+/* Polynomial coefficients in unpacked form. */
+struct newhope_poly_st {
+ alignas(32) uint16_t coeffs[PARAM_N];
+};
+
+/* The packed form is 14 bits per coefficient, or 1792 bytes. */
+#define POLY_BYTES ((1024 * 14) / 8)
+
+/* SEED_LENGTH is the length of the AES-CTR seed used to derive a polynomial. */
+#define SEED_LENGTH 32
+
+/* newhope_poly_uniform generates the polynomial |a| using AES-CTR mode with the
+ * seed
+ * |seed|. (In the reference implementation this was done with SHAKE-128.) */
+void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed);
+
+/* newhope_poly_getnoise sets |r| to a random polynomial where the coefficients
+ * are
+ * sampled from the noise distribution. (In the reference implementation, this
+ * is given a random seed and a nonce.)*/
+void newhope_poly_getnoise(NEWHOPE_POLY* r);
+
+/* newhope_poly_frombytes unpacks the packed polynomial coefficients in |a| into
+ * |r|. */
+void newhope_poly_frombytes(NEWHOPE_POLY* r, const uint8_t* a);
+
+/* newhope_poly_tobytes packs the polynomial |p| into the compact representation
+ * |r|. */
+void newhope_poly_tobytes(uint8_t* r, const NEWHOPE_POLY* p);
+
+void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v);
+
+/* newhope_reconcile performs the error-reconciliation step using the input |v|
+ * and
+ * reconciliation data |c|, writing the resulting key to |key|. */
+void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v,
+ const NEWHOPE_POLY* c);
+
+/* newhope_poly_ntt performs NTT(r) in-place. */
+void newhope_poly_ntt(NEWHOPE_POLY* r);
+
+/* newhope_poly_invntt performs the inverse of NTT(r) in-place. */
+void newhope_poly_invntt(NEWHOPE_POLY* r);
+
+void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b);
+void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b);
+
+uint16_t newhope_montgomery_reduce(uint32_t a);
+uint16_t newhope_barrett_reduce(uint16_t a);
+
+void newhope_bitrev_vector(uint16_t* poly);
+void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors);
+void newhope_ntt(uint16_t* poly, const uint16_t* omegas);
+
+
+#endif /* OPENSSL_HEADER_NEWHOPE_INTERNAL_H */
diff --git a/src/crypto/newhope/newhope.c b/src/crypto/newhope/newhope.c
new file mode 100644
index 00000000..29e189f0
--- /dev/null
+++ b/src/crypto/newhope/newhope.c
@@ -0,0 +1,160 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+NEWHOPE_POLY *NEWHOPE_POLY_new(void) {
+ return (NEWHOPE_POLY *)OPENSSL_malloc(sizeof(NEWHOPE_POLY));
+}
+
+void NEWHOPE_POLY_free(NEWHOPE_POLY *p) { OPENSSL_free(p); }
+
+/* Encodes reconciliation data from |c| into |r|. */
+static void encode_rec(const NEWHOPE_POLY *c, uint8_t *r) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ r[i] = c->coeffs[4 * i] | (c->coeffs[4 * i + 1] << 2) |
+ (c->coeffs[4 * i + 2] << 4) | (c->coeffs[4 * i + 3] << 6);
+ }
+}
+
+/* Decodes reconciliation data from |r| into |c|. */
+static void decode_rec(const uint8_t *r, NEWHOPE_POLY *c) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ c->coeffs[4 * i + 0] = r[i] & 0x03;
+ c->coeffs[4 * i + 1] = (r[i] >> 2) & 0x03;
+ c->coeffs[4 * i + 2] = (r[i] >> 4) & 0x03;
+ c->coeffs[4 * i + 3] = (r[i] >> 6);
+ }
+}
+
+void NEWHOPE_keygen(uint8_t *servermsg, NEWHOPE_POLY *sk) {
+ newhope_poly_getnoise(sk);
+ newhope_poly_ntt(sk);
+
+ /* The first part of the server's message is the seed, which compactly encodes
+ * a. */
+ NEWHOPE_POLY a;
+ uint8_t *seed = &servermsg[POLY_BYTES];
+ RAND_bytes(seed, SEED_LENGTH);
+ newhope_poly_uniform(&a, seed);
+
+ NEWHOPE_POLY e;
+ newhope_poly_getnoise(&e);
+ newhope_poly_ntt(&e);
+
+ /* The second part of the server's message is the polynomial pk = a*sk+e */
+ NEWHOPE_POLY r, pk;
+ newhope_poly_pointwise(&r, sk, &a);
+ newhope_poly_add(&pk, &e, &r);
+ newhope_poly_tobytes(servermsg, &pk);
+}
+
+int NEWHOPE_client_compute_key(
+ uint8_t key[SHA256_DIGEST_LENGTH],
+ uint8_t clientmsg[NEWHOPE_CLIENTMSG_LENGTH],
+ const uint8_t servermsg[NEWHOPE_SERVERMSG_LENGTH], size_t msg_len) {
+ if (msg_len != NEWHOPE_SERVERMSG_LENGTH) {
+ return 0;
+ }
+
+ NEWHOPE_POLY sp;
+ newhope_poly_getnoise(&sp);
+ newhope_poly_ntt(&sp);
+
+ /* The first part of the client's message is the polynomial bp=e'+a*s' */
+ {
+ NEWHOPE_POLY ep;
+ newhope_poly_getnoise(&ep);
+ newhope_poly_ntt(&ep);
+
+ /* Generate the same |a| as the server, from the server's seed. */
+ NEWHOPE_POLY a;
+ const uint8_t *seed = &servermsg[POLY_BYTES];
+ newhope_poly_uniform(&a, seed);
+
+ NEWHOPE_POLY bp;
+ newhope_poly_pointwise(&bp, &a, &sp);
+ newhope_poly_add(&bp, &bp, &ep);
+ newhope_poly_tobytes(clientmsg, &bp);
+ }
+
+ /* v = pk * s' + e'' */
+ NEWHOPE_POLY v;
+ {
+ NEWHOPE_POLY pk;
+ newhope_poly_frombytes(&pk, servermsg);
+
+ NEWHOPE_POLY epp;
+ newhope_poly_getnoise(&epp);
+
+ newhope_poly_pointwise(&v, &pk, &sp);
+ newhope_poly_invntt(&v);
+ newhope_poly_add(&v, &v, &epp);
+ }
+
+ /* The second part of the client's message is the reconciliation data derived
+ * from v. */
+ NEWHOPE_POLY c;
+ uint8_t *reconciliation = &clientmsg[POLY_BYTES];
+ newhope_helprec(&c, &v);
+ encode_rec(&c, reconciliation);
+
+ uint8_t k[KEY_LENGTH];
+ newhope_reconcile(k, &v, &c);
+ SHA256_CTX ctx;
+ if (!SHA256_Init(&ctx) ||
+ !SHA256_Update(&ctx, k, KEY_LENGTH) ||
+ !SHA256_Final(key, &ctx)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int NEWHOPE_server_compute_key(
+ uint8_t key[SHA256_DIGEST_LENGTH], const NEWHOPE_POLY *sk,
+ const uint8_t clientmsg[NEWHOPE_CLIENTMSG_LENGTH], size_t msg_len) {
+ if (msg_len != NEWHOPE_CLIENTMSG_LENGTH) {
+ return 0;
+ }
+ NEWHOPE_POLY bp;
+ newhope_poly_frombytes(&bp, clientmsg);
+
+ NEWHOPE_POLY v;
+ newhope_poly_pointwise(&v, sk, &bp);
+ newhope_poly_invntt(&v);
+
+ NEWHOPE_POLY c;
+ const uint8_t *reconciliation = &clientmsg[POLY_BYTES];
+ decode_rec(reconciliation, &c);
+
+ uint8_t k[KEY_LENGTH];
+ newhope_reconcile(k, &v, &c);
+ SHA256_CTX ctx;
+ if (!SHA256_Init(&ctx) ||
+ !SHA256_Update(&ctx, k, KEY_LENGTH) ||
+ !SHA256_Final(key, &ctx)) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/newhope/newhope_test.c b/src/crypto/newhope/newhope_test.c
new file mode 100644
index 00000000..5d960072
--- /dev/null
+++ b/src/crypto/newhope/newhope_test.c
@@ -0,0 +1,144 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+#define NTESTS 1000
+
+static int test_keys(void) {
+ NEWHOPE_POLY *sk = NEWHOPE_POLY_new();
+ uint8_t server_key[SHA256_DIGEST_LENGTH], client_key[SHA256_DIGEST_LENGTH];
+ uint8_t servermsg[NEWHOPE_SERVERMSG_LENGTH];
+ uint8_t clientmsg[NEWHOPE_CLIENTMSG_LENGTH];
+ int i;
+
+ for (i = 0; i < NTESTS; i++) {
+ /* Alice generates a public key */
+ NEWHOPE_keygen(servermsg, sk);
+
+ /* Bob derives a secret key and creates a response */
+ if (!NEWHOPE_client_compute_key(client_key, clientmsg, servermsg,
+ sizeof(servermsg))) {
+ fprintf(stderr, "ERROR client key exchange failed\n");
+ return 0;
+ }
+
+ /* Alice uses Bob's response to get her secret key */
+ if (!NEWHOPE_server_compute_key(server_key, sk, clientmsg,
+ sizeof(clientmsg))) {
+ fprintf(stderr, "ERROR server key exchange failed\n");
+ return 0;
+ }
+
+ if (memcmp(server_key, client_key, SHA256_DIGEST_LENGTH) != 0) {
+ fprintf(stderr, "ERROR keys did not agree\n");
+ return 0;
+ }
+ }
+
+ NEWHOPE_POLY_free(sk);
+ return 1;
+}
+
+static int test_invalid_sk_a(void) {
+ NEWHOPE_POLY *sk = NEWHOPE_POLY_new();
+ uint8_t server_key[SHA256_DIGEST_LENGTH], client_key[SHA256_DIGEST_LENGTH];
+ uint8_t servermsg[NEWHOPE_SERVERMSG_LENGTH];
+ uint8_t clientmsg[NEWHOPE_CLIENTMSG_LENGTH];
+ int i;
+
+ for (i = 0; i < NTESTS; i++) {
+ /* Alice generates a public key */
+ NEWHOPE_keygen(servermsg, sk);
+
+ /* Bob derives a secret key and creates a response */
+ if (!NEWHOPE_client_compute_key(client_key, clientmsg, servermsg,
+ sizeof(servermsg))) {
+ fprintf(stderr, "ERROR client key exchange failed\n");
+ return 0;
+ }
+
+ /* Corrupt the secret key */
+ NEWHOPE_keygen(servermsg /* not used below */, sk);
+
+ /* Alice uses Bob's response to get her secret key */
+ if (!NEWHOPE_server_compute_key(server_key, sk, clientmsg,
+ sizeof(clientmsg))) {
+ fprintf(stderr, "ERROR server key exchange failed\n");
+ return 0;
+ }
+
+ if (memcmp(server_key, client_key, SHA256_DIGEST_LENGTH) == 0) {
+ fprintf(stderr, "ERROR invalid sk_a\n");
+ return 0;
+ }
+ }
+
+ NEWHOPE_POLY_free(sk);
+ return 1;
+}
+
+static int test_invalid_ciphertext(void) {
+ NEWHOPE_POLY *sk = NEWHOPE_POLY_new();
+ uint8_t server_key[SHA256_DIGEST_LENGTH], client_key[SHA256_DIGEST_LENGTH];
+ uint8_t servermsg[NEWHOPE_SERVERMSG_LENGTH];
+ uint8_t clientmsg[NEWHOPE_CLIENTMSG_LENGTH];
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ /* Alice generates a public key */
+ NEWHOPE_keygen(servermsg, sk);
+
+ /* Bob derives a secret key and creates a response */
+ if (!NEWHOPE_client_compute_key(client_key, clientmsg, servermsg,
+ sizeof(servermsg))) {
+ fprintf(stderr, "ERROR client key exchange failed\n");
+ return 0;
+ }
+
+ /* Change some byte in the "ciphertext" */
+ clientmsg[42] ^= 1;
+
+ /* Alice uses Bob's response to get her secret key */
+ if (!NEWHOPE_server_compute_key(server_key, sk, clientmsg,
+ sizeof(clientmsg))) {
+ fprintf(stderr, "ERROR server key exchange failed\n");
+ return 0;
+ }
+
+ if (!memcmp(server_key, client_key, SHA256_DIGEST_LENGTH)) {
+ fprintf(stderr, "ERROR invalid clientmsg\n");
+ return 0;
+ }
+ }
+
+ NEWHOPE_POLY_free(sk);
+ return 1;
+}
+
+int main(void) {
+ if (!test_keys() || !test_invalid_sk_a() || !test_invalid_ciphertext()) {
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/newhope/ntt.c b/src/crypto/newhope/ntt.c
new file mode 100644
index 00000000..163a9d1a
--- /dev/null
+++ b/src/crypto/newhope/ntt.c
@@ -0,0 +1,148 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+static uint16_t bitrev_table[1024] = {
+ 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704,
+ 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864,
+ 224, 736, 480, 992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592,
+ 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944,
+ 112, 624, 368, 880, 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648,
+ 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808,
+ 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, 24, 536,
+ 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984,
+ 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760,
+ 504, 1016, 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836,
+ 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612,
+ 356, 868, 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916,
+ 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692,
+ 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, 12, 524, 268, 780,
+ 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556,
+ 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004,
+ 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732,
+ 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892,
+ 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, 66, 578,
+ 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930,
+ 98, 610, 354, 866, 226, 738, 482, 994, 18, 530, 274, 786, 146, 658,
+ 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818,
+ 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522,
+ 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970,
+ 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746,
+ 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858,
+ 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634,
+ 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134, 646, 390, 902,
+ 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678,
+ 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790,
+ 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566,
+ 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014,
+ 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718,
+ 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878,
+ 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94, 606,
+ 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958,
+ 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129, 641,
+ 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801,
+ 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529,
+ 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977,
+ 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753,
+ 497, 1009, 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841,
+ 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617,
+ 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921,
+ 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697,
+ 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773,
+ 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549,
+ 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997,
+ 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725,
+ 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885,
+ 245, 757, 501, 1013, 13, 525, 269, 781, 141, 653, 397, 909, 77, 589,
+ 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941,
+ 109, 621, 365, 877, 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669,
+ 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829,
+ 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, 3, 515,
+ 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963,
+ 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739,
+ 483, 995, 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851,
+ 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627,
+ 371, 883, 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907,
+ 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683,
+ 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, 27, 539, 283, 795,
+ 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571,
+ 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019,
+ 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711,
+ 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871,
+ 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, 87, 599,
+ 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951,
+ 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271, 783, 143, 655,
+ 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815,
+ 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543,
+ 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991,
+ 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767,
+ 511, 1023};
+
+void newhope_bitrev_vector(uint16_t* poly) {
+ unsigned int i, r;
+ uint16_t tmp;
+
+ for (i = 0; i < PARAM_N; i++) {
+ r = bitrev_table[i];
+ if (i < r) {
+ tmp = poly[i];
+ poly[i] = poly[r];
+ poly[r] = tmp;
+ }
+ }
+}
+
+void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors) {
+ unsigned int i;
+
+ for (i = 0; i < PARAM_N; i++) {
+ poly[i] = newhope_montgomery_reduce((poly[i] * factors[i]));
+ }
+}
+
+/* GS_bo_to_no; omegas need to be in Montgomery domain */
+void newhope_ntt(uint16_t* a, const uint16_t* omega) {
+ int i, start, j, jTwiddle, distance;
+ uint16_t temp, W;
+
+ for (i = 0; i < 10; i += 2) {
+ /* Even level */
+ distance = (1 << i);
+ for (start = 0; start < distance; start++) {
+ jTwiddle = 0;
+ for (j = start; j < PARAM_N - 1; j += 2 * distance) {
+ W = omega[jTwiddle++];
+ temp = a[j];
+ a[j] = (temp + a[j + distance]); /* Omit reduction (be lazy) */
+ a[j + distance] = newhope_montgomery_reduce(
+ (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance])));
+ }
+ }
+
+ /* Odd level */
+ distance <<= 1;
+ for (start = 0; start < distance; start++) {
+ jTwiddle = 0;
+ for (j = start; j < PARAM_N - 1; j += 2 * distance) {
+ W = omega[jTwiddle++];
+ temp = a[j];
+ a[j] = newhope_barrett_reduce((temp + a[j + distance]));
+ a[j + distance] = newhope_montgomery_reduce(
+ (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance])));
+ }
+ }
+ }
+}
diff --git a/src/crypto/newhope/poly.c b/src/crypto/newhope/poly.c
new file mode 100644
index 00000000..a9839faf
--- /dev/null
+++ b/src/crypto/newhope/poly.c
@@ -0,0 +1,183 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+extern uint16_t newhope_omegas_montgomery[];
+extern uint16_t newhope_omegas_inv_montgomery[];
+
+extern uint16_t newhope_psis_bitrev_montgomery[];
+extern uint16_t newhope_psis_inv_montgomery[];
+
+void newhope_poly_frombytes(NEWHOPE_POLY* r, const uint8_t* a) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ r->coeffs[4 * i + 0] =
+ a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8);
+ r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) |
+ (((uint16_t)a[7 * i + 2]) << 2) |
+ (((uint16_t)a[7 * i + 3] & 0x0f) << 10);
+ r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) |
+ (((uint16_t)a[7 * i + 4]) << 4) |
+ (((uint16_t)a[7 * i + 5] & 0x03) << 12);
+ r->coeffs[4 * i + 3] =
+ (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6);
+ }
+}
+
+void newhope_poly_tobytes(uint8_t* r, const NEWHOPE_POLY* p) {
+ int i;
+ uint16_t t0, t1, t2, t3, m;
+ int16_t c;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ t0 = newhope_barrett_reduce(
+ p->coeffs[4 * i + 0]); /* Make sure that coefficients
+ have only 14 bits */
+ t1 = newhope_barrett_reduce(p->coeffs[4 * i + 1]);
+ t2 = newhope_barrett_reduce(p->coeffs[4 * i + 2]);
+ t3 = newhope_barrett_reduce(p->coeffs[4 * i + 3]);
+
+ m = t0 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t0 = m ^ ((t0 ^ m) & c); /* Make sure that coefficients are in [0,q] */
+
+ m = t1 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t1 = m ^ ((t1 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
+
+ m = t2 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t2 = m ^ ((t2 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
+
+ m = t3 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t3 = m ^ ((t3 ^ m) & c); /* Make sure that coefficients are in [0,q] */
+
+ r[7 * i + 0] = t0 & 0xff;
+ r[7 * i + 1] = (t0 >> 8) | (t1 << 6);
+ r[7 * i + 2] = (t1 >> 2);
+ r[7 * i + 3] = (t1 >> 10) | (t2 << 4);
+ r[7 * i + 4] = (t2 >> 4);
+ r[7 * i + 5] = (t2 >> 12) | (t3 << 2);
+ r[7 * i + 6] = (t3 >> 6);
+ }
+}
+
+void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed) {
+/* The reference implementation uses SHAKE-128 here; this implementation uses
+ * AES-CTR. Use half the seed for the initialization vector and half for the
+ * key. */
+#if SEED_LENGTH != 2 * AES_BLOCK_SIZE
+#error "2 * seed length != AES_BLOCK_SIZE"
+#endif
+ uint8_t ivec[AES_BLOCK_SIZE];
+ memcpy(ivec, &seed[SEED_LENGTH / 2], SEED_LENGTH / 2);
+ AES_KEY key;
+ AES_set_encrypt_key(seed, 8 * SEED_LENGTH / 2, &key);
+
+ /* AES state. */
+ uint8_t ecount[AES_BLOCK_SIZE];
+ memset(ecount, 0, AES_BLOCK_SIZE);
+
+ /* Encrypt a block of zeros just to get the random bytes. With luck, 2688
+ * bytes is enough. */
+ uint8_t buf[AES_BLOCK_SIZE * 168];
+ memset(buf, 0, sizeof(buf));
+
+ unsigned int block_num = 0;
+ AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
+
+ size_t pos = 0, coeff_num = 0;
+ while (coeff_num < PARAM_N) {
+ /* Specialized for q = 12889 */
+ uint16_t val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x3fff;
+ if (val < PARAM_Q) {
+ a->coeffs[coeff_num++] = val;
+ }
+
+ pos += 2;
+ if (pos > sizeof(buf) - 2) {
+ memset(buf, 0, sizeof(buf));
+ AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
+ pos = 0;
+ }
+ }
+}
+
+void newhope_poly_getnoise(NEWHOPE_POLY* r) {
+#if PARAM_K != 16
+#error "poly_getnoise in poly.c only supports k=16"
+#endif
+
+ uint32_t tp[PARAM_N];
+
+ /* The reference implementation calls ChaCha20 here. */
+ RAND_bytes((uint8_t *) tp, sizeof(tp));
+
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ const uint32_t t = tp[i];
+
+ size_t j;
+ uint32_t d = 0;
+ for (j = 0; j < 8; j++) {
+ d += (t >> j) & 0x01010101;
+ }
+
+ const uint32_t a = ((d >> 8) & 0xff) + (d & 0xff);
+ const uint32_t b = (d >> 24) + ((d >> 16) & 0xff);
+ r->coeffs[i] = a + PARAM_Q - b;
+ }
+}
+
+void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b) {
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ uint16_t t = newhope_montgomery_reduce(3186 * b->coeffs[i]);
+ /* t is now in Montgomery domain */
+ r->coeffs[i] = newhope_montgomery_reduce(a->coeffs[i] * t);
+ /* r->coeffs[i] is back in normal domain */
+ }
+}
+
+void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b) {
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ r->coeffs[i] = newhope_barrett_reduce(a->coeffs[i] + b->coeffs[i]);
+ }
+}
+
+void newhope_poly_ntt(NEWHOPE_POLY* r) {
+ newhope_mul_coefficients(r->coeffs, newhope_psis_bitrev_montgomery);
+ newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_montgomery);
+}
+
+void newhope_poly_invntt(NEWHOPE_POLY* r) {
+ newhope_bitrev_vector(r->coeffs);
+ newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_inv_montgomery);
+ newhope_mul_coefficients(r->coeffs, newhope_psis_inv_montgomery);
+}
diff --git a/src/crypto/newhope/precomp.c b/src/crypto/newhope/precomp.c
new file mode 100644
index 00000000..d0c478ee
--- /dev/null
+++ b/src/crypto/newhope/precomp.c
@@ -0,0 +1,306 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+uint16_t newhope_omegas_montgomery[PARAM_N / 2] = {
+ 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041,
+ 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118,
+ 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973,
+ 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930,
+ 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643,
+ 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605,
+ 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080,
+ 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142,
+ 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968,
+ 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821,
+ 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874,
+ 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281,
+ 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453,
+ 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030,
+ 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939,
+ 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706,
+ 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+ 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459,
+ 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065,
+ 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922,
+ 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948,
+ 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992,
+ 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106,
+ 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969,
+ 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553,
+ 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088,
+ 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479,
+ 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961,
+ 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744,
+ 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374,
+ 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011,
+ 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791,
+ 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755,
+ 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637,
+ 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207,
+ 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952,
+ 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+ 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045,
+ 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516,
+ 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714,
+ 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618,
+ 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730,
+ 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686,
+ 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863,
+ 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852,
+ 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364,
+ 3271, 4057, 4414, 9442, 7917, 2174};
+
+uint16_t newhope_omegas_inv_montgomery[PARAM_N / 2] = {
+ 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278,
+ 9945, 3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749,
+ 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090,
+ 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427,
+ 7341, 6152, 10561, 400, 8410, 1922, 2033, 8291, 1359, 6854, 11035,
+ 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, 52, 3174,
+ 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332,
+ 9450, 10162, 151, 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369,
+ 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, 885, 6281, 10333,
+ 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438,
+ 4212, 11314, 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507,
+ 5886, 3029, 6695, 4213, 504, 11684, 2302, 1962, 1594, 6328, 7183,
+ 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297,
+ 6170, 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341,
+ 11964, 10885, 6299, 1159, 8240, 8561, 11177, 2078, 10331, 4322, 11367,
+ 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224,
+ 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830,
+ 683, 1566, 5782, 9786, 9341, 12115, 723, 3009, 1693, 5735, 2655,
+ 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, 1583,
+ 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350,
+ 6920, 10232, 4493, 9087, 8855, 8760, 9381, 218, 9928, 10446, 9259,
+ 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, 6381, 11836,
+ 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008,
+ 5876, 5333, 10258, 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689,
+ 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, 3, 4437, 160,
+ 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635,
+ 10512, 1663, 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882,
+ 3186, 10659, 10163, 1153, 9405, 8241, 10040, 2178, 1544, 5559, 420,
+ 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243,
+ 3016, 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146,
+ 10752, 242, 2678, 3704, 11744, 5019, 3833, 3778, 11899, 773, 5101,
+ 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859,
+ 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437,
+ 3646, 2566, 10102, 9867, 6250, 5444, 2381, 11796, 8193, 4337, 11854,
+ 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, 2548,
+ 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459,
+ 2731, 8357, 6378, 7399, 10861, 1696, 9863, 334, 7657, 6534, 11029,
+ 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, 6498, 544,
+ 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177,
+ 8705, 9764, 1381, 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837,
+ 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, 3006, 9545, 563,
+ 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512,
+ 1351, 7311, 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545,
+ 3621, 8747, 8785, 1646, 1212, 5860, 3195, 7203, 10963, 3201, 3014,
+ 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995,
+ 11227, 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289,
+ 9198, 12208, 2963, 7393, 2366, 9238};
+
+uint16_t newhope_psis_bitrev_montgomery[PARAM_N] = {
+ 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041,
+ 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118,
+ 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973,
+ 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930,
+ 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643,
+ 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605,
+ 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080,
+ 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142,
+ 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968,
+ 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821,
+ 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874,
+ 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281,
+ 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453,
+ 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030,
+ 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939,
+ 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706,
+ 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+ 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459,
+ 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065,
+ 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922,
+ 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948,
+ 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992,
+ 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106,
+ 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969,
+ 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553,
+ 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088,
+ 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479,
+ 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961,
+ 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744,
+ 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374,
+ 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011,
+ 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791,
+ 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755,
+ 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637,
+ 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207,
+ 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952,
+ 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+ 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045,
+ 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516,
+ 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714,
+ 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618,
+ 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730,
+ 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686,
+ 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863,
+ 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852,
+ 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364,
+ 3271, 4057, 4414, 9442, 7917, 2174, 3947, 11951, 2455, 6599, 10545,
+ 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522,
+ 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624,
+ 10397, 1325, 6565, 1945, 11260, 10077, 2674, 3338, 3276, 11034, 506,
+ 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, 9489,
+ 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914,
+ 425, 10453, 392, 10104, 8464, 4235, 8761, 7376, 2291, 3375, 7954,
+ 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, 6825, 7383,
+ 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485,
+ 1403, 5189, 6094, 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882,
+ 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, 11232, 2600, 7584,
+ 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261,
+ 2360, 11925, 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581,
+ 3238, 8840, 1136, 9363, 1826, 3171, 4489, 7885, 346, 2068, 1389,
+ 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125,
+ 11749, 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343,
+ 1908, 4538, 10423, 7078, 4727, 1208, 11572, 3589, 2982, 1373, 1721,
+ 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218,
+ 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566,
+ 5836, 12229, 2717, 1535, 3200, 5588, 5845, 412, 5102, 7326, 3744,
+ 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, 1518,
+ 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495,
+ 8328, 8755, 8144, 10533, 5966, 12077, 9175, 9520, 5596, 6302, 8400,
+ 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, 9068, 8016,
+ 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207,
+ 4050, 7087, 844, 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633,
+ 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, 2213, 8136, 3805,
+ 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154,
+ 4360, 3285, 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105,
+ 3120, 6643, 6203, 8536, 8348, 6919, 3536, 9199, 10891, 11463, 5043,
+ 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806,
+ 6586, 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684,
+ 12226, 7154, 9916, 7302, 8481, 3670, 11066, 2334, 1590, 7878, 10734,
+ 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996,
+ 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371,
+ 12265, 2485, 11385, 5039, 6742, 8449, 1842, 12217, 8176, 9577, 4834,
+ 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, 5406,
+ 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038,
+ 11249, 2035, 6125, 10407, 4565, 7315, 5078, 10506, 2840, 2478, 9270,
+ 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, 1734, 3815,
+ 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173,
+ 189, 10080, 10526, 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530,
+ 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, 3454, 3758, 7899,
+ 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988,
+ 8, 457, 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462,
+ 2873, 9855, 11498, 2535, 11169, 5808, 12268, 9687, 1901, 7171, 11787,
+ 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263,
+ 2929};
+
+uint16_t newhope_psis_inv_montgomery[PARAM_N] = {
+ 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000,
+ 2327, 2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173,
+ 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525,
+ 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207,
+ 5582, 2553, 7387, 6322, 9681, 1383, 10731, 1533, 219, 5298, 4268,
+ 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, 11387, 8649,
+ 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164,
+ 4106, 11120, 12122, 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928,
+ 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, 1991, 2040, 2047,
+ 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422,
+ 6327, 4415, 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228,
+ 2931, 7441, 1063, 3663, 5790, 9605, 10150, 1450, 8985, 11817, 10466,
+ 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367,
+ 7789, 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566,
+ 11900, 1700, 3754, 5803, 829, 1874, 7290, 2797, 10933, 5073, 7747,
+ 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734,
+ 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401,
+ 1343, 3703, 529, 10609, 12049, 6988, 6265, 895, 3639, 4031, 4087,
+ 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, 10220,
+ 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379,
+ 11159, 10372, 8504, 4726, 9453, 3106, 7466, 11600, 10435, 8513, 9994,
+ 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, 5616, 6069,
+ 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794,
+ 9177, 1311, 5454, 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531,
+ 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, 7386, 9833, 8427,
+ 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474,
+ 10744, 5046, 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118,
+ 8182, 4680, 11202, 6867, 981, 8918, 1274, 182, 26, 7026, 8026,
+ 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454,
+ 3249, 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218,
+ 6155, 6146, 878, 1881, 7291, 11575, 12187, 1741, 7271, 8061, 11685,
+ 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063,
+ 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248,
+ 4118, 5855, 2592, 5637, 6072, 2623, 7397, 8079, 9932, 4930, 5971,
+ 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, 11792,
+ 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499,
+ 4011, 573, 3593, 5780, 7848, 9899, 10192, 1456, 208, 7052, 2763,
+ 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, 7841, 9898,
+ 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588,
+ 84, 12, 7024, 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457,
+ 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, 12216, 10523, 6770,
+ 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406,
+ 8366, 9973, 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901,
+ 6824, 4486, 4152, 9371, 8361, 2950, 2177, 311, 1800, 9035, 8313,
+ 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414,
+ 7510, 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815,
+ 10180, 6721, 9738, 10169, 8475, 8233, 9954, 1422, 8981, 1283, 5450,
+ 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704,
+ 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500,
+ 1500, 5481, 783, 3623, 11051, 8601, 8251, 8201, 11705, 10450, 5004,
+ 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, 1514,
+ 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185,
+ 5436, 11310, 8638, 1234, 5443, 11311, 5127, 2488, 2111, 10835, 5059,
+ 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, 6849, 2734,
+ 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786,
+ 7706, 4612, 4170, 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733,
+ 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, 618, 5355, 765,
+ 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266,
+ 12000, 6981, 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165,
+ 9230, 11852, 10471, 5007, 5982, 11388, 5138, 734, 3616, 11050, 12112,
+ 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480,
+ 6621, 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605,
+ 515, 10607, 6782, 4480, 640, 1847, 3775, 5806, 2585, 5636, 9583,
+ 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421,
+ 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708,
+ 11206, 5112, 5997, 7879, 11659, 12199, 8765, 10030, 4944, 5973, 6120,
+ 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, 8394,
+ 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742,
+ 106, 8793, 10034, 3189, 10989, 5081, 4237, 5872, 4350, 2377, 10873,
+ 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, 2453, 2106,
+ 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262,
+ 4120, 11122, 5100, 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930,
+ 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, 4027, 5842, 11368,
+ 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797,
+ 3625, 4029, 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093,
+ 12261, 12285, 1755, 7273, 1039, 1904, 272, 3550, 9285, 3082, 5707,
+ 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936,
+ 848, 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961,
+ 5404, 772, 5377, 9546, 8386, 1198, 8949, 3034, 2189, 7335, 4559,
+ 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518,
+ 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151,
+ 1593, 10761, 6804, 972, 3650, 2277, 5592, 4310, 7638, 9869, 4921,
+ 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, 6376,
+ 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721,
+ 12065, 12257, 1751, 9028, 8312, 2943, 2176, 3822, 546, 78, 8789,
+ 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, 613, 10621,
+ 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688,
+ 6365, 6176, 6149, 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894,
+ 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, 7489, 4581, 2410,
+ 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185,
+ 455, 65, 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501,
+ 5624, 2559, 10899, 1557, 1978, 10816, 10323, 8497, 4725, 675, 1852,
+ 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034,
+ 10497};
diff --git a/src/crypto/newhope/reduce.c b/src/crypto/newhope/reduce.c
new file mode 100644
index 00000000..e7f13649
--- /dev/null
+++ b/src/crypto/newhope/reduce.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+/* Incomplete-reduction routines; for details on allowed input ranges
+ * and produced output ranges, see the description in the paper:
+ * https://cryptojedi.org/papers/#newhope */
+
+static const uint32_t kQInv = 12287; /* -inverse_mod(p,2^18) */
+static const uint32_t kRLog = 18;
+
+uint16_t newhope_montgomery_reduce(uint32_t a) {
+ uint32_t u;
+
+ u = (a * kQInv);
+ u &= ((1 << kRLog) - 1);
+ u *= PARAM_Q;
+ a = a + u;
+ return a >> 18;
+}
+
+uint16_t newhope_barrett_reduce(uint16_t a) {
+ uint32_t u;
+
+ u = ((uint32_t)a * 5) >> 16;
+ u *= PARAM_Q;
+ a -= u;
+ return a;
+}
diff --git a/src/crypto/obj/CMakeLists.txt b/src/crypto/obj/CMakeLists.txt
index b8a4ef37..f49d499d 100644
--- a/src/crypto/obj/CMakeLists.txt
+++ b/src/crypto/obj/CMakeLists.txt
@@ -8,3 +8,14 @@ add_library(
obj.c
obj_xref.c
)
+
+add_executable(
+ obj_test
+
+ obj_test.cc
+
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(obj_test crypto)
+add_dependencies(all_tests obj_test)
diff --git a/src/crypto/obj/README b/src/crypto/obj/README
index 8826e598..6199fb4b 100644
--- a/src/crypto/obj/README
+++ b/src/crypto/obj/README
@@ -1,17 +1,17 @@
OID information is generated via a series of perl scripts. In order, the full
list of commands to run are:
- perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h
- perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h
+ perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h
+ perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h
perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h
objects.txt contains the list of all built-in OIDs. It is processed by
-objects.pl to output obj_mac.num and obj_mac.h. obj_mac.num is the list of NID
+objects.pl to output obj_mac.num and nid.h. obj_mac.num is the list of NID
values for each OID. This is an input/output parameter so NID values are stable
-across regenerations. obj_mac.h is the header which defines macros for all the
+across regenerations. nid.h is the header which defines macros for all the
built-in OIDs in C.
-obj_mac.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
+nid.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables
for search by short name, OID, etc.
@@ -28,7 +28,7 @@ Dependency graph:
[objects.pl] <--+
/ \ |
V V |
- obj_mac.h obj_mac.num obj_xref.txt
+ nid.h obj_mac.num obj_xref.txt
| \ /
V V V
[obj_dat.pl] [obj_xref.pl]
diff --git a/src/crypto/obj/obj_dat.h b/src/crypto/obj/obj_dat.h
index bf44c6d9..1d779de6 100644
--- a/src/crypto/obj/obj_dat.h
+++ b/src/crypto/obj/obj_dat.h
@@ -1,6 +1,6 @@
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
* following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
+ * perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
@@ -61,7 +61,7 @@
#define NUM_NID 949
#define NUM_SN 941
#define NUM_LN 941
-#define NUM_OBJ 882
+#define NUM_OBJ 876
static const unsigned char lvalues[6176]={
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
@@ -2482,7 +2482,7 @@ static const ASN1_OBJECT kObjects[NUM_NID]={
NID_dhSinglePass_cofactorDH_sha512kdf_scheme,6,&(lvalues[6169]),0},
{"dh-std-kdf","dh-std-kdf",NID_dh_std_kdf,0,NULL,0},
{"dh-cofactor-kdf","dh-cofactor-kdf",NID_dh_cofactor_kdf,0,NULL,0},
-{"X25519","x25519",NID_x25519,0,NULL,0},
+{"X25519","X25519",NID_X25519,0,NULL,0},
};
static const unsigned int kNIDsInShortNameOrder[NUM_SN]={
@@ -3538,6 +3538,7 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
129, /* "TLS Web Server Authentication" */
133, /* "Time Stamping" */
375, /* "Trust Root" */
+948, /* "X25519" */
12, /* "X509" */
402, /* "X509v3 AC Targeting" */
746, /* "X509v3 Any Policy" */
@@ -4366,7 +4367,6 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
742, /* "wap-wsg-idm-ecid-wtls9" */
804, /* "whirlpool" */
868, /* "x121Address" */
-948, /* "x25519" */
503, /* "x500UniqueIdentifier" */
158, /* "x509Certificate" */
160, /* "x509Crl" */
@@ -4374,12 +4374,6 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
};
static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={
- 0, /* OBJ_undef 0 */
-181, /* OBJ_iso 1 */
-393, /* OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t */
-404, /* OBJ_ccitt OBJ_itu_t */
-645, /* OBJ_itu_t 0 */
-646, /* OBJ_joint_iso_itu_t 2 */
434, /* OBJ_data 0 9 */
182, /* OBJ_member_body 1 2 */
379, /* OBJ_org 1 3 */
diff --git a/src/crypto/obj/obj_dat.pl b/src/crypto/obj/obj_dat.pl
index 201ec722..036ded54 100644
--- a/src/crypto/obj/obj_dat.pl
+++ b/src/crypto/obj/obj_dat.pl
@@ -6,7 +6,7 @@ use integer;
if (scalar @ARGV != 2)
{
- print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
+ print "Usage: perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h\n";
exit 1;
}
@@ -163,7 +163,7 @@ foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a)
push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_));
}
-@a=grep(defined($obj{$nid{$_}}),0 .. $n);
+@a=grep(defined($obj{$nid{$_}}) && $objd{$obj{$nid{$_}}} =~ /,/,0 .. $n);
foreach (sort obj_cmp @a)
{
$m=$obj{$nid{$_}};
@@ -176,7 +176,7 @@ foreach (sort obj_cmp @a)
print OUT <<'EOF';
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
* following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
+ * perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
diff --git a/src/crypto/obj/obj_mac.num b/src/crypto/obj/obj_mac.num
index a0e09b80..074657ae 100644
--- a/src/crypto/obj/obj_mac.num
+++ b/src/crypto/obj/obj_mac.num
@@ -945,4 +945,4 @@ dhSinglePass_cofactorDH_sha384kdf_scheme 944
dhSinglePass_cofactorDH_sha512kdf_scheme 945
dh_std_kdf 946
dh_cofactor_kdf 947
-x25519 948
+X25519 948
diff --git a/src/crypto/obj/obj_test.cc b/src/crypto/obj/obj_test.cc
new file mode 100644
index 00000000..2948941a
--- /dev/null
+++ b/src/crypto/obj/obj_test.cc
@@ -0,0 +1,106 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/obj.h>
+
+
+static bool TestBasic() {
+ static const int kNID = NID_sha256WithRSAEncryption;
+ static const char kShortName[] = "RSA-SHA256";
+ static const char kLongName[] = "sha256WithRSAEncryption";
+ static const char kText[] = "1.2.840.113549.1.1.11";
+ static const uint8_t kDER[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ };
+
+ CBS cbs;
+ CBS_init(&cbs, kDER, sizeof(kDER));
+ if (OBJ_cbs2nid(&cbs) != kNID ||
+ OBJ_sn2nid(kShortName) != kNID ||
+ OBJ_ln2nid(kLongName) != kNID ||
+ OBJ_txt2nid(kShortName) != kNID ||
+ OBJ_txt2nid(kLongName) != kNID ||
+ OBJ_txt2nid(kText) != kNID) {
+ return false;
+ }
+
+ if (strcmp(kShortName, OBJ_nid2sn(kNID)) != 0 ||
+ strcmp(kLongName, OBJ_nid2ln(kNID)) != 0) {
+ return false;
+ }
+
+ if (OBJ_sn2nid("this is not an OID") != NID_undef ||
+ OBJ_ln2nid("this is not an OID") != NID_undef ||
+ OBJ_txt2nid("this is not an OID") != NID_undef) {
+ return false;
+ }
+
+ CBS_init(&cbs, NULL, 0);
+ if (OBJ_cbs2nid(&cbs) != NID_undef) {
+ return false;
+ }
+
+ // 1.2.840.113554.4.1.72585.2 (https://davidben.net/oid).
+ static const uint8_t kUnknownDER[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
+ };
+ CBS_init(&cbs, kUnknownDER, sizeof(kUnknownDER));
+ if (OBJ_cbs2nid(&cbs) != NID_undef) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestSignatureAlgorithms() {
+ int digest_nid, pkey_nid;
+ if (!OBJ_find_sigid_algs(NID_sha256WithRSAEncryption, &digest_nid,
+ &pkey_nid) ||
+ digest_nid != NID_sha256 || pkey_nid != NID_rsaEncryption) {
+ return false;
+ }
+
+ if (OBJ_find_sigid_algs(NID_sha256, &digest_nid, &pkey_nid)) {
+ return false;
+ }
+
+ int sign_nid;
+ if (!OBJ_find_sigid_by_algs(&sign_nid, NID_sha256, NID_rsaEncryption) ||
+ sign_nid != NID_sha256WithRSAEncryption) {
+ return false;
+ }
+
+ if (OBJ_find_sigid_by_algs(&sign_nid, NID_dsa, NID_rsaEncryption)) {
+ return false;
+ }
+
+ return true;
+}
+
+int main() {
+ CRYPTO_library_init();
+
+ if (!TestBasic() ||
+ !TestSignatureAlgorithms()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/obj/objects.pl b/src/crypto/obj/objects.pl
index 7073e855..165429b4 100644
--- a/src/crypto/obj/objects.pl
+++ b/src/crypto/obj/objects.pl
@@ -2,7 +2,7 @@
if (scalar @ARGV != 3)
{
- print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h\n";
+ print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h\n";
exit 1;
}
@@ -127,7 +127,7 @@ open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]";
print OUT <<'EOF';
/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
* following command:
- * perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
+ * perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
@@ -186,23 +186,43 @@ print OUT <<'EOF';
* [including the GNU Public Licence.]
*/
-#define SN_undef "UNDEF"
-#define LN_undef "undefined"
-#define NID_undef 0
-#define OBJ_undef 0L
+#ifndef OPENSSL_HEADER_NID_H
+#define OPENSSL_HEADER_NID_H
+
+
+/* The nid library provides numbered values for ASN.1 object identifiers and
+ * other symbols. These values are used by other libraries to identify
+ * cryptographic primitives.
+ *
+ * A separate objects library, obj.h, provides functions for converting between
+ * nids and object identifiers. However it depends on large internal tables with
+ * the encodings of every nid defind. Consumers concerned with binary size
+ * should instead embed the encodings of the few consumed OIDs and compare
+ * against those.
+ *
+ * These values should not be used outside of a single process; they are not
+ * stable identifiers. */
+
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
EOF
foreach (sort { $a <=> $b } keys %ordern)
{
$Cname=$ordern{$_};
- print OUT "#define SN_",$Cname,"\t\t\"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
- print OUT "#define LN_",$Cname,"\t\t\"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
- print OUT "#define NID_",$Cname,"\t\t",$nid{$Cname},"\n" if $nid{$Cname} ne "";
- print OUT "#define OBJ_",$Cname,"\t\t",$obj{$Cname},"\n" if $obj{$Cname} ne "";
+ print OUT "#define SN_",$Cname," \"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
+ print OUT "#define LN_",$Cname," \"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
+ print OUT "#define NID_",$Cname," ",$nid{$Cname},"\n" if $nid{$Cname} ne "";
+ print OUT "#define OBJ_",$Cname," ",$obj{$Cname},"\n" if $obj{$Cname} ne "";
print OUT "\n";
}
+print OUT "\n#endif /* OPENSSL_HEADER_NID_H */\n";
+
close OUT;
sub process_oid
diff --git a/src/crypto/obj/objects.txt b/src/crypto/obj/objects.txt
index 93cf53aa..f3990d00 100644
--- a/src/crypto/obj/objects.txt
+++ b/src/crypto/obj/objects.txt
@@ -1332,4 +1332,4 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
: dh-cofactor-kdf
# NID for X25519 (no corresponding OID).
- : X25519 : x25519
+ : X25519
diff --git a/src/crypto/pem/pem_all.c b/src/crypto/pem/pem_all.c
index c9f8b6ee..e94ff265 100644
--- a/src/crypto/pem/pem_all.c
+++ b/src/crypto/pem/pem_all.c
@@ -113,159 +113,150 @@
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
-/*#include <openssl/pkcs7.h> */
+/*
+ * #include <openssl/pkcs7.h>
+ */
#include <openssl/rsa.h>
#include <openssl/x509.h>
-
static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa);
static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa);
static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey);
-
IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ)
IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
-
IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
-
-
-/* We treat RSA or DSA private keys as a special case.
- *
- * For private keys we read in an EVP_PKEY structure with
- * PEM_read_bio_PrivateKey() and extract the relevant private
- * key: this means can handle "traditional" and PKCS#8 formats
- * transparently.
+/*
+ * We treat RSA or DSA private keys as a special case. For private keys we
+ * read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract
+ * the relevant private key: this means can handle "traditional" and PKCS#8
+ * formats transparently.
*/
-
static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa)
{
- RSA *rtmp;
- if(!key) return NULL;
- rtmp = EVP_PKEY_get1_RSA(key);
- EVP_PKEY_free(key);
- if(!rtmp) return NULL;
- if(rsa) {
- RSA_free(*rsa);
- *rsa = rtmp;
- }
- return rtmp;
+ RSA *rtmp;
+ if (!key)
+ return NULL;
+ rtmp = EVP_PKEY_get1_RSA(key);
+ EVP_PKEY_free(key);
+ if (!rtmp)
+ return NULL;
+ if (rsa) {
+ RSA_free(*rsa);
+ *rsa = rtmp;
+ }
+ return rtmp;
}
RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb,
- void *u)
+ void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
- return pkey_get_rsa(pktmp, rsa);
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+ return pkey_get_rsa(pktmp, rsa);
}
#ifndef OPENSSL_NO_FP_API
-RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb,
- void *u)
+RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
- return pkey_get_rsa(pktmp, rsa);
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+ return pkey_get_rsa(pktmp, rsa);
}
#endif
-IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey)
+IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA,
+ RSAPrivateKey)
-IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey)
-IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY)
+IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC,
+ RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA,
+ PEM_STRING_PUBLIC,
+ RSA_PUBKEY)
#ifndef OPENSSL_NO_DSA
-
static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa)
{
- DSA *dtmp;
- if(!key) return NULL;
- dtmp = EVP_PKEY_get1_DSA(key);
- EVP_PKEY_free(key);
- if(!dtmp) return NULL;
- if(dsa) {
- DSA_free(*dsa);
- *dsa = dtmp;
- }
- return dtmp;
+ DSA *dtmp;
+ if (!key)
+ return NULL;
+ dtmp = EVP_PKEY_get1_DSA(key);
+ EVP_PKEY_free(key);
+ if (!dtmp)
+ return NULL;
+ if (dsa) {
+ DSA_free(*dsa);
+ *dsa = dtmp;
+ }
+ return dtmp;
}
DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb,
- void *u)
+ void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
- return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+ return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
}
+IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA,
+ DSAPrivateKey)
-IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey)
-
-IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
-
-#ifndef OPENSSL_NO_FP_API
-
-DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb,
- void *u)
+ IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
+# ifndef OPENSSL_NO_FP_API
+DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
- return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+ return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
}
-#endif
+# endif
IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
-
#endif
-
-
static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
{
- EC_KEY *dtmp;
- if(!key) return NULL;
- dtmp = EVP_PKEY_get1_EC_KEY(key);
- EVP_PKEY_free(key);
- if(!dtmp) return NULL;
- if(eckey)
- {
- EC_KEY_free(*eckey);
- *eckey = dtmp;
- }
- return dtmp;
+ EC_KEY *dtmp;
+ if (!key)
+ return NULL;
+ dtmp = EVP_PKEY_get1_EC_KEY(key);
+ EVP_PKEY_free(key);
+ if (!dtmp)
+ return NULL;
+ if (eckey) {
+ EC_KEY_free(*eckey);
+ *eckey = dtmp;
+ }
+ return dtmp;
}
EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb,
- void *u)
+ void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
- return pkey_get_eckey(pktmp, key); /* will free pktmp */
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+ return pkey_get_eckey(pktmp, key); /* will free pktmp */
}
-IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, ECPrivateKey)
-
-
-IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
+IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY,
+ ECPrivateKey)
+ IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
#ifndef OPENSSL_NO_FP_API
-
EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
- void *u)
+ void *u)
{
- EVP_PKEY *pktmp;
- pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
- return pkey_get_eckey(pktmp, eckey); /* will free pktmp */
+ EVP_PKEY *pktmp;
+ pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+ return pkey_get_eckey(pktmp, eckey); /* will free pktmp */
}
#endif
-
-
IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
-IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
+ IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/src/crypto/pem/pem_info.c b/src/crypto/pem/pem_info.c
index 2a39a5be..57c87d4f 100644
--- a/src/crypto/pem/pem_info.c
+++ b/src/crypto/pem/pem_info.c
@@ -5,21 +5,21 @@
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
- *
+ *
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
+ *
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -34,10 +34,10 @@
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
+ * 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
+ *
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -49,7 +49,7 @@
* 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.
- *
+ *
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
@@ -71,334 +71,311 @@
#include <openssl/rsa.h>
#include <openssl/x509.h>
-
#ifndef OPENSSL_NO_FP_API
-STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
- {
- BIO *b;
- STACK_OF(X509_INFO) *ret;
+STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u)
+{
+ BIO *b;
+ STACK_OF(X509_INFO) *ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_X509_INFO_read_bio(b,sk,cb,u);
- BIO_free(b);
- return(ret);
- }
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+ BIO_free(b);
+ return (ret);
+}
#endif
-STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
- {
- X509_INFO *xi=NULL;
- char *name=NULL,*header=NULL;
- void *pp;
- unsigned char *data=NULL;
- const unsigned char *p;
- long len,error=0;
- int ok=0;
- STACK_OF(X509_INFO) *ret=NULL;
- unsigned int i,raw,ptype;
- d2i_of_void *d2i = 0;
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u)
+{
+ X509_INFO *xi = NULL;
+ char *name = NULL, *header = NULL;
+ void *pp;
+ unsigned char *data = NULL;
+ const unsigned char *p;
+ long len, error = 0;
+ int ok = 0;
+ STACK_OF(X509_INFO) *ret = NULL;
+ unsigned int i, raw, ptype;
+ d2i_of_void *d2i = 0;
- if (sk == NULL)
- {
- if ((ret=sk_X509_INFO_new_null()) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- else
- ret=sk;
+ if (sk == NULL) {
+ if ((ret = sk_X509_INFO_new_null()) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else
+ ret = sk;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- for (;;)
- {
- raw=0;
- ptype = 0;
- i=PEM_read_bio(bp,&name,&header,&data,&len);
- if (i == 0)
- {
- error=ERR_GET_REASON(ERR_peek_last_error());
- if (error == PEM_R_NO_START_LINE)
- {
- ERR_clear_error();
- break;
- }
- goto err;
- }
-start:
- if ( (strcmp(name,PEM_STRING_X509) == 0) ||
- (strcmp(name,PEM_STRING_X509_OLD) == 0))
- {
- d2i=(D2I_OF(void))d2i_X509;
- if (xi->x509 != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
- pp=&(xi->x509);
- }
- else if ((strcmp(name,PEM_STRING_X509_TRUSTED) == 0))
- {
- d2i=(D2I_OF(void))d2i_X509_AUX;
- if (xi->x509 != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
- pp=&(xi->x509);
- }
- else if (strcmp(name,PEM_STRING_X509_CRL) == 0)
- {
- d2i=(D2I_OF(void))d2i_X509_CRL;
- if (xi->crl != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
- pp=&(xi->crl);
- }
- else
- if (strcmp(name,PEM_STRING_RSA) == 0)
- {
- d2i=(D2I_OF(void))d2i_RSAPrivateKey;
- if (xi->x_pkey != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ for (;;) {
+ raw = 0;
+ ptype = 0;
+ i = PEM_read_bio(bp, &name, &header, &data, &len);
+ if (i == 0) {
+ error = ERR_GET_REASON(ERR_peek_last_error());
+ if (error == PEM_R_NO_START_LINE) {
+ ERR_clear_error();
+ break;
+ }
+ goto err;
+ }
+ start:
+ if ((strcmp(name, PEM_STRING_X509) == 0) ||
+ (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
+ d2i = (D2I_OF(void)) d2i_X509;
+ if (xi->x509 != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
+ pp = &(xi->x509);
+ } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
+ d2i = (D2I_OF(void)) d2i_X509_AUX;
+ if (xi->x509 != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
+ pp = &(xi->x509);
+ } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
+ d2i = (D2I_OF(void)) d2i_X509_CRL;
+ if (xi->crl != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
+ pp = &(xi->crl);
+ } else if (strcmp(name, PEM_STRING_RSA) == 0) {
+ d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
+ if (xi->x_pkey != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
- xi->enc_data=NULL;
- xi->enc_len=0;
+ xi->enc_data = NULL;
+ xi->enc_len = 0;
- xi->x_pkey=X509_PKEY_new();
- ptype=EVP_PKEY_RSA;
- pp=&xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw=1;
- }
- else
+ xi->x_pkey = X509_PKEY_new();
+ ptype = EVP_PKEY_RSA;
+ pp = &xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw = 1;
+ } else
#ifndef OPENSSL_NO_DSA
- if (strcmp(name,PEM_STRING_DSA) == 0)
- {
- d2i=(D2I_OF(void))d2i_DSAPrivateKey;
- if (xi->x_pkey != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
+ if (strcmp(name, PEM_STRING_DSA) == 0) {
+ d2i = (D2I_OF(void)) d2i_DSAPrivateKey;
+ if (xi->x_pkey != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
- xi->enc_data=NULL;
- xi->enc_len=0;
+ xi->enc_data = NULL;
+ xi->enc_len = 0;
- xi->x_pkey=X509_PKEY_new();
- ptype = EVP_PKEY_DSA;
- pp=&xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw=1;
- }
- else
+ xi->x_pkey = X509_PKEY_new();
+ ptype = EVP_PKEY_DSA;
+ pp = &xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw = 1;
+ } else
#endif
- if (strcmp(name,PEM_STRING_ECPRIVATEKEY) == 0)
- {
- d2i=(D2I_OF(void))d2i_ECPrivateKey;
- if (xi->x_pkey != NULL)
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- if ((xi=X509_INFO_new()) == NULL) goto err;
- goto start;
- }
-
- xi->enc_data=NULL;
- xi->enc_len=0;
-
- xi->x_pkey=X509_PKEY_new();
- ptype = EVP_PKEY_EC;
- pp=&xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw=1;
- }
- else
- {
- d2i=NULL;
- pp=NULL;
- }
+ if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
+ d2i = (D2I_OF(void)) d2i_ECPrivateKey;
+ if (xi->x_pkey != NULL) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ if ((xi = X509_INFO_new()) == NULL)
+ goto err;
+ goto start;
+ }
+
+ xi->enc_data = NULL;
+ xi->enc_len = 0;
- if (d2i != NULL)
- {
- if (!raw)
- {
- EVP_CIPHER_INFO cipher;
+ xi->x_pkey = X509_PKEY_new();
+ ptype = EVP_PKEY_EC;
+ pp = &xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw = 1;
+ } else {
+ d2i = NULL;
+ pp = NULL;
+ }
- if (!PEM_get_EVP_CIPHER_INFO(header,&cipher))
- goto err;
- if (!PEM_do_header(&cipher,data,&len,cb,u))
- goto err;
- p=data;
- if (ptype)
- {
- if (!d2i_PrivateKey(ptype, pp, &p, len))
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- goto err;
- }
- }
- else if (d2i(pp,&p,len) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- goto err;
- }
- }
- else
- { /* encrypted RSA data */
- if (!PEM_get_EVP_CIPHER_INFO(header,
- &xi->enc_cipher)) goto err;
- xi->enc_data=(char *)data;
- xi->enc_len=(int)len;
- data=NULL;
- }
- }
- else {
- /* unknown */
- }
- if (name != NULL) OPENSSL_free(name);
- if (header != NULL) OPENSSL_free(header);
- if (data != NULL) OPENSSL_free(data);
- name=NULL;
- header=NULL;
- data=NULL;
- }
+ if (d2i != NULL) {
+ if (!raw) {
+ EVP_CIPHER_INFO cipher;
- /* if the last one hasn't been pushed yet and there is anything
- * in it then add it to the stack ...
- */
- if ((xi->x509 != NULL) || (xi->crl != NULL) ||
- (xi->x_pkey != NULL) || (xi->enc_data != NULL))
- {
- if (!sk_X509_INFO_push(ret,xi)) goto err;
- xi=NULL;
- }
- ok=1;
-err:
- if (xi != NULL) X509_INFO_free(xi);
- if (!ok)
- {
- for (i=0; i<sk_X509_INFO_num(ret); i++)
- {
- xi=sk_X509_INFO_value(ret,i);
- X509_INFO_free(xi);
- }
- if (ret != sk) sk_X509_INFO_free(ret);
- ret=NULL;
- }
-
- if (name != NULL) OPENSSL_free(name);
- if (header != NULL) OPENSSL_free(header);
- if (data != NULL) OPENSSL_free(data);
- return(ret);
- }
+ if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+ goto err;
+ if (!PEM_do_header(&cipher, data, &len, cb, u))
+ goto err;
+ p = data;
+ if (ptype) {
+ if (!d2i_PrivateKey(ptype, pp, &p, len)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ } else if (d2i(pp, &p, len) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ } else { /* encrypted RSA data */
+ if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher))
+ goto err;
+ xi->enc_data = (char *)data;
+ xi->enc_len = (int)len;
+ data = NULL;
+ }
+ } else {
+ /* unknown */
+ }
+ if (name != NULL)
+ OPENSSL_free(name);
+ if (header != NULL)
+ OPENSSL_free(header);
+ if (data != NULL)
+ OPENSSL_free(data);
+ name = NULL;
+ header = NULL;
+ data = NULL;
+ }
+ /*
+ * if the last one hasn't been pushed yet and there is anything in it
+ * then add it to the stack ...
+ */
+ if ((xi->x509 != NULL) || (xi->crl != NULL) ||
+ (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
+ if (!sk_X509_INFO_push(ret, xi))
+ goto err;
+ xi = NULL;
+ }
+ ok = 1;
+ err:
+ if (xi != NULL)
+ X509_INFO_free(xi);
+ if (!ok) {
+ for (i = 0; i < sk_X509_INFO_num(ret); i++) {
+ xi = sk_X509_INFO_value(ret, i);
+ X509_INFO_free(xi);
+ }
+ if (ret != sk)
+ sk_X509_INFO_free(ret);
+ ret = NULL;
+ }
+
+ if (name != NULL)
+ OPENSSL_free(name);
+ if (header != NULL)
+ OPENSSL_free(header);
+ if (data != NULL)
+ OPENSSL_free(data);
+ return (ret);
+}
/* A TJH addition */
int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
- {
- EVP_CIPHER_CTX ctx;
- int i,ret=0;
- unsigned char *data=NULL;
- const char *objstr=NULL;
- char buf[PEM_BUFSIZE];
- unsigned char *iv=NULL;
- unsigned iv_len = 0;
-
- if (enc != NULL)
- {
- iv_len = EVP_CIPHER_iv_length(enc);
- objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
- if (objstr == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
- goto err;
- }
- }
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ EVP_CIPHER_CTX ctx;
+ int i, ret = 0;
+ unsigned char *data = NULL;
+ const char *objstr = NULL;
+ char buf[PEM_BUFSIZE];
+ unsigned char *iv = NULL;
+ unsigned iv_len = 0;
+
+ if (enc != NULL) {
+ iv_len = EVP_CIPHER_iv_length(enc);
+ objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+ if (objstr == NULL) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+ }
- /* now for the fun part ... if we have a private key then
- * we have to be able to handle a not-yet-decrypted key
- * being written out correctly ... if it is decrypted or
- * it is non-encrypted then we use the base code
- */
- if (xi->x_pkey!=NULL)
- {
- if ( (xi->enc_data!=NULL) && (xi->enc_len>0) )
- {
- if (enc == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL);
- goto err;
- }
+ /*
+ * now for the fun part ... if we have a private key then we have to be
+ * able to handle a not-yet-decrypted key being written out correctly ...
+ * if it is decrypted or it is non-encrypted then we use the base code
+ */
+ if (xi->x_pkey != NULL) {
+ if ((xi->enc_data != NULL) && (xi->enc_len > 0)) {
+ if (enc == NULL) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL);
+ goto err;
+ }
- /* copy from weirdo names into more normal things */
- iv=xi->enc_cipher.iv;
- data=(unsigned char *)xi->enc_data;
- i=xi->enc_len;
+ /* copy from weirdo names into more normal things */
+ iv = xi->enc_cipher.iv;
+ data = (unsigned char *)xi->enc_data;
+ i = xi->enc_len;
- /* we take the encryption data from the
- * internal stuff rather than what the
- * user has passed us ... as we have to
- * match exactly for some strange reason
- */
- objstr=OBJ_nid2sn(
- EVP_CIPHER_nid(xi->enc_cipher.cipher));
- if (objstr == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
- goto err;
- }
+ /*
+ * we take the encryption data from the internal stuff rather
+ * than what the user has passed us ... as we have to match
+ * exactly for some strange reason
+ */
+ objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher));
+ if (objstr == NULL) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
- /* create the right magic header stuff */
- assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
- buf[0]='\0';
- PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
- PEM_dek_info(buf,objstr,iv_len,(char *)iv);
+ /* create the right magic header stuff */
+ assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
+ buf[0] = '\0';
+ PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+ PEM_dek_info(buf, objstr, iv_len, (char *)iv);
- /* use the normal code to write things out */
- i=PEM_write_bio(bp,PEM_STRING_RSA,buf,data,i);
- if (i <= 0) goto err;
- }
- else
- {
- /* Add DSA/DH */
- /* normal optionally encrypted stuff */
- if (PEM_write_bio_RSAPrivateKey(bp,
- xi->x_pkey->dec_pkey->pkey.rsa,
- enc,kstr,klen,cb,u)<=0)
- goto err;
- }
- }
+ /* use the normal code to write things out */
+ i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
+ if (i <= 0)
+ goto err;
+ } else {
+ /* Add DSA/DH */
+ /* normal optionally encrypted stuff */
+ if (PEM_write_bio_RSAPrivateKey(bp,
+ xi->x_pkey->dec_pkey->pkey.rsa,
+ enc, kstr, klen, cb, u) <= 0)
+ goto err;
+ }
+ }
- /* if we have a certificate then write it out now */
- if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp,xi->x509) <= 0))
- goto err;
+ /* if we have a certificate then write it out now */
+ if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
+ goto err;
- /* we are ignoring anything else that is loaded into the X509_INFO
- * structure for the moment ... as I don't need it so I'm not
- * coding it here and Eric can do it when this makes it into the
- * base library --tjh
- */
+ /*
+ * we are ignoring anything else that is loaded into the X509_INFO
+ * structure for the moment ... as I don't need it so I'm not coding it
+ * here and Eric can do it when this makes it into the base library --tjh
+ */
- ret=1;
+ ret = 1;
-err:
- OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
- OPENSSL_cleanse(buf,PEM_BUFSIZE);
- return(ret);
- }
+ err:
+ OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
+ OPENSSL_cleanse(buf, PEM_BUFSIZE);
+ return (ret);
+}
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index 12d96744..6e928a65 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -71,761 +71,708 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
+#define MIN_LENGTH 4
-
-#define MIN_LENGTH 4
-
-static int load_iv(char **fromp,unsigned char *to, int num);
+static int load_iv(char **fromp, unsigned char *to, int num);
static int check_pem(const char *nm, const char *name);
-int pem_check_suffix(const char *pem_str, const char *suffix);
void PEM_proc_type(char *buf, int type)
- {
- const char *str;
-
- if (type == PEM_TYPE_ENCRYPTED)
- str="ENCRYPTED";
- else if (type == PEM_TYPE_MIC_CLEAR)
- str="MIC-CLEAR";
- else if (type == PEM_TYPE_MIC_ONLY)
- str="MIC-ONLY";
- else
- str="BAD-TYPE";
-
- BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
- BUF_strlcat(buf,str,PEM_BUFSIZE);
- BUF_strlcat(buf,"\n",PEM_BUFSIZE);
- }
+{
+ const char *str;
+
+ if (type == PEM_TYPE_ENCRYPTED)
+ str = "ENCRYPTED";
+ else if (type == PEM_TYPE_MIC_CLEAR)
+ str = "MIC-CLEAR";
+ else if (type == PEM_TYPE_MIC_ONLY)
+ str = "MIC-ONLY";
+ else
+ str = "BAD-TYPE";
+
+ BUF_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE);
+ BUF_strlcat(buf, str, PEM_BUFSIZE);
+ BUF_strlcat(buf, "\n", PEM_BUFSIZE);
+}
void PEM_dek_info(char *buf, const char *type, int len, char *str)
- {
- static const unsigned char map[17]="0123456789ABCDEF";
- long i;
- int j;
-
- BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
- BUF_strlcat(buf,type,PEM_BUFSIZE);
- BUF_strlcat(buf,",",PEM_BUFSIZE);
- j=strlen(buf);
- if (j + (len * 2) + 1 > PEM_BUFSIZE)
- return;
- for (i=0; i<len; i++)
- {
- buf[j+i*2] =map[(str[i]>>4)&0x0f];
- buf[j+i*2+1]=map[(str[i] )&0x0f];
- }
- buf[j+i*2]='\n';
- buf[j+i*2+1]='\0';
- }
+{
+ static const unsigned char map[17] = "0123456789ABCDEF";
+ long i;
+ int j;
+
+ BUF_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE);
+ BUF_strlcat(buf, type, PEM_BUFSIZE);
+ BUF_strlcat(buf, ",", PEM_BUFSIZE);
+ j = strlen(buf);
+ if (j + (len * 2) + 1 > PEM_BUFSIZE)
+ return;
+ for (i = 0; i < len; i++) {
+ buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
+ buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
+ }
+ buf[j + i * 2] = '\n';
+ buf[j + i * 2 + 1] = '\0';
+}
#ifndef OPENSSL_NO_FP_API
void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
- pem_password_cb *cb, void *u)
- {
- BIO *b;
- void *ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
- BIO_free(b);
- return(ret);
- }
+ pem_password_cb *cb, void *u)
+{
+ BIO *b;
+ void *ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
+ BIO_free(b);
+ return (ret);
+}
#endif
static int check_pem(const char *nm, const char *name)
{
- /* Normal matching nm and name */
- if (!strcmp(nm,name)) return 1;
-
- /* Make PEM_STRING_EVP_PKEY match any private key */
-
- if(!strcmp(name,PEM_STRING_EVP_PKEY))
- {
- int slen;
- const EVP_PKEY_ASN1_METHOD *ameth;
- if(!strcmp(nm,PEM_STRING_PKCS8))
- return 1;
- if(!strcmp(nm,PEM_STRING_PKCS8INF))
- return 1;
- slen = pem_check_suffix(nm, "PRIVATE KEY");
- if (slen > 0)
- {
- /* NB: ENGINE implementations wont contain
- * a deprecated old private key decode function
- * so don't look for them.
- */
- ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
- if (ameth && ameth->old_priv_decode)
- return 1;
- }
- return 0;
- }
-
- if(!strcmp(name,PEM_STRING_PARAMETERS))
- {
- int slen;
- const EVP_PKEY_ASN1_METHOD *ameth;
- slen = pem_check_suffix(nm, "PARAMETERS");
- if (slen > 0)
- {
- ENGINE *e;
- ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
- if (ameth)
- {
- int r;
- if (ameth->param_decode)
- r = 1;
- else
- r = 0;
- return r;
- }
- }
- return 0;
- }
- /* Permit older strings */
-
- if(!strcmp(nm,PEM_STRING_X509_OLD) &&
- !strcmp(name,PEM_STRING_X509)) return 1;
-
- if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) &&
- !strcmp(name,PEM_STRING_X509_REQ)) return 1;
-
- /* Allow normal certs to be read as trusted certs */
- if(!strcmp(nm,PEM_STRING_X509) &&
- !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
-
- if(!strcmp(nm,PEM_STRING_X509_OLD) &&
- !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
-
- /* Some CAs use PKCS#7 with CERTIFICATE headers */
- if(!strcmp(nm, PEM_STRING_X509) &&
- !strcmp(name, PEM_STRING_PKCS7)) return 1;
-
- if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
- !strcmp(name, PEM_STRING_PKCS7)) return 1;
+ /* Normal matching nm and name */
+ if (!strcmp(nm, name))
+ return 1;
+
+ /* Make PEM_STRING_EVP_PKEY match any private key */
+
+ if (!strcmp(name, PEM_STRING_EVP_PKEY)) {
+ return !strcmp(nm, PEM_STRING_PKCS8) ||
+ !strcmp(nm, PEM_STRING_PKCS8INF) ||
+ !strcmp(nm, PEM_STRING_RSA) ||
+ !strcmp(nm, PEM_STRING_EC) ||
+ !strcmp(nm, PEM_STRING_DSA);
+ }
+
+ /* Permit older strings */
+
+ if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509))
+ return 1;
+
+ if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) &&
+ !strcmp(name, PEM_STRING_X509_REQ))
+ return 1;
+
+ /* Allow normal certs to be read as trusted certs */
+ if (!strcmp(nm, PEM_STRING_X509) &&
+ !strcmp(name, PEM_STRING_X509_TRUSTED))
+ return 1;
+
+ if (!strcmp(nm, PEM_STRING_X509_OLD) &&
+ !strcmp(name, PEM_STRING_X509_TRUSTED))
+ return 1;
+
+ /* Some CAs use PKCS#7 with CERTIFICATE headers */
+ if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7))
+ return 1;
+
+ if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
+ !strcmp(name, PEM_STRING_PKCS7))
+ return 1;
#ifndef OPENSSL_NO_CMS
- if(!strcmp(nm, PEM_STRING_X509) &&
- !strcmp(name, PEM_STRING_CMS)) return 1;
- /* Allow CMS to be read from PKCS#7 headers */
- if(!strcmp(nm, PEM_STRING_PKCS7) &&
- !strcmp(name, PEM_STRING_CMS)) return 1;
+ if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS))
+ return 1;
+ /* Allow CMS to be read from PKCS#7 headers */
+ if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS))
+ return 1;
#endif
- return 0;
+ return 0;
}
-int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
- pem_password_cb *cb, void *u)
- {
- EVP_CIPHER_INFO cipher;
- char *nm=NULL,*header=NULL;
- unsigned char *data=NULL;
- long len;
- int ret = 0;
-
- for (;;)
- {
- if (!PEM_read_bio(bp,&nm,&header,&data,&len)) {
- if(ERR_GET_REASON(ERR_peek_error()) ==
- PEM_R_NO_START_LINE)
- ERR_add_error_data(2, "Expecting: ", name);
- return 0;
- }
- if(check_pem(nm, name)) break;
- OPENSSL_free(nm);
- OPENSSL_free(header);
- OPENSSL_free(data);
- }
- if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
- if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
-
- *pdata = data;
- *plen = len;
-
- if (pnm)
- *pnm = nm;
-
- ret = 1;
-
-err:
- if (!ret || !pnm) OPENSSL_free(nm);
- OPENSSL_free(header);
- if (!ret) OPENSSL_free(data);
- return ret;
- }
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
+ const char *name, BIO *bp, pem_password_cb *cb,
+ void *u)
+{
+ EVP_CIPHER_INFO cipher;
+ char *nm = NULL, *header = NULL;
+ unsigned char *data = NULL;
+ long len;
+ int ret = 0;
+
+ for (;;) {
+ if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
+ if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
+ ERR_add_error_data(2, "Expecting: ", name);
+ return 0;
+ }
+ if (check_pem(nm, name))
+ break;
+ OPENSSL_free(nm);
+ OPENSSL_free(header);
+ OPENSSL_free(data);
+ }
+ if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+ goto err;
+ if (!PEM_do_header(&cipher, data, &len, cb, u))
+ goto err;
+
+ *pdata = data;
+ *plen = len;
+
+ if (pnm)
+ *pnm = nm;
+
+ ret = 1;
+
+ err:
+ if (!ret || !pnm)
+ OPENSSL_free(nm);
+ OPENSSL_free(header);
+ if (!ret)
+ OPENSSL_free(data);
+ return ret;
+}
#ifndef OPENSSL_NO_FP_API
int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
- void *x, const EVP_CIPHER *enc, unsigned char *kstr,
- int klen, pem_password_cb *callback, void *u)
- {
- BIO *b;
- int ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
- BIO_free(b);
- return(ret);
- }
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+ int klen, pem_password_cb *callback, void *u)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
+ BIO_free(b);
+ return (ret);
+}
#endif
int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
- void *x, const EVP_CIPHER *enc, unsigned char *kstr,
- int klen, pem_password_cb *callback, void *u)
- {
- EVP_CIPHER_CTX ctx;
- int dsize=0,i,j,ret=0;
- unsigned char *p,*data=NULL;
- const char *objstr=NULL;
- char buf[PEM_BUFSIZE];
- unsigned char key[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
- if (enc != NULL)
- {
- objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
- if (objstr == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
- goto err;
- }
- }
-
- if ((dsize=i2d(x,NULL)) < 0)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- dsize=0;
- goto err;
- }
- /* dzise + 8 bytes are needed */
- /* actually it needs the cipher block size extra... */
- data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
- if (data == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- p=data;
- i=i2d(x,&p);
-
- if (enc != NULL)
- {
- const unsigned iv_len = EVP_CIPHER_iv_length(enc);
-
- if (kstr == NULL)
- {
- klen = 0;
- if (!callback)
- callback = PEM_def_callback;
- klen=(*callback)(buf,PEM_BUFSIZE,1,u);
- if (klen <= 0)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
- goto err;
- }
- kstr=(unsigned char *)buf;
- }
- assert(iv_len <= (int)sizeof(iv));
- if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
- goto err;
- /* The 'iv' is used as the iv and as a salt. It is
- * NOT taken from the BytesToKey function */
- if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL))
- goto err;
-
- if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE);
-
- assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
-
- buf[0]='\0';
- PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
- PEM_dek_info(buf,objstr,iv_len,(char *)iv);
- /* k=strlen(buf); */
-
- EVP_CIPHER_CTX_init(&ctx);
- ret = 1;
- if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv)
- || !EVP_EncryptUpdate(&ctx,data,&j,data,i)
- || !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i))
- ret = 0;
- else
- i += j;
- EVP_CIPHER_CTX_cleanup(&ctx);
- if (ret == 0)
- goto err;
- }
- else
- {
- ret=1;
- buf[0]='\0';
- }
- i=PEM_write_bio(bp,name,buf,data,i);
- if (i <= 0) ret=0;
-err:
- OPENSSL_cleanse(key,sizeof(key));
- OPENSSL_cleanse(iv,sizeof(iv));
- OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
- OPENSSL_cleanse(buf,PEM_BUFSIZE);
- if (data != NULL)
- {
- OPENSSL_cleanse(data,(unsigned int)dsize);
- OPENSSL_free(data);
- }
- return(ret);
- }
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+ int klen, pem_password_cb *callback, void *u)
+{
+ EVP_CIPHER_CTX ctx;
+ int dsize = 0, i, j, ret = 0;
+ unsigned char *p, *data = NULL;
+ const char *objstr = NULL;
+ char buf[PEM_BUFSIZE];
+ unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (enc != NULL) {
+ objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+ if (objstr == NULL) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+ }
+
+ if ((dsize = i2d(x, NULL)) < 0) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ dsize = 0;
+ goto err;
+ }
+ /* dzise + 8 bytes are needed */
+ /* actually it needs the cipher block size extra... */
+ data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20);
+ if (data == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ p = data;
+ i = i2d(x, &p);
+
+ if (enc != NULL) {
+ const unsigned iv_len = EVP_CIPHER_iv_length(enc);
+
+ if (kstr == NULL) {
+ klen = 0;
+ if (!callback)
+ callback = PEM_def_callback;
+ klen = (*callback) (buf, PEM_BUFSIZE, 1, u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
+ goto err;
+ }
+ kstr = (unsigned char *)buf;
+ }
+ assert(iv_len <= (int)sizeof(iv));
+ if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
+ goto err;
+ /*
+ * The 'iv' is used as the iv and as a salt. It is NOT taken from
+ * the BytesToKey function
+ */
+ if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL))
+ goto err;
+
+ if (kstr == (unsigned char *)buf)
+ OPENSSL_cleanse(buf, PEM_BUFSIZE);
+
+ assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
+
+ buf[0] = '\0';
+ PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+ PEM_dek_info(buf, objstr, iv_len, (char *)iv);
+ /* k=strlen(buf); */
+
+ EVP_CIPHER_CTX_init(&ctx);
+ ret = 1;
+ if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv)
+ || !EVP_EncryptUpdate(&ctx, data, &j, data, i)
+ || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
+ ret = 0;
+ else
+ i += j;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ if (ret == 0)
+ goto err;
+ } else {
+ ret = 1;
+ buf[0] = '\0';
+ }
+ i = PEM_write_bio(bp, name, buf, data, i);
+ if (i <= 0)
+ ret = 0;
+ err:
+ OPENSSL_cleanse(key, sizeof(key));
+ OPENSSL_cleanse(iv, sizeof(iv));
+ OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
+ OPENSSL_cleanse(buf, PEM_BUFSIZE);
+ if (data != NULL) {
+ OPENSSL_cleanse(data, (unsigned int)dsize);
+ OPENSSL_free(data);
+ }
+ return (ret);
+}
int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
- pem_password_cb *callback,void *u)
- {
- int i=0,j,o,klen;
- long len;
- EVP_CIPHER_CTX ctx;
- unsigned char key[EVP_MAX_KEY_LENGTH];
- char buf[PEM_BUFSIZE];
-
- len= *plen;
-
- if (cipher->cipher == NULL) return(1);
-
- klen = 0;
- if (!callback) callback = PEM_def_callback;
- klen=callback(buf,PEM_BUFSIZE,0,u);
- if (klen <= 0)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
- return(0);
- }
-
- if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
- (unsigned char *)buf,klen,1,key,NULL))
- return 0;
-
- j=(int)len;
- EVP_CIPHER_CTX_init(&ctx);
- o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0]));
- if (o)
- o = EVP_DecryptUpdate(&ctx,data,&i,data,j);
- if (o)
- o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j);
- EVP_CIPHER_CTX_cleanup(&ctx);
- OPENSSL_cleanse((char *)buf,sizeof(buf));
- OPENSSL_cleanse((char *)key,sizeof(key));
- if (!o)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT);
- return(0);
- }
- j+=i;
- *plen=j;
- return(1);
- }
-
-static const EVP_CIPHER* cipher_by_name(const char *name) {
- /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */
- if (0 == strcmp(name, SN_rc4)) {
- return EVP_rc4();
- } else if (0 == strcmp(name, SN_des_cbc)) {
- return EVP_des_cbc();
- } else if (0 == strcmp(name, SN_des_ede3_cbc)) {
- return EVP_des_ede3_cbc();
- } else if (0 == strcmp(name, SN_aes_128_cbc)) {
- return EVP_aes_128_cbc();
- } else if (0 == strcmp(name, SN_aes_192_cbc)) {
- return EVP_aes_192_cbc();
- } else if (0 == strcmp(name, SN_aes_256_cbc)) {
- return EVP_aes_256_cbc();
- } else {
- return NULL;
- }
+ pem_password_cb *callback, void *u)
+{
+ int i = 0, j, o, klen;
+ long len;
+ EVP_CIPHER_CTX ctx;
+ unsigned char key[EVP_MAX_KEY_LENGTH];
+ char buf[PEM_BUFSIZE];
+
+ len = *plen;
+
+ if (cipher->cipher == NULL)
+ return (1);
+
+ klen = 0;
+ if (!callback)
+ callback = PEM_def_callback;
+ klen = callback(buf, PEM_BUFSIZE, 0, u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+ return (0);
+ }
+
+ if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]),
+ (unsigned char *)buf, klen, 1, key, NULL))
+ return 0;
+
+ j = (int)len;
+ EVP_CIPHER_CTX_init(&ctx);
+ o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0]));
+ if (o)
+ o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
+ if (o)
+ o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ OPENSSL_cleanse((char *)buf, sizeof(buf));
+ OPENSSL_cleanse((char *)key, sizeof(key));
+ if (!o) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT);
+ return (0);
+ }
+ j += i;
+ *plen = j;
+ return (1);
+}
+
+static const EVP_CIPHER *cipher_by_name(const char *name)
+{
+ /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */
+ if (0 == strcmp(name, SN_rc4)) {
+ return EVP_rc4();
+ } else if (0 == strcmp(name, SN_des_cbc)) {
+ return EVP_des_cbc();
+ } else if (0 == strcmp(name, SN_des_ede3_cbc)) {
+ return EVP_des_ede3_cbc();
+ } else if (0 == strcmp(name, SN_aes_128_cbc)) {
+ return EVP_aes_128_cbc();
+ } else if (0 == strcmp(name, SN_aes_192_cbc)) {
+ return EVP_aes_192_cbc();
+ } else if (0 == strcmp(name, SN_aes_256_cbc)) {
+ return EVP_aes_256_cbc();
+ } else {
+ return NULL;
+ }
}
int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
- {
- const EVP_CIPHER *enc=NULL;
- char *p,c;
- char **header_pp = &header;
-
- cipher->cipher=NULL;
- if ((header == NULL) || (*header == '\0') || (*header == '\n'))
- return(1);
- if (strncmp(header,"Proc-Type: ",11) != 0)
- { OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); return(0); }
- header+=11;
- if (*header != '4') return(0); header++;
- if (*header != ',') return(0); header++;
- if (strncmp(header,"ENCRYPTED",9) != 0)
- { OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); return(0); }
- for (; (*header != '\n') && (*header != '\0'); header++)
- ;
- if (*header == '\0')
- { OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); return(0); }
- header++;
- if (strncmp(header,"DEK-Info: ",10) != 0)
- { OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); return(0); }
- header+=10;
-
- p=header;
- for (;;)
- {
- c= *header;
- if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') ||
- ((c >= '0') && (c <= '9'))))
- break;
- header++;
- }
- *header='\0';
- cipher->cipher=enc=cipher_by_name(p);
- *header=c;
- header++;
-
- if (enc == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION);
- return(0);
- }
- if (!load_iv(header_pp,&(cipher->iv[0]),EVP_CIPHER_iv_length(enc)))
- return(0);
-
- return(1);
- }
+{
+ const EVP_CIPHER *enc = NULL;
+ char *p, c;
+ char **header_pp = &header;
+
+ cipher->cipher = NULL;
+ if ((header == NULL) || (*header == '\0') || (*header == '\n'))
+ return (1);
+ if (strncmp(header, "Proc-Type: ", 11) != 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE);
+ return (0);
+ }
+ header += 11;
+ if (*header != '4')
+ return (0);
+ header++;
+ if (*header != ',')
+ return (0);
+ header++;
+ if (strncmp(header, "ENCRYPTED", 9) != 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED);
+ return (0);
+ }
+ for (; (*header != '\n') && (*header != '\0'); header++) ;
+ if (*header == '\0') {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER);
+ return (0);
+ }
+ header++;
+ if (strncmp(header, "DEK-Info: ", 10) != 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO);
+ return (0);
+ }
+ header += 10;
+
+ p = header;
+ for (;;) {
+ c = *header;
+ if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') ||
+ ((c >= '0') && (c <= '9'))))
+ break;
+ header++;
+ }
+ *header = '\0';
+ cipher->cipher = enc = cipher_by_name(p);
+ *header = c;
+ header++;
+
+ if (enc == NULL) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION);
+ return (0);
+ }
+ if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc)))
+ return (0);
+
+ return (1);
+}
static int load_iv(char **fromp, unsigned char *to, int num)
- {
- int v,i;
- char *from;
-
- from= *fromp;
- for (i=0; i<num; i++) to[i]=0;
- num*=2;
- for (i=0; i<num; i++)
- {
- if ((*from >= '0') && (*from <= '9'))
- v= *from-'0';
- else if ((*from >= 'A') && (*from <= 'F'))
- v= *from-'A'+10;
- else if ((*from >= 'a') && (*from <= 'f'))
- v= *from-'a'+10;
- else
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS);
- return(0);
- }
- from++;
- to[i/2]|=v<<(long)((!(i&1))*4);
- }
-
- *fromp=from;
- return(1);
- }
+{
+ int v, i;
+ char *from;
+
+ from = *fromp;
+ for (i = 0; i < num; i++)
+ to[i] = 0;
+ num *= 2;
+ for (i = 0; i < num; i++) {
+ if ((*from >= '0') && (*from <= '9'))
+ v = *from - '0';
+ else if ((*from >= 'A') && (*from <= 'F'))
+ v = *from - 'A' + 10;
+ else if ((*from >= 'a') && (*from <= 'f'))
+ v = *from - 'a' + 10;
+ else {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS);
+ return (0);
+ }
+ from++;
+ to[i / 2] |= v << (long)((!(i & 1)) * 4);
+ }
+
+ *fromp = from;
+ return (1);
+}
#ifndef OPENSSL_NO_FP_API
int PEM_write(FILE *fp, const char *name, const char *header,
- const unsigned char *data, long len)
- {
- BIO *b;
- int ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_write_bio(b, name, header, data,len);
- BIO_free(b);
- return(ret);
- }
+ const unsigned char *data, long len)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_write_bio(b, name, header, data, len);
+ BIO_free(b);
+ return (ret);
+}
#endif
int PEM_write_bio(BIO *bp, const char *name, const char *header,
- const unsigned char *data, long len)
- {
- int nlen,n,i,j,outl;
- unsigned char *buf = NULL;
- EVP_ENCODE_CTX ctx;
- int reason=ERR_R_BUF_LIB;
-
- EVP_EncodeInit(&ctx);
- nlen=strlen(name);
-
- if ( (BIO_write(bp,"-----BEGIN ",11) != 11) ||
- (BIO_write(bp,name,nlen) != nlen) ||
- (BIO_write(bp,"-----\n",6) != 6))
- goto err;
-
- i=strlen(header);
- if (i > 0)
- {
- if ( (BIO_write(bp,header,i) != i) ||
- (BIO_write(bp,"\n",1) != 1))
- goto err;
- }
-
- buf = OPENSSL_malloc(PEM_BUFSIZE*8);
- if (buf == NULL)
- {
- reason=ERR_R_MALLOC_FAILURE;
- goto err;
- }
-
- i=j=0;
- while (len > 0)
- {
- n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
- EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
- if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
- goto err;
- i+=outl;
- len-=n;
- j+=n;
- }
- EVP_EncodeFinal(&ctx,buf,&outl);
- if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
- OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
- OPENSSL_free(buf);
- buf = NULL;
- if ( (BIO_write(bp,"-----END ",9) != 9) ||
- (BIO_write(bp,name,nlen) != nlen) ||
- (BIO_write(bp,"-----\n",6) != 6))
- goto err;
- return(i+outl);
-err:
- if (buf) {
- OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
- OPENSSL_free(buf);
- }
- OPENSSL_PUT_ERROR(PEM, reason);
- return(0);
- }
+ const unsigned char *data, long len)
+{
+ int nlen, n, i, j, outl;
+ unsigned char *buf = NULL;
+ EVP_ENCODE_CTX ctx;
+ int reason = ERR_R_BUF_LIB;
+
+ EVP_EncodeInit(&ctx);
+ nlen = strlen(name);
+
+ if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
+ (BIO_write(bp, name, nlen) != nlen) ||
+ (BIO_write(bp, "-----\n", 6) != 6))
+ goto err;
+
+ i = strlen(header);
+ if (i > 0) {
+ if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1))
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(PEM_BUFSIZE * 8);
+ if (buf == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+
+ i = j = 0;
+ while (len > 0) {
+ n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len);
+ EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n);
+ if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
+ goto err;
+ i += outl;
+ len -= n;
+ j += n;
+ }
+ EVP_EncodeFinal(&ctx, buf, &outl);
+ if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
+ goto err;
+ OPENSSL_cleanse(buf, PEM_BUFSIZE * 8);
+ OPENSSL_free(buf);
+ buf = NULL;
+ if ((BIO_write(bp, "-----END ", 9) != 9) ||
+ (BIO_write(bp, name, nlen) != nlen) ||
+ (BIO_write(bp, "-----\n", 6) != 6))
+ goto err;
+ return (i + outl);
+ err:
+ if (buf) {
+ OPENSSL_cleanse(buf, PEM_BUFSIZE * 8);
+ OPENSSL_free(buf);
+ }
+ OPENSSL_PUT_ERROR(PEM, reason);
+ return (0);
+}
#ifndef OPENSSL_NO_FP_API
int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
- long *len)
- {
- BIO *b;
- int ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_read_bio(b, name, header, data,len);
- BIO_free(b);
- return(ret);
- }
+ long *len)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_read_bio(b, name, header, data, len);
+ BIO_free(b);
+ return (ret);
+}
#endif
int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
- long *len)
- {
- EVP_ENCODE_CTX ctx;
- int end=0,i,k,bl=0,hl=0,nohead=0;
- char buf[256];
- BUF_MEM *nameB;
- BUF_MEM *headerB;
- BUF_MEM *dataB,*tmpB;
-
- nameB=BUF_MEM_new();
- headerB=BUF_MEM_new();
- dataB=BUF_MEM_new();
- if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
- {
- BUF_MEM_free(nameB);
- BUF_MEM_free(headerB);
- BUF_MEM_free(dataB);
- OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- return(0);
- }
-
- buf[254]='\0';
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
-
- if (i <= 0)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
- goto err;
- }
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (strncmp(buf,"-----BEGIN ",11) == 0)
- {
- i=strlen(&(buf[11]));
-
- if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
- continue;
- if (!BUF_MEM_grow(nameB,i+9))
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memcpy(nameB->data,&(buf[11]),i-6);
- nameB->data[i-6]='\0';
- break;
- }
- }
- hl=0;
- if (!BUF_MEM_grow(headerB,256))
- { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
- headerB->data[0]='\0';
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (buf[0] == '\n') break;
- if (!BUF_MEM_grow(headerB,hl+i+9))
- { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
- if (strncmp(buf,"-----END ",9) == 0)
- {
- nohead=1;
- break;
- }
- memcpy(&(headerB->data[hl]),buf,i);
- headerB->data[hl+i]='\0';
- hl+=i;
- }
-
- bl=0;
- if (!BUF_MEM_grow(dataB,1024))
- { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
- dataB->data[0]='\0';
- if (!nohead)
- {
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (i != 65) end=1;
- if (strncmp(buf,"-----END ",9) == 0)
- break;
- if (i > 65) break;
- if (!BUF_MEM_grow_clean(dataB,i+bl+9))
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memcpy(&(dataB->data[bl]),buf,i);
- dataB->data[bl+i]='\0';
- bl+=i;
- if (end)
- {
- buf[0]='\0';
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- break;
- }
- }
- }
- else
- {
- tmpB=headerB;
- headerB=dataB;
- dataB=tmpB;
- bl=hl;
- }
- i=strlen(nameB->data);
- if ( (strncmp(buf,"-----END ",9) != 0) ||
- (strncmp(nameB->data,&(buf[9]),i) != 0) ||
- (strncmp(&(buf[9+i]),"-----\n",6) != 0))
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
- goto err;
- }
-
- EVP_DecodeInit(&ctx);
- i=EVP_DecodeUpdate(&ctx,
- (unsigned char *)dataB->data,&bl,
- (unsigned char *)dataB->data,bl);
- if (i < 0)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
- goto err;
- }
- i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
- if (i < 0)
- {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
- goto err;
- }
- bl+=k;
-
- if (bl == 0) goto err;
- *name=nameB->data;
- *header=headerB->data;
- *data=(unsigned char *)dataB->data;
- *len=bl;
- OPENSSL_free(nameB);
- OPENSSL_free(headerB);
- OPENSSL_free(dataB);
- return(1);
-err:
- BUF_MEM_free(nameB);
- BUF_MEM_free(headerB);
- BUF_MEM_free(dataB);
- return(0);
- }
-
-/* Check pem string and return prefix length.
- * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
- * the return value is 3 for the string "RSA".
- */
-
-int pem_check_suffix(const char *pem_str, const char *suffix)
- {
- int pem_len = strlen(pem_str);
- int suffix_len = strlen(suffix);
- const char *p;
- if (suffix_len + 1 >= pem_len)
- return 0;
- p = pem_str + pem_len - suffix_len;
- if (strcmp(p, suffix))
- return 0;
- p--;
- if (*p != ' ')
- return 0;
- return p - pem_str;
- }
+ long *len)
+{
+ EVP_ENCODE_CTX ctx;
+ int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
+ char buf[256];
+ BUF_MEM *nameB;
+ BUF_MEM *headerB;
+ BUF_MEM *dataB, *tmpB;
+
+ nameB = BUF_MEM_new();
+ headerB = BUF_MEM_new();
+ dataB = BUF_MEM_new();
+ if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
+ BUF_MEM_free(nameB);
+ BUF_MEM_free(headerB);
+ BUF_MEM_free(dataB);
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+
+ buf[254] = '\0';
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+
+ if (i <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
+ goto err;
+ }
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (strncmp(buf, "-----BEGIN ", 11) == 0) {
+ i = strlen(&(buf[11]));
+
+ if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
+ continue;
+ if (!BUF_MEM_grow(nameB, i + 9)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(nameB->data, &(buf[11]), i - 6);
+ nameB->data[i - 6] = '\0';
+ break;
+ }
+ }
+ hl = 0;
+ if (!BUF_MEM_grow(headerB, 256)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ headerB->data[0] = '\0';
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (buf[0] == '\n')
+ break;
+ if (!BUF_MEM_grow(headerB, hl + i + 9)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (strncmp(buf, "-----END ", 9) == 0) {
+ nohead = 1;
+ break;
+ }
+ memcpy(&(headerB->data[hl]), buf, i);
+ headerB->data[hl + i] = '\0';
+ hl += i;
+ }
+
+ bl = 0;
+ if (!BUF_MEM_grow(dataB, 1024)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ dataB->data[0] = '\0';
+ if (!nohead) {
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (i != 65)
+ end = 1;
+ if (strncmp(buf, "-----END ", 9) == 0)
+ break;
+ if (i > 65)
+ break;
+ if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(&(dataB->data[bl]), buf, i);
+ dataB->data[bl + i] = '\0';
+ bl += i;
+ if (end) {
+ buf[0] = '\0';
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ break;
+ }
+ }
+ } else {
+ tmpB = headerB;
+ headerB = dataB;
+ dataB = tmpB;
+ bl = hl;
+ }
+ i = strlen(nameB->data);
+ if ((strncmp(buf, "-----END ", 9) != 0) ||
+ (strncmp(nameB->data, &(buf[9]), i) != 0) ||
+ (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
+ goto err;
+ }
+
+ EVP_DecodeInit(&ctx);
+ i = EVP_DecodeUpdate(&ctx,
+ (unsigned char *)dataB->data, &bl,
+ (unsigned char *)dataB->data, bl);
+ if (i < 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
+ goto err;
+ }
+ i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
+ if (i < 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
+ goto err;
+ }
+ bl += k;
+
+ if (bl == 0)
+ goto err;
+ *name = nameB->data;
+ *header = headerB->data;
+ *data = (unsigned char *)dataB->data;
+ *len = bl;
+ OPENSSL_free(nameB);
+ OPENSSL_free(headerB);
+ OPENSSL_free(dataB);
+ return (1);
+ err:
+ BUF_MEM_free(nameB);
+ BUF_MEM_free(headerB);
+ BUF_MEM_free(dataB);
+ return (0);
+}
int PEM_def_callback(char *buf, int size, int rwflag, void *userdata)
- {
- if (!buf || !userdata)
- {
- return 0;
- }
- size_t len = strlen((char *) userdata);
- if (len >= (size_t) size)
- {
- return 0;
- }
- strcpy(buf, (char *) userdata);
- return len;
- }
+{
+ if (!buf || !userdata) {
+ return 0;
+ }
+ size_t len = strlen((char *)userdata);
+ if (len >= (size_t)size) {
+ return 0;
+ }
+ strcpy(buf, (char *)userdata);
+ return len;
+}
diff --git a/src/crypto/pem/pem_oth.c b/src/crypto/pem/pem_oth.c
index 3e8f6bda..8530c567 100644
--- a/src/crypto/pem/pem_oth.c
+++ b/src/crypto/pem/pem_oth.c
@@ -67,23 +67,22 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-
/* Handle 'other' PEMs: not private keys */
void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
- pem_password_cb *cb, void *u)
- {
- const unsigned char *p=NULL;
- unsigned char *data=NULL;
- long len;
- char *ret=NULL;
+ pem_password_cb *cb, void *u)
+{
+ const unsigned char *p = NULL;
+ unsigned char *data = NULL;
+ long len;
+ char *ret = NULL;
- if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u))
- return NULL;
- p = data;
- ret=d2i(x,&p,len);
- if (ret == NULL)
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- OPENSSL_free(data);
- return ret;
- }
+ if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u))
+ return NULL;
+ p = data;
+ ret = d2i(x, &p, len);
+ if (ret == NULL)
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ OPENSSL_free(data);
+ return ret;
+}
diff --git a/src/crypto/pem/pem_pk8.c b/src/crypto/pem/pem_pk8.c
index 08244772..550661d6 100644
--- a/src/crypto/pem/pem_pk8.c
+++ b/src/crypto/pem/pem_pk8.c
@@ -65,180 +65,193 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-
static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder,
- int nid, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u);
+ int nid, const EVP_CIPHER *enc,
+ char *kstr, int klen, pem_password_cb *cb, void *u);
static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
- int nid, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u);
+ int nid, const EVP_CIPHER *enc,
+ char *kstr, int klen, pem_password_cb *cb, void *u);
-/* These functions write a private key in PKCS#8 format: it is a "drop in"
+/*
+ * These functions write a private key in PKCS#8 format: it is a "drop in"
* replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
* is NULL then it uses the unencrypted private key form. The 'nid' versions
* uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
*/
int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
}
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
}
int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
}
int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
}
-static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid,
+ const EVP_CIPHER *enc, char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- X509_SIG *p8;
- PKCS8_PRIV_KEY_INFO *p8inf;
- char buf[PEM_BUFSIZE];
- int ret;
- if(!(p8inf = EVP_PKEY2PKCS8(x))) {
- OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
- return 0;
- }
- if(enc || (nid != -1)) {
- if(!kstr) {
- klen = 0;
- if (!cb) cb = PEM_def_callback;
- klen = cb(buf, PEM_BUFSIZE, 1, u);
- if(klen <= 0) {
- OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- return 0;
- }
-
- kstr = buf;
- }
- p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
- if(kstr == buf) OPENSSL_cleanse(buf, klen);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- if(isder) ret = i2d_PKCS8_bio(bp, p8);
- else ret = PEM_write_bio_PKCS8(bp, p8);
- X509_SIG_free(p8);
- return ret;
- } else {
- if(isder) ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
- else ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- return ret;
- }
+ X509_SIG *p8;
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ char buf[PEM_BUFSIZE];
+ int ret;
+ if (!(p8inf = EVP_PKEY2PKCS8(x))) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+ return 0;
+ }
+ if (enc || (nid != -1)) {
+ if (!kstr) {
+ klen = 0;
+ if (!cb)
+ cb = PEM_def_callback;
+ klen = cb(buf, PEM_BUFSIZE, 1, u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 0;
+ }
+
+ kstr = buf;
+ }
+ p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
+ if (kstr == buf)
+ OPENSSL_cleanse(buf, klen);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (isder)
+ ret = i2d_PKCS8_bio(bp, p8);
+ else
+ ret = PEM_write_bio_PKCS8(bp, p8);
+ X509_SIG_free(p8);
+ return ret;
+ } else {
+ if (isder)
+ ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+ else
+ ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+ }
}
-EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
{
- PKCS8_PRIV_KEY_INFO *p8inf = NULL;
- X509_SIG *p8 = NULL;
- int klen;
- EVP_PKEY *ret;
- char psbuf[PEM_BUFSIZE];
- p8 = d2i_PKCS8_bio(bp, NULL);
- if(!p8) return NULL;
-
- klen = 0;
- if (!cb) cb = PEM_def_callback;
- klen=cb(psbuf,PEM_BUFSIZE,0,u);
- if (klen <= 0) {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
- X509_SIG_free(p8);
- return NULL;
- }
- p8inf = PKCS8_decrypt(p8, psbuf, klen);
- X509_SIG_free(p8);
- if(!p8inf) return NULL;
- ret = EVP_PKCS82PKEY(p8inf);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- if(!ret) return NULL;
- if(x) {
- if(*x) EVP_PKEY_free(*x);
- *x = ret;
- }
- return ret;
+ PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+ X509_SIG *p8 = NULL;
+ int klen;
+ EVP_PKEY *ret;
+ char psbuf[PEM_BUFSIZE];
+ p8 = d2i_PKCS8_bio(bp, NULL);
+ if (!p8)
+ return NULL;
+
+ klen = 0;
+ if (!cb)
+ cb = PEM_def_callback;
+ klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+ X509_SIG_free(p8);
+ return NULL;
+ }
+ p8inf = PKCS8_decrypt(p8, psbuf, klen);
+ X509_SIG_free(p8);
+ if (!p8inf)
+ return NULL;
+ ret = EVP_PKCS82PKEY(p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (!ret)
+ return NULL;
+ if (x) {
+ if (*x)
+ EVP_PKEY_free(*x);
+ *x = ret;
+ }
+ return ret;
}
#ifndef OPENSSL_NO_FP_API
int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen, pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
}
int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
}
int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
}
int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u)
+ char *kstr, int klen, pem_password_cb *cb,
+ void *u)
{
- return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
}
-static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc,
- char *kstr, int klen,
- pem_password_cb *cb, void *u)
+static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid,
+ const EVP_CIPHER *enc, char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- BIO *bp;
- int ret;
- if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
- BIO_free(bp);
- return ret;
+ BIO *bp;
+ int ret;
+ if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
+ BIO_free(bp);
+ return ret;
}
-EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
{
- BIO *bp;
- EVP_PKEY *ret;
- if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return NULL;
- }
- ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
- BIO_free(bp);
- return ret;
+ BIO *bp;
+ EVP_PKEY *ret;
+ if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return NULL;
+ }
+ ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
+ BIO_free(bp);
+ return ret;
}
#endif
IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
+
+
IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
- PKCS8_PRIV_KEY_INFO)
+ PKCS8_PRIV_KEY_INFO)
diff --git a/src/crypto/pem/pem_pkey.c b/src/crypto/pem/pem_pkey.c
index cd334b4d..058c0311 100644
--- a/src/crypto/pem/pem_pkey.c
+++ b/src/crypto/pem/pem_pkey.c
@@ -69,240 +69,159 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
-
-
-int pem_check_suffix(const char *pem_str, const char *suffix);
-
-EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
- {
- char *nm=NULL;
- const unsigned char *p=NULL;
- unsigned char *data=NULL;
- long len;
- int slen;
- EVP_PKEY *ret=NULL;
-
- if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
- return NULL;
- p = data;
-
- if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
- PKCS8_PRIV_KEY_INFO *p8inf;
- p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
- if(!p8inf) goto p8err;
- ret = EVP_PKCS82PKEY(p8inf);
- if(x) {
- if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
- *x = ret;
- }
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else if (strcmp(nm,PEM_STRING_PKCS8) == 0) {
- PKCS8_PRIV_KEY_INFO *p8inf;
- X509_SIG *p8;
- int klen;
- char psbuf[PEM_BUFSIZE];
- p8 = d2i_X509_SIG(NULL, &p, len);
- if(!p8) goto p8err;
-
- klen = 0;
- if (!cb) cb = PEM_def_callback;
- klen=cb(psbuf,PEM_BUFSIZE,0,u);
- if (klen <= 0) {
- OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
- X509_SIG_free(p8);
- goto err;
- }
- p8inf = PKCS8_decrypt(p8, psbuf, klen);
- X509_SIG_free(p8);
- if(!p8inf) goto p8err;
- ret = EVP_PKCS82PKEY(p8inf);
- if(x) {
- if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
- *x = ret;
- }
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0)
- {
- const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
- if (!ameth || !ameth->old_priv_decode)
- goto p8err;
- ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);
- }
-p8err:
- if (ret == NULL)
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-
-err:
- OPENSSL_free(nm);
- OPENSSL_cleanse(data, len);
- OPENSSL_free(data);
- return(ret);
- }
-
-int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
- pem_password_cb *cb, void *u)
- {
- char pem_str[80];
- if (!x->ameth || x->ameth->priv_encode)
- return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
- (char *)kstr, klen,
- cb, u);
-
- BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
- pem_str,bp,x,enc,kstr,klen,cb,u);
- }
-
-static int public_key_type_from_str(const char *name, size_t len) {
- if (len == 3 && memcmp(name, "RSA", 3) == 0) {
- return EVP_PKEY_RSA;
- } else if (len == 2 && memcmp(name, "DH", 2) == 0) {
- return EVP_PKEY_DH;
- } else if (len == 2 && memcmp(name, "EC", 2) == 0) {
- return EVP_PKEY_EC;
- }
- return NID_undef;
+EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
+{
+ char *nm = NULL;
+ const unsigned char *p = NULL;
+ unsigned char *data = NULL;
+ long len;
+ EVP_PKEY *ret = NULL;
+
+ if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
+ return NULL;
+ p = data;
+
+ if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
+ if (!p8inf)
+ goto p8err;
+ ret = EVP_PKCS82PKEY(p8inf);
+ if (x) {
+ if (*x)
+ EVP_PKEY_free((EVP_PKEY *)*x);
+ *x = ret;
+ }
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ X509_SIG *p8;
+ int klen;
+ char psbuf[PEM_BUFSIZE];
+ p8 = d2i_X509_SIG(NULL, &p, len);
+ if (!p8)
+ goto p8err;
+
+ klen = 0;
+ if (!cb)
+ cb = PEM_def_callback;
+ klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+ X509_SIG_free(p8);
+ goto err;
+ }
+ p8inf = PKCS8_decrypt(p8, psbuf, klen);
+ X509_SIG_free(p8);
+ if (!p8inf)
+ goto p8err;
+ ret = EVP_PKCS82PKEY(p8inf);
+ if (x) {
+ if (*x)
+ EVP_PKEY_free((EVP_PKEY *)*x);
+ *x = ret;
+ }
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
+ /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
+ * standalone format. This and the cases below probably should not
+ * accept PKCS#8. */
+ ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
+ } else if (strcmp(nm, PEM_STRING_EC) == 0) {
+ ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);
+ } else if (strcmp(nm, PEM_STRING_DSA) == 0) {
+ ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len);
+ }
+ p8err:
+ if (ret == NULL)
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+
+ err:
+ OPENSSL_free(nm);
+ OPENSSL_cleanse(data, len);
+ OPENSSL_free(data);
+ return (ret);
}
-static int set_pkey_type_from_str(EVP_PKEY *pkey, const char *name, size_t len) {
- int nid = public_key_type_from_str(name, len);
- if (nid == NID_undef) {
- return 0;
- }
- return EVP_PKEY_set_type(pkey, nid);
+int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u);
}
-EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
- {
- char *nm=NULL;
- const unsigned char *p=NULL;
- unsigned char *data=NULL;
- long len;
- int slen;
- EVP_PKEY *ret=NULL;
-
- if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS,
- bp, 0, NULL))
- return NULL;
- p = data;
-
- if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0)
- {
- ret = EVP_PKEY_new();
- if (!ret)
- goto err;
- if (!set_pkey_type_from_str(ret, nm, slen)
- || !ret->ameth->param_decode
- || !ret->ameth->param_decode(ret, &p, len))
- {
- EVP_PKEY_free(ret);
- ret = NULL;
- goto err;
- }
- if(x)
- {
- if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
- *x = ret;
- }
- }
-err:
- if (ret == NULL)
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- OPENSSL_free(nm);
- OPENSSL_free(data);
- return(ret);
- }
-
-int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
- {
- char pem_str[80];
- if (!x->ameth || !x->ameth->param_encode)
- return 0;
-
- BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
- return PEM_ASN1_write_bio(
- (i2d_of_void *)x->ameth->param_encode,
- pem_str,bp,x,NULL,NULL,0,0,NULL);
- }
-
#ifndef OPENSSL_NO_FP_API
-EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
- {
- BIO *b;
- EVP_PKEY *ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_read_bio_PrivateKey(b,x,cb,u);
- BIO_free(b);
- return(ret);
- }
+EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
+{
+ BIO *b;
+ EVP_PKEY *ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_read_bio_PrivateKey(b, x, cb, u);
+ BIO_free(b);
+ return (ret);
+}
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
- pem_password_cb *cb, void *u)
- {
- BIO *b;
- int ret;
-
- if ((b=BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return 0;
- }
- ret=PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
- BIO_free(b);
- return ret;
- }
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return 0;
+ }
+ ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+ BIO_free(b);
+ return ret;
+}
#endif
-
/* Transparently read in PKCS#3 or X9.42 DH parameters */
DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
- {
- char *nm=NULL;
- const unsigned char *p=NULL;
- unsigned char *data=NULL;
- long len;
- DH *ret=NULL;
-
- if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS,
- bp, cb, u))
- return NULL;
- p = data;
-
- ret = d2i_DHparams(x, &p, len);
-
- if (ret == NULL)
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- OPENSSL_free(nm);
- OPENSSL_free(data);
- return ret;
- }
+{
+ char *nm = NULL;
+ const unsigned char *p = NULL;
+ unsigned char *data = NULL;
+ long len;
+ DH *ret = NULL;
+
+ if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u))
+ return NULL;
+ p = data;
+
+ ret = d2i_DHparams(x, &p, len);
+
+ if (ret == NULL)
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ OPENSSL_free(nm);
+ OPENSSL_free(data);
+ return ret;
+}
#ifndef OPENSSL_NO_FP_API
DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
- {
- BIO *b;
- DH *ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=PEM_read_bio_DHparams(b,x,cb,u);
- BIO_free(b);
- return(ret);
- }
+{
+ BIO *b;
+ DH *ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_read_bio_DHparams(b, x, cb, u);
+ BIO_free(b);
+ return (ret);
+}
#endif
diff --git a/src/crypto/pem/pem_x509.c b/src/crypto/pem/pem_x509.c
index f4630472..97f814db 100644
--- a/src/crypto/pem/pem_x509.c
+++ b/src/crypto/pem/pem_x509.c
@@ -1,6 +1,7 @@
/* pem_x509.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
*/
/* ====================================================================
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
@@ -61,5 +62,4 @@
#include <openssl/pem.h>
#include <openssl/x509.h>
-
IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509)
diff --git a/src/crypto/pem/pem_xaux.c b/src/crypto/pem/pem_xaux.c
index 8dabd41e..386dd60d 100644
--- a/src/crypto/pem/pem_xaux.c
+++ b/src/crypto/pem/pem_xaux.c
@@ -1,6 +1,7 @@
/* pem_xaux.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
*/
/* ====================================================================
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
@@ -61,6 +62,6 @@
#include <openssl/pem.h>
#include <openssl/x509.h>
-
IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX)
-IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR, X509_CERT_PAIR)
+IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR,
+ X509_CERT_PAIR)
diff --git a/src/crypto/perlasm/arm-xlate.pl b/src/crypto/perlasm/arm-xlate.pl
index 706fa708..6e9b0199 100755
--- a/src/crypto/perlasm/arm-xlate.pl
+++ b/src/crypto/perlasm/arm-xlate.pl
@@ -55,7 +55,9 @@ my $globl = sub {
};
}
- $ret = ".globl $name" if (!$ret);
+ $ret = ".globl $name\n";
+ # All symbols in assembly files are hidden.
+ $ret .= &$hidden($name);
$$global = $name;
$ret;
};
@@ -165,6 +167,6 @@ while($line=<>) {
print "\n";
}
-print "#endif" if ($flavour eq "linux32" || $flavour eq "linux64");
+print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64");
close STDOUT;
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index 3ebb0184..4965985d 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -190,14 +190,17 @@ my %globals;
sub out {
my $self = shift;
+ $self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig;
if ($gas) {
# Solaris /usr/ccs/bin/as can't handle multiplications
# in $self->{value}
- $self->{value} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
- $self->{value} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
+ my $value = $self->{value};
+ $value =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
+ if ($value =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg) {
+ $self->{value} = $value;
+ }
sprintf "\$%s",$self->{value};
} else {
- $self->{value} =~ s/(0b[0-1]+)/oct($1)/eig;
$self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
sprintf "%s",$self->{value};
}
diff --git a/src/crypto/perlasm/x86gas.pl b/src/crypto/perlasm/x86gas.pl
index 99d7c1bd..55d09d8b 100644
--- a/src/crypto/perlasm/x86gas.pl
+++ b/src/crypto/perlasm/x86gas.pl
@@ -17,7 +17,7 @@ sub opsize()
{ my $reg=shift;
if ($reg =~ m/^%e/o) { "l"; }
elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; }
- elsif ($reg =~ m/^%[xm]/o) { undef; }
+ elsif ($reg =~ m/^%[yxm]/o) { undef; }
else { "w"; }
}
diff --git a/src/crypto/pkcs8/CMakeLists.txt b/src/crypto/pkcs8/CMakeLists.txt
index 95501099..ffb38218 100644
--- a/src/crypto/pkcs8/CMakeLists.txt
+++ b/src/crypto/pkcs8/CMakeLists.txt
@@ -1,7 +1,7 @@
include_directories(../../include)
add_library(
- pkcs8
+ pkcs8_lib
OBJECT
diff --git a/src/crypto/pkcs8/p5_pbe.c b/src/crypto/pkcs8/p5_pbe.c
index 653cabf3..8e56d41b 100644
--- a/src/crypto/pkcs8/p5_pbe.c
+++ b/src/crypto/pkcs8/p5_pbe.c
@@ -57,6 +57,7 @@
#include <openssl/asn1t.h>
#include <openssl/err.h>
+#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
diff --git a/src/crypto/pkcs8/p5_pbev2.c b/src/crypto/pkcs8/p5_pbev2.c
index fec0d86d..3799b39b 100644
--- a/src/crypto/pkcs8/p5_pbev2.c
+++ b/src/crypto/pkcs8/p5_pbev2.c
@@ -61,6 +61,7 @@
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
diff --git a/src/crypto/pkcs8/pkcs12_test.cc b/src/crypto/pkcs8/pkcs12_test.cc
index 55006b4d..17bcd273 100644
--- a/src/crypto/pkcs8/pkcs12_test.cc
+++ b/src/crypto/pkcs8/pkcs12_test.cc
@@ -708,7 +708,7 @@ static bool Test(const char *name, const uint8_t *der, size_t der_len) {
}
static bool TestCompat(const uint8_t *der, size_t der_len) {
- ScopedBIO bio(BIO_new_mem_buf((void*) der, der_len));
+ ScopedBIO bio(BIO_new_mem_buf(der, der_len));
if (!bio) {
return false;
}
@@ -757,7 +757,6 @@ static bool TestCompat(const uint8_t *der, size_t der_len) {
int main(int argc, char **argv) {
CRYPTO_library_init();
- ERR_load_crypto_strings();
if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
!Test("NSS", kNSS, sizeof(kNSS)) ||
diff --git a/src/crypto/pkcs8/pkcs8.c b/src/crypto/pkcs8/pkcs8.c
index 31a34a7c..4ecf17f8 100644
--- a/src/crypto/pkcs8/pkcs8.c
+++ b/src/crypto/pkcs8/pkcs8.c
@@ -60,18 +60,18 @@
#include <string.h>
#include <openssl/asn1.h>
-#include <openssl/bn.h>
#include <openssl/buf.h>
+#include <openssl/bytestring.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
+#include <openssl/obj.h>
#include <openssl/x509.h>
#include "internal.h"
#include "../bytestring/internal.h"
-#include "../evp/internal.h"
#define PKCS12_KEY_ID 1
@@ -106,112 +106,122 @@ static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
const uint8_t *salt, size_t salt_len,
- int id, int iterations,
+ uint8_t id, int iterations,
size_t out_len, uint8_t *out,
- const EVP_MD *md_type) {
- uint8_t *B, *D, *I, *p, *Ai;
- int Slen, Plen, Ilen, Ijlen;
- int i, j, v;
- size_t u;
- int ret = 0;
- BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */
- EVP_MD_CTX ctx;
+ const EVP_MD *md) {
+ /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the
+ * specification have errata applied and other typos fixed. */
- EVP_MD_CTX_init(&ctx);
- v = EVP_MD_block_size(md_type);
- u = EVP_MD_size(md_type);
- D = OPENSSL_malloc(v);
- Ai = OPENSSL_malloc(u);
- B = OPENSSL_malloc(v + 1);
- Slen = v * ((salt_len + v - 1) / v);
- if (pass_raw_len) {
- Plen = v * ((pass_raw_len + v - 1) / v);
- } else {
- Plen = 0;
+ if (iterations < 1) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
+ return 0;
}
- Ilen = Slen + Plen;
- I = OPENSSL_malloc(Ilen);
- Ij = BN_new();
- Bpl1 = BN_new();
- if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
- goto err;
+
+ /* In the spec, |block_size| is called "v", but measured in bits. */
+ size_t block_size = EVP_MD_block_size(md);
+
+ /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies
+ * of ID. */
+ uint8_t D[EVP_MAX_MD_BLOCK_SIZE];
+ memset(D, id, block_size);
+
+ /* 2. Concatenate copies of the salt together to create a string S of length
+ * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to
+ * create S). Note that if the salt is the empty string, then so is S.
+ *
+ * 3. Concatenate copies of the password together to create a string P of
+ * length v(ceiling(p/v)) bits (the final copy of the password may be
+ * truncated to create P). Note that if the password is the empty string,
+ * then so is P.
+ *
+ * 4. Set I=S||P to be the concatenation of S and P. */
+ if (salt_len + block_size - 1 < salt_len ||
+ pass_raw_len + block_size - 1 < pass_raw_len) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+ return 0;
}
- for (i = 0; i < v; i++) {
- D[i] = id;
+ size_t S_len = block_size * ((salt_len + block_size - 1) / block_size);
+ size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size);
+ size_t I_len = S_len + P_len;
+ if (I_len < S_len) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+ return 0;
}
- p = I;
- for (i = 0; i < Slen; i++) {
- *p++ = salt[i % salt_len];
+
+ uint8_t *I = OPENSSL_malloc(I_len);
+ if (I_len != 0 && I == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- for (i = 0; i < Plen; i++) {
- *p++ = pass_raw[i % pass_raw_len];
+
+ size_t i;
+ for (i = 0; i < S_len; i++) {
+ I[i] = salt[i % salt_len];
}
- for (;;) {
- if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
- !EVP_DigestUpdate(&ctx, D, v) ||
- !EVP_DigestUpdate(&ctx, I, Ilen) ||
- !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ for (i = 0; i < P_len; i++) {
+ I[i + S_len] = pass_raw[i % pass_raw_len];
+ }
+
+ int ret = 0;
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+
+ while (out_len != 0) {
+ /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I,
+ * H(H(H(... H(D||I)))) */
+ uint8_t A[EVP_MAX_MD_SIZE];
+ unsigned A_len;
+ if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+ !EVP_DigestUpdate(&ctx, D, block_size) ||
+ !EVP_DigestUpdate(&ctx, I, I_len) ||
+ !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
goto err;
}
- for (j = 1; j < iterations; j++) {
- if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
- !EVP_DigestUpdate(&ctx, Ai, u) ||
- !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ int iter;
+ for (iter = 1; iter < iterations; iter++) {
+ if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+ !EVP_DigestUpdate(&ctx, A, A_len) ||
+ !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
goto err;
}
}
- memcpy(out, Ai, out_len < u ? out_len : u);
- if (u >= out_len) {
- ret = 1;
- goto end;
- }
- out_len -= u;
- out += u;
- for (j = 0; j < v; j++) {
- B[j] = Ai[j % u];
+
+ size_t todo = out_len < A_len ? out_len : A_len;
+ memcpy(out, A, todo);
+ out += todo;
+ out_len -= todo;
+ if (out_len == 0) {
+ break;
}
- /* Work out B + 1 first then can use B as tmp space */
- if (!BN_bin2bn(B, v, Bpl1) ||
- !BN_add_word(Bpl1, 1)) {
- goto err;
+
+ /* B. Concatenate copies of A_i to create a string B of length v bits (the
+ * final copy of A_i may be truncated to create B). */
+ uint8_t B[EVP_MAX_MD_BLOCK_SIZE];
+ for (i = 0; i < block_size; i++) {
+ B[i] = A[i % A_len];
}
- for (j = 0; j < Ilen; j += v) {
- if (!BN_bin2bn(I + j, v, Ij) ||
- !BN_add(Ij, Ij, Bpl1) ||
- !BN_bn2bin(Ij, B)) {
- goto err;
- }
- Ijlen = BN_num_bytes(Ij);
- /* If more than 2^(v*8) - 1 cut off MSB */
- if (Ijlen > v) {
- if (!BN_bn2bin(Ij, B)) {
- goto err;
- }
- memcpy(I + j, B + 1, v);
- /* If less than v bytes pad with zeroes */
- } else if (Ijlen < v) {
- memset(I + j, 0, v - Ijlen);
- if (!BN_bn2bin(Ij, I + j + v - Ijlen)) {
- goto err;
- }
- } else if (!BN_bn2bin(Ij, I + j)) {
- goto err;
+
+ /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks,
+ * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod
+ * 2^v for each j. */
+ assert(I_len % block_size == 0);
+ for (i = 0; i < I_len; i += block_size) {
+ unsigned carry = 1;
+ size_t j;
+ for (j = block_size - 1; j < block_size; j--) {
+ carry += I[i + j] + B[j];
+ I[i + j] = (uint8_t)carry;
+ carry >>= 8;
}
}
}
-err:
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ ret = 1;
-end:
- OPENSSL_free(Ai);
- OPENSSL_free(B);
- OPENSSL_free(D);
+err:
+ OPENSSL_cleanse(I, I_len);
OPENSSL_free(I);
- BN_free(Ij);
- BN_free(Bpl1);
EVP_MD_CTX_cleanup(&ctx);
-
return ret;
}
@@ -591,72 +601,52 @@ err:
}
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
- EVP_PKEY *pkey = NULL;
- ASN1_OBJECT *algoid;
- char obj_tmp[80];
-
- if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) {
+ uint8_t *der = NULL;
+ int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
+ if (der_len < 0) {
return NULL;
}
- pkey = EVP_PKEY_new();
- if (pkey == NULL) {
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ CBS cbs;
+ CBS_init(&cbs, der, (size_t)der_len);
+ EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+ if (ret == NULL || CBS_len(&cbs) != 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+ EVP_PKEY_free(ret);
+ OPENSSL_free(der);
return NULL;
}
- if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
- ERR_add_error_data(2, "TYPE=", obj_tmp);
- goto error;
- }
-
- if (pkey->ameth->priv_decode) {
- if (!pkey->ameth->priv_decode(pkey, p8)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_DECODE_ERROR);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
-
- return pkey;
-
-error:
- EVP_PKEY_free(pkey);
- return NULL;
+ OPENSSL_free(der);
+ return ret;
}
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
- PKCS8_PRIV_KEY_INFO *p8;
-
- p8 = PKCS8_PRIV_KEY_INFO_new();
- if (p8 == NULL) {
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
- return NULL;
+ CBB cbb;
+ uint8_t *der = NULL;
+ size_t der_len;
+ if (!CBB_init(&cbb, 0) ||
+ !EVP_marshal_private_key(&cbb, pkey) ||
+ !CBB_finish(&cbb, &der, &der_len) ||
+ der_len > LONG_MAX) {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
+ goto err;
}
- p8->broken = PKCS8_OK;
- if (pkey->ameth) {
- if (pkey->ameth->priv_encode) {
- if (!pkey->ameth->priv_encode(p8, pkey)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
- } else {
- OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- goto error;
+ const uint8_t *p = der;
+ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len);
+ if (p8 == NULL || p != der + der_len) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+ goto err;
}
+
+ OPENSSL_free(der);
return p8;
-error:
- PKCS8_PRIV_KEY_INFO_free(p8);
+err:
+ OPENSSL_free(der);
return NULL;
}
@@ -737,6 +727,7 @@ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
struct pkcs12_context *ctx) {
CBS content_type, wrapped_contents, contents, content_infos;
int nid, ret = 0;
+ uint8_t *storage = NULL;
if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(content_info, &wrapped_contents,
@@ -767,8 +758,9 @@ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
/* AlgorithmIdentifier, see
* https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
!CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&eci, &encrypted_contents,
- CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
+ !CBS_get_asn1_implicit_string(
+ &eci, &encrypted_contents, &storage,
+ CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -895,6 +887,7 @@ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
}
err:
+ OPENSSL_free(storage);
return ret;
}
@@ -975,7 +968,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
ctx.out_key = out_key;
ctx.out_certs = out_certs;
- if (!ascii_to_ucs2(password, strlen(password), &ctx.password,
+ if (!ascii_to_ucs2(password, password ? strlen(password) : 0, &ctx.password,
&ctx.password_len)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
goto err;
@@ -1066,9 +1059,6 @@ struct pkcs12_st {
PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) {
PKCS12 *p12;
- /* out_p12 must be NULL because we don't export the PKCS12 structure. */
- assert(out_p12 == NULL);
-
p12 = OPENSSL_malloc(sizeof(PKCS12));
if (!p12) {
return NULL;
@@ -1084,6 +1074,12 @@ PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len)
p12->ber_len = ber_len;
*ber_bytes += ber_len;
+ if (out_p12) {
+ PKCS12_free(*out_p12);
+
+ *out_p12 = p12;
+ }
+
return p12;
}
@@ -1105,7 +1101,12 @@ PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
for (;;) {
int n = BIO_read(bio, &buf->data[used], buf->length - used);
if (n < 0) {
- goto out;
+ if (used == 0) {
+ goto out;
+ }
+ /* Workaround a bug in node.js. It uses a memory BIO for this in the wrong
+ * mode. */
+ n = 0;
}
if (n == 0) {
@@ -1212,6 +1213,9 @@ int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
}
void PKCS12_free(PKCS12 *p12) {
+ if (p12 == NULL) {
+ return;
+ }
OPENSSL_free(p12->ber_bytes);
OPENSSL_free(p12);
}
diff --git a/src/crypto/poly1305/asm/poly1305-armv4.pl b/src/crypto/poly1305/asm/poly1305-armv4.pl
new file mode 100755
index 00000000..9b765cec
--- /dev/null
+++ b/src/crypto/poly1305/asm/poly1305-armv4.pl
@@ -0,0 +1,1216 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# IALU(*)/gcc-4.4 NEON
+#
+# ARM11xx(ARMv6) 7.78/+100% -
+# Cortex-A5 6.30/+130% 2.96
+# Cortex-A8 6.25/+115% 2.36
+# Cortex-A9 5.10/+95% 2.55
+# Cortex-A15 3.79/+85% 1.25(**)
+# Snapdragon S4 5.70/+100% 1.48(**)
+#
+# (*) this is for -march=armv6, i.e. with bunch of ldrb loading data;
+# (**) these are trade-off results, they can be improved by ~8% but at
+# the cost of 15/12% regression on Cortex-A5/A7, it's even possible
+# to improve Cortex-A9 result, but then A5/A7 loose more than 20%;
+
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
+
+($ctx,$inp,$len,$padbit)=map("r$_",(0..3));
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+#else
+.code 32
+#endif
+
+.globl poly1305_emit
+.globl poly1305_blocks
+.globl poly1305_init
+.type poly1305_init,%function
+.align 5
+poly1305_init:
+.Lpoly1305_init:
+ stmdb sp!,{r4-r11}
+
+ eor r3,r3,r3
+ cmp $inp,#0
+ str r3,[$ctx,#0] @ zero hash value
+ str r3,[$ctx,#4]
+ str r3,[$ctx,#8]
+ str r3,[$ctx,#12]
+ str r3,[$ctx,#16]
+ str r3,[$ctx,#36] @ is_base2_26
+ add $ctx,$ctx,#20
+
+#ifdef __thumb2__
+ it eq
+#endif
+ moveq r0,#0
+ beq .Lno_key
+
+#if __ARM_MAX_ARCH__>=7
+ adr r11,.Lpoly1305_init
+ ldr r12,.LOPENSSL_armcap
+#endif
+ ldrb r4,[$inp,#0]
+ mov r10,#0x0fffffff
+ ldrb r5,[$inp,#1]
+ and r3,r10,#-4 @ 0x0ffffffc
+ ldrb r6,[$inp,#2]
+ ldrb r7,[$inp,#3]
+ orr r4,r4,r5,lsl#8
+ ldrb r5,[$inp,#4]
+ orr r4,r4,r6,lsl#16
+ ldrb r6,[$inp,#5]
+ orr r4,r4,r7,lsl#24
+ ldrb r7,[$inp,#6]
+ and r4,r4,r10
+
+#if __ARM_MAX_ARCH__>=7
+ ldr r12,[r11,r12] @ OPENSSL_armcap_P
+# ifdef __APPLE__
+ ldr r12,[r12]
+# endif
+#endif
+ ldrb r8,[$inp,#7]
+ orr r5,r5,r6,lsl#8
+ ldrb r6,[$inp,#8]
+ orr r5,r5,r7,lsl#16
+ ldrb r7,[$inp,#9]
+ orr r5,r5,r8,lsl#24
+ ldrb r8,[$inp,#10]
+ and r5,r5,r3
+
+#if __ARM_MAX_ARCH__>=7
+ tst r12,#ARMV7_NEON @ check for NEON
+# ifdef __APPLE__
+ adr r9,poly1305_blocks_neon
+ adr r11,poly1305_blocks
+# ifdef __thumb2__
+ it ne
+# endif
+ movne r11,r9
+ adr r12,poly1305_emit
+ adr r10,poly1305_emit_neon
+# ifdef __thumb2__
+ it ne
+# endif
+ movne r12,r10
+# else
+# ifdef __thumb2__
+ itete eq
+# endif
+ addeq r12,r11,#(poly1305_emit-.Lpoly1305_init)
+ addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init)
+ addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init)
+ addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init)
+# endif
+# ifdef __thumb2__
+ orr r12,r12,#1 @ thumb-ify address
+ orr r11,r11,#1
+# endif
+#endif
+ ldrb r9,[$inp,#11]
+ orr r6,r6,r7,lsl#8
+ ldrb r7,[$inp,#12]
+ orr r6,r6,r8,lsl#16
+ ldrb r8,[$inp,#13]
+ orr r6,r6,r9,lsl#24
+ ldrb r9,[$inp,#14]
+ and r6,r6,r3
+
+ ldrb r10,[$inp,#15]
+ orr r7,r7,r8,lsl#8
+ str r4,[$ctx,#0]
+ orr r7,r7,r9,lsl#16
+ str r5,[$ctx,#4]
+ orr r7,r7,r10,lsl#24
+ str r6,[$ctx,#8]
+ and r7,r7,r3
+ str r7,[$ctx,#12]
+#if __ARM_MAX_ARCH__>=7
+ stmia r2,{r11,r12} @ fill functions table
+ mov r0,#1
+#else
+ mov r0,#0
+#endif
+.Lno_key:
+ ldmia sp!,{r4-r11}
+#if __ARM_ARCH__>=5
+ ret @ bx lr
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_init,.-poly1305_init
+___
+{
+my ($h0,$h1,$h2,$h3,$h4,$r0,$r1,$r2,$r3)=map("r$_",(4..12));
+my ($s1,$s2,$s3)=($r1,$r2,$r3);
+
+$code.=<<___;
+.type poly1305_blocks,%function
+.align 5
+poly1305_blocks:
+ stmdb sp!,{r3-r11,lr}
+
+ ands $len,$len,#-16
+ beq .Lno_data
+
+ cmp $padbit,#0
+ add $len,$len,$inp @ end pointer
+ sub sp,sp,#32
+
+ ldmia $ctx,{$h0-$r3} @ load context
+
+ str $ctx,[sp,#12] @ offload stuff
+ mov lr,$inp
+ str $len,[sp,#16]
+ str $r1,[sp,#20]
+ str $r2,[sp,#24]
+ str $r3,[sp,#28]
+ b .Loop
+
+.Loop:
+#if __ARM_ARCH__<7
+ ldrb r0,[lr],#16 @ load input
+# ifdef __thumb2__
+ it hi
+# endif
+ addhi $h4,$h4,#1 @ 1<<128
+ ldrb r1,[lr,#-15]
+ ldrb r2,[lr,#-14]
+ ldrb r3,[lr,#-13]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-12]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-11]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-10]
+ adds $h0,$h0,r3 @ accumulate input
+
+ ldrb r3,[lr,#-9]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-8]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-7]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-6]
+ adcs $h1,$h1,r3
+
+ ldrb r3,[lr,#-5]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-4]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-3]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-2]
+ adcs $h2,$h2,r3
+
+ ldrb r3,[lr,#-1]
+ orr r1,r0,r1,lsl#8
+ str lr,[sp,#8] @ offload input pointer
+ orr r2,r1,r2,lsl#16
+ add $s1,$r1,$r1,lsr#2
+ orr r3,r2,r3,lsl#24
+#else
+ ldr r0,[lr],#16 @ load input
+# ifdef __thumb2__
+ it hi
+# endif
+ addhi $h4,$h4,#1 @ padbit
+ ldr r1,[lr,#-12]
+ ldr r2,[lr,#-8]
+ ldr r3,[lr,#-4]
+# ifdef __ARMEB__
+ rev r0,r0
+ rev r1,r1
+ rev r2,r2
+ rev r3,r3
+# endif
+ adds $h0,$h0,r0 @ accumulate input
+ str lr,[sp,#8] @ offload input pointer
+ adcs $h1,$h1,r1
+ add $s1,$r1,$r1,lsr#2
+ adcs $h2,$h2,r2
+#endif
+ add $s2,$r2,$r2,lsr#2
+ adcs $h3,$h3,r3
+ add $s3,$r3,$r3,lsr#2
+
+ umull r2,r3,$h1,$r0
+ adc $h4,$h4,#0
+ umull r0,r1,$h0,$r0
+ umlal r2,r3,$h4,$s1
+ umlal r0,r1,$h3,$s1
+ ldr $r1,[sp,#20] @ reload $r1
+ umlal r2,r3,$h2,$s3
+ umlal r0,r1,$h1,$s3
+ umlal r2,r3,$h3,$s2
+ umlal r0,r1,$h2,$s2
+ umlal r2,r3,$h0,$r1
+ str r0,[sp,#0] @ future $h0
+ mul r0,$s2,$h4
+ ldr $r2,[sp,#24] @ reload $r2
+ adds r2,r2,r1 @ d1+=d0>>32
+ eor r1,r1,r1
+ adc lr,r3,#0 @ future $h2
+ str r2,[sp,#4] @ future $h1
+
+ mul r2,$s3,$h4
+ eor r3,r3,r3
+ umlal r0,r1,$h3,$s3
+ ldr $r3,[sp,#28] @ reload $r3
+ umlal r2,r3,$h3,$r0
+ umlal r0,r1,$h2,$r0
+ umlal r2,r3,$h2,$r1
+ umlal r0,r1,$h1,$r1
+ umlal r2,r3,$h1,$r2
+ umlal r0,r1,$h0,$r2
+ umlal r2,r3,$h0,$r3
+ ldr $h0,[sp,#0]
+ mul $h4,$r0,$h4
+ ldr $h1,[sp,#4]
+
+ adds $h2,lr,r0 @ d2+=d1>>32
+ ldr lr,[sp,#8] @ reload input pointer
+ adc r1,r1,#0
+ adds $h3,r2,r1 @ d3+=d2>>32
+ ldr r0,[sp,#16] @ reload end pointer
+ adc r3,r3,#0
+ add $h4,$h4,r3 @ h4+=d3>>32
+
+ and r1,$h4,#-4
+ and $h4,$h4,#3
+ add r1,r1,r1,lsr#2 @ *=5
+ adds $h0,$h0,r1
+ adcs $h1,$h1,#0
+ adcs $h2,$h2,#0
+ adc $h3,$h3,#0
+
+ cmp r0,lr @ done yet?
+ bhi .Loop
+
+ ldr $ctx,[sp,#12]
+ add sp,sp,#32
+ stmia $ctx,{$h0-$h4} @ store the result
+
+.Lno_data:
+#if __ARM_ARCH__>=5
+ ldmia sp!,{r3-r11,pc}
+#else
+ ldmia sp!,{r3-r11,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_blocks,.-poly1305_blocks
+___
+}
+{
+my ($ctx,$mac,$nonce)=map("r$_",(0..2));
+my ($h0,$h1,$h2,$h3,$h4,$g0,$g1,$g2,$g3)=map("r$_",(3..11));
+my $g4=$h4;
+
+$code.=<<___;
+.type poly1305_emit,%function
+.align 5
+poly1305_emit:
+ stmdb sp!,{r4-r11}
+.Lpoly1305_emit_enter:
+
+ ldmia $ctx,{$h0-$h4}
+ adds $g0,$h0,#5 @ compare to modulus
+ adcs $g1,$h1,#0
+ adcs $g2,$h2,#0
+ adcs $g3,$h3,#0
+ adc $g4,$h4,#0
+ tst $g4,#4 @ did it carry/borrow?
+
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h0,$g0
+ ldr $g0,[$nonce,#0]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h1,$g1
+ ldr $g1,[$nonce,#4]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h2,$g2
+ ldr $g2,[$nonce,#8]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h3,$g3
+ ldr $g3,[$nonce,#12]
+
+ adds $h0,$h0,$g0
+ adcs $h1,$h1,$g1
+ adcs $h2,$h2,$g2
+ adc $h3,$h3,$g3
+
+#if __ARM_ARCH__>=7
+# ifdef __ARMEB__
+ rev $h0,$h0
+ rev $h1,$h1
+ rev $h2,$h2
+ rev $h3,$h3
+# endif
+ str $h0,[$mac,#0]
+ str $h1,[$mac,#4]
+ str $h2,[$mac,#8]
+ str $h3,[$mac,#12]
+#else
+ strb $h0,[$mac,#0]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#4]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#8]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#12]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#1]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#5]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#9]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#13]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#2]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#6]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#10]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#14]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#3]
+ strb $h1,[$mac,#7]
+ strb $h2,[$mac,#11]
+ strb $h3,[$mac,#15]
+#endif
+ ldmia sp!,{r4-r11}
+#if __ARM_ARCH__>=5
+ ret @ bx lr
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_emit,.-poly1305_emit
+___
+{
+my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("d$_",(0..9));
+my ($D0,$D1,$D2,$D3,$D4, $H0,$H1,$H2,$H3,$H4) = map("q$_",(5..14));
+my ($T0,$T1,$MASK) = map("q$_",(15,4,0));
+
+my ($in2,$zeros,$tbl0,$tbl1) = map("r$_",(4..7));
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.fpu neon
+
+.type poly1305_init_neon,%function
+.align 5
+poly1305_init_neon:
+ ldr r4,[$ctx,#20] @ load key base 2^32
+ ldr r5,[$ctx,#24]
+ ldr r6,[$ctx,#28]
+ ldr r7,[$ctx,#32]
+
+ and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26
+ mov r3,r4,lsr#26
+ mov r4,r5,lsr#20
+ orr r3,r3,r5,lsl#6
+ mov r5,r6,lsr#14
+ orr r4,r4,r6,lsl#12
+ mov r6,r7,lsr#8
+ orr r5,r5,r7,lsl#18
+ and r3,r3,#0x03ffffff
+ and r4,r4,#0x03ffffff
+ and r5,r5,#0x03ffffff
+
+ vdup.32 $R0,r2 @ r^1 in both lanes
+ add r2,r3,r3,lsl#2 @ *5
+ vdup.32 $R1,r3
+ add r3,r4,r4,lsl#2
+ vdup.32 $S1,r2
+ vdup.32 $R2,r4
+ add r4,r5,r5,lsl#2
+ vdup.32 $S2,r3
+ vdup.32 $R3,r5
+ add r5,r6,r6,lsl#2
+ vdup.32 $S3,r4
+ vdup.32 $R4,r6
+ vdup.32 $S4,r5
+
+ mov $zeros,#2 @ counter
+
+.Lsquare_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+
+ vmull.u32 $D0,$R0,${R0}[1]
+ vmull.u32 $D1,$R1,${R0}[1]
+ vmull.u32 $D2,$R2,${R0}[1]
+ vmull.u32 $D3,$R3,${R0}[1]
+ vmull.u32 $D4,$R4,${R0}[1]
+
+ vmlal.u32 $D0,$R4,${S1}[1]
+ vmlal.u32 $D1,$R0,${R1}[1]
+ vmlal.u32 $D2,$R1,${R1}[1]
+ vmlal.u32 $D3,$R2,${R1}[1]
+ vmlal.u32 $D4,$R3,${R1}[1]
+
+ vmlal.u32 $D0,$R3,${S2}[1]
+ vmlal.u32 $D1,$R4,${S2}[1]
+ vmlal.u32 $D3,$R1,${R2}[1]
+ vmlal.u32 $D2,$R0,${R2}[1]
+ vmlal.u32 $D4,$R2,${R2}[1]
+
+ vmlal.u32 $D0,$R2,${S3}[1]
+ vmlal.u32 $D3,$R0,${R3}[1]
+ vmlal.u32 $D1,$R3,${S3}[1]
+ vmlal.u32 $D2,$R4,${S3}[1]
+ vmlal.u32 $D4,$R1,${R3}[1]
+
+ vmlal.u32 $D3,$R4,${S4}[1]
+ vmlal.u32 $D0,$R1,${S4}[1]
+ vmlal.u32 $D1,$R2,${S4}[1]
+ vmlal.u32 $D2,$R3,${S4}[1]
+ vmlal.u32 $D4,$R0,${R4}[1]
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ @ and P. Schwabe
+
+ vshr.u64 $T0,$D3,#26
+ vmovn.i64 $D3#lo,$D3
+ vshr.u64 $T1,$D0,#26
+ vmovn.i64 $D0#lo,$D0
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vbic.i32 $D3#lo,#0xfc000000 @ &=0x03ffffff
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+ vbic.i32 $D0#lo,#0xfc000000
+
+ vshrn.u64 $T0#lo,$D4,#26
+ vmovn.i64 $D4#lo,$D4
+ vshr.u64 $T1,$D1,#26
+ vmovn.i64 $D1#lo,$D1
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+ vbic.i32 $D4#lo,#0xfc000000
+ vbic.i32 $D1#lo,#0xfc000000
+
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo
+ vshl.u32 $T0#lo,$T0#lo,#2
+ vshrn.u64 $T1#lo,$D2,#26
+ vmovn.i64 $D2#lo,$D2
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0
+ vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3
+ vbic.i32 $D2#lo,#0xfc000000
+
+ vshr.u32 $T0#lo,$D0#lo,#26
+ vbic.i32 $D0#lo,#0xfc000000
+ vshr.u32 $T1#lo,$D3#lo,#26
+ vbic.i32 $D3#lo,#0xfc000000
+ vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1
+ vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4
+
+ subs $zeros,$zeros,#1
+ beq .Lsquare_break_neon
+
+ add $tbl0,$ctx,#(48+0*9*4)
+ add $tbl1,$ctx,#(48+1*9*4)
+
+ vtrn.32 $R0,$D0#lo @ r^2:r^1
+ vtrn.32 $R2,$D2#lo
+ vtrn.32 $R3,$D3#lo
+ vtrn.32 $R1,$D1#lo
+ vtrn.32 $R4,$D4#lo
+
+ vshl.u32 $S2,$R2,#2 @ *5
+ vshl.u32 $S3,$R3,#2
+ vshl.u32 $S1,$R1,#2
+ vshl.u32 $S4,$R4,#2
+ vadd.i32 $S2,$S2,$R2
+ vadd.i32 $S1,$S1,$R1
+ vadd.i32 $S3,$S3,$R3
+ vadd.i32 $S4,$S4,$R4
+
+ vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]!
+ vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]!
+ vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vst1.32 {${S4}[0]},[$tbl0,:32]
+ vst1.32 {${S4}[1]},[$tbl1,:32]
+
+ b .Lsquare_neon
+
+.align 4
+.Lsquare_break_neon:
+ add $tbl0,$ctx,#(48+2*4*9)
+ add $tbl1,$ctx,#(48+3*4*9)
+
+ vmov $R0,$D0#lo @ r^4:r^3
+ vshl.u32 $S1,$D1#lo,#2 @ *5
+ vmov $R1,$D1#lo
+ vshl.u32 $S2,$D2#lo,#2
+ vmov $R2,$D2#lo
+ vshl.u32 $S3,$D3#lo,#2
+ vmov $R3,$D3#lo
+ vshl.u32 $S4,$D4#lo,#2
+ vmov $R4,$D4#lo
+ vadd.i32 $S1,$S1,$D1#lo
+ vadd.i32 $S2,$S2,$D2#lo
+ vadd.i32 $S3,$S3,$D3#lo
+ vadd.i32 $S4,$S4,$D4#lo
+
+ vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]!
+ vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]!
+ vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vst1.32 {${S4}[0]},[$tbl0]
+ vst1.32 {${S4}[1]},[$tbl1]
+
+ ret @ bx lr
+.size poly1305_init_neon,.-poly1305_init_neon
+
+.type poly1305_blocks_neon,%function
+.align 5
+poly1305_blocks_neon:
+ ldr ip,[$ctx,#36] @ is_base2_26
+ ands $len,$len,#-16
+ beq .Lno_data_neon
+
+ cmp $len,#64
+ bhs .Lenter_neon
+ tst ip,ip @ is_base2_26?
+ beq poly1305_blocks
+
+.Lenter_neon:
+ stmdb sp!,{r4-r7}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ tst ip,ip @ is_base2_26?
+ bne .Lbase2_26_neon
+
+ stmdb sp!,{r1-r3,lr}
+ bl poly1305_init_neon
+
+ ldr r4,[$ctx,#0] @ load hash value base 2^32
+ ldr r5,[$ctx,#4]
+ ldr r6,[$ctx,#8]
+ ldr r7,[$ctx,#12]
+ ldr ip,[$ctx,#16]
+
+ and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26
+ mov r3,r4,lsr#26
+ veor $D0#lo,$D0#lo,$D0#lo
+ mov r4,r5,lsr#20
+ orr r3,r3,r5,lsl#6
+ veor $D1#lo,$D1#lo,$D1#lo
+ mov r5,r6,lsr#14
+ orr r4,r4,r6,lsl#12
+ veor $D2#lo,$D2#lo,$D2#lo
+ mov r6,r7,lsr#8
+ orr r5,r5,r7,lsl#18
+ veor $D3#lo,$D3#lo,$D3#lo
+ and r3,r3,#0x03ffffff
+ orr r6,r6,ip,lsl#24
+ veor $D4#lo,$D4#lo,$D4#lo
+ and r4,r4,#0x03ffffff
+ mov r1,#1
+ and r5,r5,#0x03ffffff
+ str r1,[$ctx,#36] @ is_base2_26
+
+ vmov.32 $D0#lo[0],r2
+ vmov.32 $D1#lo[0],r3
+ vmov.32 $D2#lo[0],r4
+ vmov.32 $D3#lo[0],r5
+ vmov.32 $D4#lo[0],r6
+ adr $zeros,.Lzeros
+
+ ldmia sp!,{r1-r3,lr}
+ b .Lbase2_32_neon
+
+.align 4
+.Lbase2_26_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ load hash value
+
+ veor $D0#lo,$D0#lo,$D0#lo
+ veor $D1#lo,$D1#lo,$D1#lo
+ veor $D2#lo,$D2#lo,$D2#lo
+ veor $D3#lo,$D3#lo,$D3#lo
+ veor $D4#lo,$D4#lo,$D4#lo
+ vld4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]!
+ adr $zeros,.Lzeros
+ vld1.32 {$D4#lo[0]},[$ctx]
+ sub $ctx,$ctx,#16 @ rewind
+
+.Lbase2_32_neon:
+ add $in2,$inp,#32
+ mov $padbit,$padbit,lsl#24
+ tst $len,#31
+ beq .Leven
+
+ vld4.32 {$H0#lo[0],$H1#lo[0],$H2#lo[0],$H3#lo[0]},[$inp]!
+ vmov.32 $H4#lo[0],$padbit
+ sub $len,$len,#16
+ add $in2,$inp,#32
+
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H3,$H3
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+# endif
+ vsri.u32 $H4#lo,$H3#lo,#8 @ base 2^32 -> base 2^26
+ vshl.u32 $H3#lo,$H3#lo,#18
+
+ vsri.u32 $H3#lo,$H2#lo,#14
+ vshl.u32 $H2#lo,$H2#lo,#12
+ vadd.i32 $H4#hi,$H4#lo,$D4#lo @ add hash value and move to #hi
+
+ vbic.i32 $H3#lo,#0xfc000000
+ vsri.u32 $H2#lo,$H1#lo,#20
+ vshl.u32 $H1#lo,$H1#lo,#6
+
+ vbic.i32 $H2#lo,#0xfc000000
+ vsri.u32 $H1#lo,$H0#lo,#26
+ vadd.i32 $H3#hi,$H3#lo,$D3#lo
+
+ vbic.i32 $H0#lo,#0xfc000000
+ vbic.i32 $H1#lo,#0xfc000000
+ vadd.i32 $H2#hi,$H2#lo,$D2#lo
+
+ vadd.i32 $H0#hi,$H0#lo,$D0#lo
+ vadd.i32 $H1#hi,$H1#lo,$D1#lo
+
+ mov $tbl1,$zeros
+ add $tbl0,$ctx,#48
+
+ cmp $len,$len
+ b .Long_tail
+
+.align 4
+.Leven:
+ subs $len,$len,#64
+# ifdef __thumb2__
+ it lo
+# endif
+ movlo $in2,$zeros
+
+ vmov.i32 $H4,#1<<24 @ padbit, yes, always
+ vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1]
+ add $inp,$inp,#64
+ vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0)
+ add $in2,$in2,#64
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi $tbl1,$ctx,#(48+1*9*4)
+ addhi $tbl0,$ctx,#(48+3*9*4)
+
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H3,$H3
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+# endif
+ vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26
+ vshl.u32 $H3,$H3,#18
+
+ vsri.u32 $H3,$H2,#14
+ vshl.u32 $H2,$H2,#12
+
+ vbic.i32 $H3,#0xfc000000
+ vsri.u32 $H2,$H1,#20
+ vshl.u32 $H1,$H1,#6
+
+ vbic.i32 $H2,#0xfc000000
+ vsri.u32 $H1,$H0,#26
+
+ vbic.i32 $H0,#0xfc000000
+ vbic.i32 $H1,#0xfc000000
+
+ bls .Lskip_loop
+
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^2
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ b .Loop_neon
+
+.align 5
+.Loop_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ @ \___________________/
+ @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ @ \___________________/ \____________________/
+ @
+ @ Note that we start with inp[2:3]*r^2. This is because it
+ @ doesn't depend on reduction in previous iteration.
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ inp[2:3]*r^2
+
+ vadd.i32 $H2#lo,$H2#lo,$D2#lo @ accumulate inp[0:1]
+ vmull.u32 $D2,$H2#hi,${R0}[1]
+ vadd.i32 $H0#lo,$H0#lo,$D0#lo
+ vmull.u32 $D0,$H0#hi,${R0}[1]
+ vadd.i32 $H3#lo,$H3#lo,$D3#lo
+ vmull.u32 $D3,$H3#hi,${R0}[1]
+ vmlal.u32 $D2,$H1#hi,${R1}[1]
+ vadd.i32 $H1#lo,$H1#lo,$D1#lo
+ vmull.u32 $D1,$H1#hi,${R0}[1]
+
+ vadd.i32 $H4#lo,$H4#lo,$D4#lo
+ vmull.u32 $D4,$H4#hi,${R0}[1]
+ subs $len,$len,#64
+ vmlal.u32 $D0,$H4#hi,${S1}[1]
+# ifdef __thumb2__
+ it lo
+# endif
+ movlo $in2,$zeros
+ vmlal.u32 $D3,$H2#hi,${R1}[1]
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D1,$H0#hi,${R1}[1]
+ vmlal.u32 $D4,$H3#hi,${R1}[1]
+
+ vmlal.u32 $D0,$H3#hi,${S2}[1]
+ vmlal.u32 $D3,$H1#hi,${R2}[1]
+ vmlal.u32 $D4,$H2#hi,${R2}[1]
+ vmlal.u32 $D1,$H4#hi,${S2}[1]
+ vmlal.u32 $D2,$H0#hi,${R2}[1]
+
+ vmlal.u32 $D3,$H0#hi,${R3}[1]
+ vmlal.u32 $D0,$H2#hi,${S3}[1]
+ vmlal.u32 $D4,$H1#hi,${R3}[1]
+ vmlal.u32 $D1,$H3#hi,${S3}[1]
+ vmlal.u32 $D2,$H4#hi,${S3}[1]
+
+ vmlal.u32 $D3,$H4#hi,${S4}[1]
+ vmlal.u32 $D0,$H1#hi,${S4}[1]
+ vmlal.u32 $D4,$H0#hi,${R4}[1]
+ vmlal.u32 $D1,$H2#hi,${S4}[1]
+ vmlal.u32 $D2,$H3#hi,${S4}[1]
+
+ vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0)
+ add $in2,$in2,#64
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ (hash+inp[0:1])*r^4 and accumulate
+
+ vmlal.u32 $D3,$H3#lo,${R0}[0]
+ vmlal.u32 $D0,$H0#lo,${R0}[0]
+ vmlal.u32 $D4,$H4#lo,${R0}[0]
+ vmlal.u32 $D1,$H1#lo,${R0}[0]
+ vmlal.u32 $D2,$H2#lo,${R0}[0]
+ vld1.32 ${S4}[0],[$tbl0,:32]
+
+ vmlal.u32 $D3,$H2#lo,${R1}[0]
+ vmlal.u32 $D0,$H4#lo,${S1}[0]
+ vmlal.u32 $D4,$H3#lo,${R1}[0]
+ vmlal.u32 $D1,$H0#lo,${R1}[0]
+ vmlal.u32 $D2,$H1#lo,${R1}[0]
+
+ vmlal.u32 $D3,$H1#lo,${R2}[0]
+ vmlal.u32 $D0,$H3#lo,${S2}[0]
+ vmlal.u32 $D4,$H2#lo,${R2}[0]
+ vmlal.u32 $D1,$H4#lo,${S2}[0]
+ vmlal.u32 $D2,$H0#lo,${R2}[0]
+
+ vmlal.u32 $D3,$H0#lo,${R3}[0]
+ vmlal.u32 $D0,$H2#lo,${S3}[0]
+ vmlal.u32 $D4,$H1#lo,${R3}[0]
+ vmlal.u32 $D1,$H3#lo,${S3}[0]
+ vmlal.u32 $D3,$H4#lo,${S4}[0]
+
+ vmlal.u32 $D2,$H4#lo,${S3}[0]
+ vmlal.u32 $D0,$H1#lo,${S4}[0]
+ vmlal.u32 $D4,$H0#lo,${R4}[0]
+ vmov.i32 $H4,#1<<24 @ padbit, yes, always
+ vmlal.u32 $D1,$H2#lo,${S4}[0]
+ vmlal.u32 $D2,$H3#lo,${S4}[0]
+
+ vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1]
+ add $inp,$inp,#64
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+ vrev32.8 $H3,$H3
+# endif
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction interleaved with base 2^32 -> base 2^26
+
+ vshr.u64 $T0,$D3,#26
+ vmovn.i64 $D3#lo,$D3
+ vshr.u64 $T1,$D0,#26
+ vmovn.i64 $D0#lo,$D0
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vbic.i32 $D3#lo,#0xfc000000
+ vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+ vshl.u32 $H3,$H3,#18
+ vbic.i32 $D0#lo,#0xfc000000
+
+ vshrn.u64 $T0#lo,$D4,#26
+ vmovn.i64 $D4#lo,$D4
+ vshr.u64 $T1,$D1,#26
+ vmovn.i64 $D1#lo,$D1
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+ vsri.u32 $H3,$H2,#14
+ vbic.i32 $D4#lo,#0xfc000000
+ vshl.u32 $H2,$H2,#12
+ vbic.i32 $D1#lo,#0xfc000000
+
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo
+ vshl.u32 $T0#lo,$T0#lo,#2
+ vbic.i32 $H3,#0xfc000000
+ vshrn.u64 $T1#lo,$D2,#26
+ vmovn.i64 $D2#lo,$D2
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0
+ vsri.u32 $H2,$H1,#20
+ vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3
+ vshl.u32 $H1,$H1,#6
+ vbic.i32 $D2#lo,#0xfc000000
+ vbic.i32 $H2,#0xfc000000
+
+ vshr.u32 $T0#lo,$D0#lo,#26
+ vbic.i32 $D0#lo,#0xfc000000
+ vsri.u32 $H1,$H0,#26
+ vbic.i32 $H0,#0xfc000000
+ vshr.u32 $T1#lo,$D3#lo,#26
+ vbic.i32 $D3#lo,#0xfc000000
+ vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1
+ vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4
+ vbic.i32 $H1,#0xfc000000
+
+ bhi .Loop_neon
+
+.Lskip_loop:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ add $tbl1,$ctx,#(48+0*9*4)
+ add $tbl0,$ctx,#(48+1*9*4)
+ adds $len,$len,#32
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $len,#0
+ bne .Long_tail
+
+ vadd.i32 $H2#hi,$H2#lo,$D2#lo @ add hash value and move to #hi
+ vadd.i32 $H0#hi,$H0#lo,$D0#lo
+ vadd.i32 $H3#hi,$H3#lo,$D3#lo
+ vadd.i32 $H1#hi,$H1#lo,$D1#lo
+ vadd.i32 $H4#hi,$H4#lo,$D4#lo
+
+.Long_tail:
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^1
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^2
+
+ vadd.i32 $H2#lo,$H2#lo,$D2#lo @ can be redundant
+ vmull.u32 $D2,$H2#hi,$R0
+ vadd.i32 $H0#lo,$H0#lo,$D0#lo
+ vmull.u32 $D0,$H0#hi,$R0
+ vadd.i32 $H3#lo,$H3#lo,$D3#lo
+ vmull.u32 $D3,$H3#hi,$R0
+ vadd.i32 $H1#lo,$H1#lo,$D1#lo
+ vmull.u32 $D1,$H1#hi,$R0
+ vadd.i32 $H4#lo,$H4#lo,$D4#lo
+ vmull.u32 $D4,$H4#hi,$R0
+
+ vmlal.u32 $D0,$H4#hi,$S1
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vmlal.u32 $D3,$H2#hi,$R1
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vmlal.u32 $D1,$H0#hi,$R1
+ vmlal.u32 $D4,$H3#hi,$R1
+ vmlal.u32 $D2,$H1#hi,$R1
+
+ vmlal.u32 $D3,$H1#hi,$R2
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D0,$H3#hi,$S2
+ vld1.32 ${S4}[0],[$tbl0,:32]
+ vmlal.u32 $D4,$H2#hi,$R2
+ vmlal.u32 $D1,$H4#hi,$S2
+ vmlal.u32 $D2,$H0#hi,$R2
+
+ vmlal.u32 $D3,$H0#hi,$R3
+# ifdef __thumb2__
+ it ne
+# endif
+ addne $tbl1,$ctx,#(48+2*9*4)
+ vmlal.u32 $D0,$H2#hi,$S3
+# ifdef __thumb2__
+ it ne
+# endif
+ addne $tbl0,$ctx,#(48+3*9*4)
+ vmlal.u32 $D4,$H1#hi,$R3
+ vmlal.u32 $D1,$H3#hi,$S3
+ vmlal.u32 $D2,$H4#hi,$S3
+
+ vmlal.u32 $D3,$H4#hi,$S4
+ vorn $MASK,$MASK,$MASK @ all-ones, can be redundant
+ vmlal.u32 $D0,$H1#hi,$S4
+ vshr.u64 $MASK,$MASK,#38
+ vmlal.u32 $D4,$H0#hi,$R4
+ vmlal.u32 $D1,$H2#hi,$S4
+ vmlal.u32 $D2,$H3#hi,$S4
+
+ beq .Lshort_tail
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ (hash+inp[0:1])*r^4:r^3 and accumulate
+
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^3
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4
+
+ vmlal.u32 $D2,$H2#lo,$R0
+ vmlal.u32 $D0,$H0#lo,$R0
+ vmlal.u32 $D3,$H3#lo,$R0
+ vmlal.u32 $D1,$H1#lo,$R0
+ vmlal.u32 $D4,$H4#lo,$R0
+
+ vmlal.u32 $D0,$H4#lo,$S1
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vmlal.u32 $D3,$H2#lo,$R1
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vmlal.u32 $D1,$H0#lo,$R1
+ vmlal.u32 $D4,$H3#lo,$R1
+ vmlal.u32 $D2,$H1#lo,$R1
+
+ vmlal.u32 $D3,$H1#lo,$R2
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D0,$H3#lo,$S2
+ vld1.32 ${S4}[0],[$tbl0,:32]
+ vmlal.u32 $D4,$H2#lo,$R2
+ vmlal.u32 $D1,$H4#lo,$S2
+ vmlal.u32 $D2,$H0#lo,$R2
+
+ vmlal.u32 $D3,$H0#lo,$R3
+ vmlal.u32 $D0,$H2#lo,$S3
+ vmlal.u32 $D4,$H1#lo,$R3
+ vmlal.u32 $D1,$H3#lo,$S3
+ vmlal.u32 $D2,$H4#lo,$S3
+
+ vmlal.u32 $D3,$H4#lo,$S4
+ vorn $MASK,$MASK,$MASK @ all-ones
+ vmlal.u32 $D0,$H1#lo,$S4
+ vshr.u64 $MASK,$MASK,#38
+ vmlal.u32 $D4,$H0#lo,$R4
+ vmlal.u32 $D1,$H2#lo,$S4
+ vmlal.u32 $D2,$H3#lo,$S4
+
+.Lshort_tail:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ horizontal addition
+
+ vadd.i64 $D3#lo,$D3#lo,$D3#hi
+ vadd.i64 $D0#lo,$D0#lo,$D0#hi
+ vadd.i64 $D4#lo,$D4#lo,$D4#hi
+ vadd.i64 $D1#lo,$D1#lo,$D1#hi
+ vadd.i64 $D2#lo,$D2#lo,$D2#hi
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction, but without narrowing
+
+ vshr.u64 $T0,$D3,#26
+ vand.i64 $D3,$D3,$MASK
+ vshr.u64 $T1,$D0,#26
+ vand.i64 $D0,$D0,$MASK
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+
+ vshr.u64 $T0,$D4,#26
+ vand.i64 $D4,$D4,$MASK
+ vshr.u64 $T1,$D1,#26
+ vand.i64 $D1,$D1,$MASK
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+
+ vadd.i64 $D0,$D0,$T0
+ vshl.u64 $T0,$T0,#2
+ vshr.u64 $T1,$D2,#26
+ vand.i64 $D2,$D2,$MASK
+ vadd.i64 $D0,$D0,$T0 @ h4 -> h0
+ vadd.i64 $D3,$D3,$T1 @ h2 -> h3
+
+ vshr.u64 $T0,$D0,#26
+ vand.i64 $D0,$D0,$MASK
+ vshr.u64 $T1,$D3,#26
+ vand.i64 $D3,$D3,$MASK
+ vadd.i64 $D1,$D1,$T0 @ h0 -> h1
+ vadd.i64 $D4,$D4,$T1 @ h3 -> h4
+
+ cmp $len,#0
+ bne .Leven
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ store hash value
+
+ vst4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]!
+ vst1.32 {$D4#lo[0]},[$ctx]
+
+ vldmia sp!,{d8-d15} @ epilogue
+ ldmia sp!,{r4-r7}
+.Lno_data_neon:
+ ret @ bx lr
+.size poly1305_blocks_neon,.-poly1305_blocks_neon
+
+.type poly1305_emit_neon,%function
+.align 5
+poly1305_emit_neon:
+ ldr ip,[$ctx,#36] @ is_base2_26
+
+ stmdb sp!,{r4-r11}
+
+ tst ip,ip
+ beq .Lpoly1305_emit_enter
+
+ ldmia $ctx,{$h0-$h4}
+ eor $g0,$g0,$g0
+
+ adds $h0,$h0,$h1,lsl#26 @ base 2^26 -> base 2^32
+ mov $h1,$h1,lsr#6
+ adcs $h1,$h1,$h2,lsl#20
+ mov $h2,$h2,lsr#12
+ adcs $h2,$h2,$h3,lsl#14
+ mov $h3,$h3,lsr#18
+ adcs $h3,$h3,$h4,lsl#8
+ adc $h4,$g0,$h4,lsr#24 @ can be partially reduced ...
+
+ and $g0,$h4,#-4 @ ... so reduce
+ and $h4,$h3,#3
+ add $g0,$g0,$g0,lsr#2 @ *= 5
+ adds $h0,$h0,$g0
+ adcs $h1,$h1,#0
+ adcs $h2,$h2,#0
+ adc $h3,$h3,#0
+
+ adds $g0,$h0,#5 @ compare to modulus
+ adcs $g1,$h1,#0
+ adcs $g2,$h2,#0
+ adcs $g3,$h3,#0
+ adc $g4,$h4,#0
+ tst $g4,#4 @ did it carry/borrow?
+
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h0,$g0
+ ldr $g0,[$nonce,#0]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h1,$g1
+ ldr $g1,[$nonce,#4]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h2,$g2
+ ldr $g2,[$nonce,#8]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h3,$g3
+ ldr $g3,[$nonce,#12]
+
+ adds $h0,$h0,$g0 @ accumulate nonce
+ adcs $h1,$h1,$g1
+ adcs $h2,$h2,$g2
+ adc $h3,$h3,$g3
+
+# ifdef __ARMEB__
+ rev $h0,$h0
+ rev $h1,$h1
+ rev $h2,$h2
+ rev $h3,$h3
+# endif
+ str $h0,[$mac,#0] @ store the result
+ str $h1,[$mac,#4]
+ str $h2,[$mac,#8]
+ str $h3,[$mac,#12]
+
+ ldmia sp!,{r4-r11}
+ ret @ bx lr
+.size poly1305_emit_neon,.-poly1305_emit_neon
+
+.align 5
+.Lzeros:
+.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-.Lpoly1305_init
+#endif
+___
+} }
+$code.=<<___;
+.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/\bret\b/bx lr/go or
+ s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
+
+ print $_,"\n";
+}
+close STDOUT; # enforce flush
diff --git a/src/crypto/poly1305/asm/poly1305-armv8.pl b/src/crypto/poly1305/asm/poly1305-armv8.pl
new file mode 100755
index 00000000..1d9a81b8
--- /dev/null
+++ b/src/crypto/poly1305/asm/poly1305-armv8.pl
@@ -0,0 +1,925 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for ARMv8.
+#
+# June 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone.
+#
+# IALU/gcc-4.9 NEON
+#
+# Apple A7 1.86/+5% 0.72
+# Cortex-A53 2.63/+58% 1.47
+# Cortex-A57 2.70/+7% 1.14
+# Denver 1.39/+50% 1.18(*)
+# X-Gene 2.00/+68% 2.19
+#
+# (*) estimate based on resources availability is less than 1.0,
+# i.e. measured result is worse than expected, presumably binary
+# translator is not almighty;
+
+$flavour=shift;
+$output=shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3));
+my ($mac,$nonce)=($inp,$len);
+
+my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14));
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+
+// forward "declarations" are required for Apple
+.extern OPENSSL_armcap_P
+.globl poly1305_blocks
+.globl poly1305_emit
+
+.globl poly1305_init
+.type poly1305_init,%function
+.align 5
+poly1305_init:
+ cmp $inp,xzr
+ stp xzr,xzr,[$ctx] // zero hash value
+ stp xzr,xzr,[$ctx,#16] // [along with is_base2_26]
+
+ csel x0,xzr,x0,eq
+ b.eq .Lno_key
+
+#ifdef __ILP32__
+ ldrsw $t1,.LOPENSSL_armcap_P
+#else
+ ldr $t1,.LOPENSSL_armcap_P
+#endif
+ adr $t0,.LOPENSSL_armcap_P
+
+ ldp $r0,$r1,[$inp] // load key
+ mov $s1,#0xfffffffc0fffffff
+ movk $s1,#0x0fff,lsl#48
+ ldr w17,[$t0,$t1]
+#ifdef __ARMEB__
+ rev $r0,$r0 // flip bytes
+ rev $r1,$r1
+#endif
+ and $r0,$r0,$s1 // &=0ffffffc0fffffff
+ and $s1,$s1,#-4
+ and $r1,$r1,$s1 // &=0ffffffc0ffffffc
+ stp $r0,$r1,[$ctx,#32] // save key value
+
+ tst w17,#ARMV7_NEON
+
+ adr $d0,poly1305_blocks
+ adr $r0,poly1305_blocks_neon
+ adr $d1,poly1305_emit
+ adr $r1,poly1305_emit_neon
+
+ csel $d0,$d0,$r0,eq
+ csel $d1,$d1,$r1,eq
+
+ stp $d0,$d1,[$len]
+
+ mov x0,#1
+.Lno_key:
+ ret
+.size poly1305_init,.-poly1305_init
+
+.type poly1305_blocks,%function
+.align 5
+poly1305_blocks:
+ ands $len,$len,#-16
+ b.eq .Lno_data
+
+ ldp $h0,$h1,[$ctx] // load hash value
+ ldp $r0,$r1,[$ctx,#32] // load key value
+ ldr $h2,[$ctx,#16]
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+ b .Loop
+
+.align 5
+.Loop:
+ ldp $t0,$t1,[$inp],#16 // load input
+ sub $len,$len,#16
+#ifdef __ARMEB__
+ rev $t0,$t0
+ rev $t1,$t1
+#endif
+ adds $h0,$h0,$t0 // accumulate input
+ adcs $h1,$h1,$t1
+
+ mul $d0,$h0,$r0 // h0*r0
+ adc $h2,$h2,$padbit
+ umulh $d1,$h0,$r0
+
+ mul $t0,$h1,$s1 // h1*5*r1
+ umulh $t1,$h1,$s1
+
+ adds $d0,$d0,$t0
+ mul $t0,$h0,$r1 // h0*r1
+ adc $d1,$d1,$t1
+ umulh $d2,$h0,$r1
+
+ adds $d1,$d1,$t0
+ mul $t0,$h1,$r0 // h1*r0
+ adc $d2,$d2,xzr
+ umulh $t1,$h1,$r0
+
+ adds $d1,$d1,$t0
+ mul $t0,$h2,$s1 // h2*5*r1
+ adc $d2,$d2,$t1
+ mul $t1,$h2,$r0 // h2*r0
+
+ adds $d1,$d1,$t0
+ adc $d2,$d2,$t1
+
+ and $t0,$d2,#-4 // final reduction
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$d0,$t0
+ adc $h1,$d1,xzr
+
+ cbnz $len,.Loop
+
+ stp $h0,$h1,[$ctx] // store hash value
+ str $h2,[$ctx,#16]
+
+.Lno_data:
+ ret
+.size poly1305_blocks,.-poly1305_blocks
+
+.type poly1305_emit,%function
+.align 5
+poly1305_emit:
+ ldp $h0,$h1,[$ctx] // load hash base 2^64
+ ldr $h2,[$ctx,#16]
+ ldp $t0,$t1,[$nonce] // load nonce
+
+ adds $d0,$h0,#5 // compare to modulus
+ adcs $d1,$h1,xzr
+ adc $d2,$h2,xzr
+
+ tst $d2,#-4 // see if it's carried/borrowed
+
+ csel $h0,$h0,$d0,eq
+ csel $h1,$h1,$d1,eq
+
+#ifdef __ARMEB__
+ ror $t0,$t0,#32 // flip nonce words
+ ror $t1,$t1,#32
+#endif
+ adds $h0,$h0,$t0 // accumulate nonce
+ adc $h1,$h1,$t1
+#ifdef __ARMEB__
+ rev $h0,$h0 // flip output bytes
+ rev $h1,$h1
+#endif
+ stp $h0,$h1,[$mac] // write result
+
+ ret
+.size poly1305_emit,.-poly1305_emit
+___
+my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("v$_.4s",(0..8));
+my ($IN01_0,$IN01_1,$IN01_2,$IN01_3,$IN01_4) = map("v$_.2s",(9..13));
+my ($IN23_0,$IN23_1,$IN23_2,$IN23_3,$IN23_4) = map("v$_.2s",(14..18));
+my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4) = map("v$_.2d",(19..23));
+my ($H0,$H1,$H2,$H3,$H4) = map("v$_.2s",(24..28));
+my ($T0,$T1,$MASK) = map("v$_",(29..31));
+
+my ($in2,$zeros)=("x16","x17");
+my $is_base2_26 = $zeros; # borrow
+
+$code.=<<___;
+.type poly1305_mult,%function
+.align 5
+poly1305_mult:
+ mul $d0,$h0,$r0 // h0*r0
+ umulh $d1,$h0,$r0
+
+ mul $t0,$h1,$s1 // h1*5*r1
+ umulh $t1,$h1,$s1
+
+ adds $d0,$d0,$t0
+ mul $t0,$h0,$r1 // h0*r1
+ adc $d1,$d1,$t1
+ umulh $d2,$h0,$r1
+
+ adds $d1,$d1,$t0
+ mul $t0,$h1,$r0 // h1*r0
+ adc $d2,$d2,xzr
+ umulh $t1,$h1,$r0
+
+ adds $d1,$d1,$t0
+ mul $t0,$h2,$s1 // h2*5*r1
+ adc $d2,$d2,$t1
+ mul $t1,$h2,$r0 // h2*r0
+
+ adds $d1,$d1,$t0
+ adc $d2,$d2,$t1
+
+ and $t0,$d2,#-4 // final reduction
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$d0,$t0
+ adc $h1,$d1,xzr
+
+ ret
+.size poly1305_mult,.-poly1305_mult
+
+.type poly1305_splat,%function
+.align 5
+poly1305_splat:
+ and x12,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x13,$h0,#26,#26
+ extr x14,$h1,$h0,#52
+ and x14,x14,#0x03ffffff
+ ubfx x15,$h1,#14,#26
+ extr x16,$h2,$h1,#40
+
+ str w12,[$ctx,#16*0] // r0
+ add w12,w13,w13,lsl#2 // r1*5
+ str w13,[$ctx,#16*1] // r1
+ add w13,w14,w14,lsl#2 // r2*5
+ str w12,[$ctx,#16*2] // s1
+ str w14,[$ctx,#16*3] // r2
+ add w14,w15,w15,lsl#2 // r3*5
+ str w13,[$ctx,#16*4] // s2
+ str w15,[$ctx,#16*5] // r3
+ add w15,w16,w16,lsl#2 // r4*5
+ str w14,[$ctx,#16*6] // s3
+ str w16,[$ctx,#16*7] // r4
+ str w15,[$ctx,#16*8] // s4
+
+ ret
+.size poly1305_splat,.-poly1305_splat
+
+.type poly1305_blocks_neon,%function
+.align 5
+poly1305_blocks_neon:
+ ldr $is_base2_26,[$ctx,#24]
+ cmp $len,#128
+ b.hs .Lblocks_neon
+ cbz $is_base2_26,poly1305_blocks
+
+.Lblocks_neon:
+ stp x29,x30,[sp,#-80]!
+ add x29,sp,#0
+
+ ands $len,$len,#-16
+ b.eq .Lno_data_neon
+
+ cbz $is_base2_26,.Lbase2_64_neon
+
+ ldp w10,w11,[$ctx] // load hash value base 2^26
+ ldp w12,w13,[$ctx,#8]
+ ldr w14,[$ctx,#16]
+
+ tst $len,#31
+ b.eq .Leven_neon
+
+ ldp $r0,$r1,[$ctx,#32] // load key value
+
+ add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64
+ lsr $h1,x12,#12
+ adds $h0,$h0,x12,lsl#52
+ add $h1,$h1,x13,lsl#14
+ adc $h1,$h1,xzr
+ lsr $h2,x14,#24
+ adds $h1,$h1,x14,lsl#40
+ adc $d2,$h2,xzr // can be partially reduced...
+
+ ldp $d0,$d1,[$inp],#16 // load input
+ sub $len,$len,#16
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+
+ and $t0,$d2,#-4 // ... so reduce
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$h0,$t0
+ adc $h1,$h1,xzr
+
+#ifdef __ARMEB__
+ rev $d0,$d0
+ rev $d1,$d1
+#endif
+ adds $h0,$h0,$d0 // accumulate input
+ adcs $h1,$h1,$d1
+ adc $h2,$h2,$padbit
+
+ bl poly1305_mult
+ ldr x30,[sp,#8]
+
+ cbz $padbit,.Lstore_base2_64_neon
+
+ and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x11,$h0,#26,#26
+ extr x12,$h1,$h0,#52
+ and x12,x12,#0x03ffffff
+ ubfx x13,$h1,#14,#26
+ extr x14,$h2,$h1,#40
+
+ cbnz $len,.Leven_neon
+
+ stp w10,w11,[$ctx] // store hash value base 2^26
+ stp w12,w13,[$ctx,#8]
+ str w14,[$ctx,#16]
+ b .Lno_data_neon
+
+.align 4
+.Lstore_base2_64_neon:
+ stp $h0,$h1,[$ctx] // store hash value base 2^64
+ stp $h2,xzr,[$ctx,#16] // note that is_base2_26 is zeroed
+ b .Lno_data_neon
+
+.align 4
+.Lbase2_64_neon:
+ ldp $r0,$r1,[$ctx,#32] // load key value
+
+ ldp $h0,$h1,[$ctx] // load hash value base 2^64
+ ldr $h2,[$ctx,#16]
+
+ tst $len,#31
+ b.eq .Linit_neon
+
+ ldp $d0,$d1,[$inp],#16 // load input
+ sub $len,$len,#16
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+#ifdef __ARMEB__
+ rev $d0,$d0
+ rev $d1,$d1
+#endif
+ adds $h0,$h0,$d0 // accumulate input
+ adcs $h1,$h1,$d1
+ adc $h2,$h2,$padbit
+
+ bl poly1305_mult
+
+.Linit_neon:
+ and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x11,$h0,#26,#26
+ extr x12,$h1,$h0,#52
+ and x12,x12,#0x03ffffff
+ ubfx x13,$h1,#14,#26
+ extr x14,$h2,$h1,#40
+
+ stp d8,d9,[sp,#16] // meet ABI requirements
+ stp d10,d11,[sp,#32]
+ stp d12,d13,[sp,#48]
+ stp d14,d15,[sp,#64]
+
+ fmov ${H0},x10
+ fmov ${H1},x11
+ fmov ${H2},x12
+ fmov ${H3},x13
+ fmov ${H4},x14
+
+ ////////////////////////////////// initialize r^n table
+ mov $h0,$r0 // r^1
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+ mov $h1,$r1
+ mov $h2,xzr
+ add $ctx,$ctx,#48+12
+ bl poly1305_splat
+
+ bl poly1305_mult // r^2
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+
+ bl poly1305_mult // r^3
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+
+ bl poly1305_mult // r^4
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+ ldr x30,[sp,#8]
+
+ add $in2,$inp,#32
+ adr $zeros,.Lzeros
+ subs $len,$len,#64
+ csel $in2,$zeros,$in2,lo
+
+ mov x4,#1
+ str x4,[$ctx,#-24] // set is_base2_26
+ sub $ctx,$ctx,#48 // restore original $ctx
+ b .Ldo_neon
+
+.align 4
+.Leven_neon:
+ add $in2,$inp,#32
+ adr $zeros,.Lzeros
+ subs $len,$len,#64
+ csel $in2,$zeros,$in2,lo
+
+ stp d8,d9,[sp,#16] // meet ABI requirements
+ stp d10,d11,[sp,#32]
+ stp d12,d13,[sp,#48]
+ stp d14,d15,[sp,#64]
+
+ fmov ${H0},x10
+ fmov ${H1},x11
+ fmov ${H2},x12
+ fmov ${H3},x13
+ fmov ${H4},x14
+
+.Ldo_neon:
+ ldp x8,x12,[$in2],#16 // inp[2:3] (or zero)
+ ldp x9,x13,[$in2],#48
+
+ lsl $padbit,$padbit,#24
+ add x15,$ctx,#48
+
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ and x5,x9,#0x03ffffff
+ ubfx x6,x8,#26,#26
+ ubfx x7,x9,#26,#26
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ extr x8,x12,x8,#52
+ extr x9,x13,x9,#52
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ fmov $IN23_0,x4
+ and x8,x8,#0x03ffffff
+ and x9,x9,#0x03ffffff
+ ubfx x10,x12,#14,#26
+ ubfx x11,x13,#14,#26
+ add x12,$padbit,x12,lsr#40
+ add x13,$padbit,x13,lsr#40
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ fmov $IN23_1,x6
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ fmov $IN23_2,x8
+ fmov $IN23_3,x10
+ fmov $IN23_4,x12
+
+ ldp x8,x12,[$inp],#16 // inp[0:1]
+ ldp x9,x13,[$inp],#48
+
+ ld1 {$R0,$R1,$S1,$R2},[x15],#64
+ ld1 {$S2,$R3,$S3,$R4},[x15],#64
+ ld1 {$S4},[x15]
+
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ and x5,x9,#0x03ffffff
+ ubfx x6,x8,#26,#26
+ ubfx x7,x9,#26,#26
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ extr x8,x12,x8,#52
+ extr x9,x13,x9,#52
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ fmov $IN01_0,x4
+ and x8,x8,#0x03ffffff
+ and x9,x9,#0x03ffffff
+ ubfx x10,x12,#14,#26
+ ubfx x11,x13,#14,#26
+ add x12,$padbit,x12,lsr#40
+ add x13,$padbit,x13,lsr#40
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ fmov $IN01_1,x6
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ fmov $IN01_2,x8
+ fmov $IN01_3,x10
+ fmov $IN01_4,x12
+
+ b.ls .Lskip_loop
+
+.align 4
+.Loop_neon:
+ ////////////////////////////////////////////////////////////////
+ // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ // \___________________/
+ // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ // \___________________/ \____________________/
+ //
+ // Note that we start with inp[2:3]*r^2. This is because it
+ // doesn't depend on reduction in previous iteration.
+ ////////////////////////////////////////////////////////////////
+ // d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0
+ // d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4
+ // d2 = h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3
+ // d1 = h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ // d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ subs $len,$len,#64
+ umull $ACC4,$IN23_0,${R4}[2]
+ csel $in2,$zeros,$in2,lo
+ umull $ACC3,$IN23_0,${R3}[2]
+ umull $ACC2,$IN23_0,${R2}[2]
+ ldp x8,x12,[$in2],#16 // inp[2:3] (or zero)
+ umull $ACC1,$IN23_0,${R1}[2]
+ ldp x9,x13,[$in2],#48
+ umull $ACC0,$IN23_0,${R0}[2]
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+
+ umlal $ACC4,$IN23_1,${R3}[2]
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ umlal $ACC3,$IN23_1,${R2}[2]
+ and x5,x9,#0x03ffffff
+ umlal $ACC2,$IN23_1,${R1}[2]
+ ubfx x6,x8,#26,#26
+ umlal $ACC1,$IN23_1,${R0}[2]
+ ubfx x7,x9,#26,#26
+ umlal $ACC0,$IN23_1,${S4}[2]
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+
+ umlal $ACC4,$IN23_2,${R2}[2]
+ extr x8,x12,x8,#52
+ umlal $ACC3,$IN23_2,${R1}[2]
+ extr x9,x13,x9,#52
+ umlal $ACC2,$IN23_2,${R0}[2]
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ umlal $ACC1,$IN23_2,${S4}[2]
+ fmov $IN23_0,x4
+ umlal $ACC0,$IN23_2,${S3}[2]
+ and x8,x8,#0x03ffffff
+
+ umlal $ACC4,$IN23_3,${R1}[2]
+ and x9,x9,#0x03ffffff
+ umlal $ACC3,$IN23_3,${R0}[2]
+ ubfx x10,x12,#14,#26
+ umlal $ACC2,$IN23_3,${S4}[2]
+ ubfx x11,x13,#14,#26
+ umlal $ACC1,$IN23_3,${S3}[2]
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ umlal $ACC0,$IN23_3,${S2}[2]
+ fmov $IN23_1,x6
+
+ add $IN01_2,$IN01_2,$H2
+ add x12,$padbit,x12,lsr#40
+ umlal $ACC4,$IN23_4,${R0}[2]
+ add x13,$padbit,x13,lsr#40
+ umlal $ACC3,$IN23_4,${S4}[2]
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ umlal $ACC2,$IN23_4,${S3}[2]
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ umlal $ACC1,$IN23_4,${S2}[2]
+ fmov $IN23_2,x8
+ umlal $ACC0,$IN23_4,${S1}[2]
+ fmov $IN23_3,x10
+
+ ////////////////////////////////////////////////////////////////
+ // (hash+inp[0:1])*r^4 and accumulate
+
+ add $IN01_0,$IN01_0,$H0
+ fmov $IN23_4,x12
+ umlal $ACC3,$IN01_2,${R1}[0]
+ ldp x8,x12,[$inp],#16 // inp[0:1]
+ umlal $ACC0,$IN01_2,${S3}[0]
+ ldp x9,x13,[$inp],#48
+ umlal $ACC4,$IN01_2,${R2}[0]
+ umlal $ACC1,$IN01_2,${S4}[0]
+ umlal $ACC2,$IN01_2,${R0}[0]
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+
+ add $IN01_1,$IN01_1,$H1
+ umlal $ACC3,$IN01_0,${R3}[0]
+ umlal $ACC4,$IN01_0,${R4}[0]
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ umlal $ACC2,$IN01_0,${R2}[0]
+ and x5,x9,#0x03ffffff
+ umlal $ACC0,$IN01_0,${R0}[0]
+ ubfx x6,x8,#26,#26
+ umlal $ACC1,$IN01_0,${R1}[0]
+ ubfx x7,x9,#26,#26
+
+ add $IN01_3,$IN01_3,$H3
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ umlal $ACC3,$IN01_1,${R2}[0]
+ extr x8,x12,x8,#52
+ umlal $ACC4,$IN01_1,${R3}[0]
+ extr x9,x13,x9,#52
+ umlal $ACC0,$IN01_1,${S4}[0]
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ umlal $ACC2,$IN01_1,${R1}[0]
+ fmov $IN01_0,x4
+ umlal $ACC1,$IN01_1,${R0}[0]
+ and x8,x8,#0x03ffffff
+
+ add $IN01_4,$IN01_4,$H4
+ and x9,x9,#0x03ffffff
+ umlal $ACC3,$IN01_3,${R0}[0]
+ ubfx x10,x12,#14,#26
+ umlal $ACC0,$IN01_3,${S2}[0]
+ ubfx x11,x13,#14,#26
+ umlal $ACC4,$IN01_3,${R1}[0]
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ umlal $ACC1,$IN01_3,${S3}[0]
+ fmov $IN01_1,x6
+ umlal $ACC2,$IN01_3,${S4}[0]
+ add x12,$padbit,x12,lsr#40
+
+ umlal $ACC3,$IN01_4,${S4}[0]
+ add x13,$padbit,x13,lsr#40
+ umlal $ACC0,$IN01_4,${S1}[0]
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ umlal $ACC4,$IN01_4,${R0}[0]
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ umlal $ACC1,$IN01_4,${S2}[0]
+ fmov $IN01_2,x8
+ umlal $ACC2,$IN01_4,${S3}[0]
+ fmov $IN01_3,x10
+
+ /////////////////////////////////////////////////////////////////
+ // lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ // and P. Schwabe
+
+ ushr $T0.2d,$ACC3,#26
+ fmov $IN01_4,x12
+ xtn $H3,$ACC3
+ ushr $T1.2d,$ACC0,#26
+ xtn $H0,$ACC0
+ add $ACC4,$ACC4,$T0.2d // h3 -> h4
+ bic $H3,#0xfc,lsl#24 // &=0x03ffffff
+ add $ACC1,$ACC1,$T1.2d // h0 -> h1
+ bic $H0,#0xfc,lsl#24
+
+ shrn $T0.2s,$ACC4,#26
+ xtn $H4,$ACC4
+ ushr $T1.2d,$ACC1,#26
+ xtn $H1,$ACC1
+ add $ACC2,$ACC2,$T1.2d // h1 -> h2
+ bic $H4,#0xfc,lsl#24
+ bic $H1,#0xfc,lsl#24
+
+ add $H0,$H0,$T0.2s
+ shl $T0.2s,$T0.2s,#2
+ shrn $T1.2s,$ACC2,#26
+ xtn $H2,$ACC2
+ add $H0,$H0,$T0.2s // h4 -> h0
+ add $H3,$H3,$T1.2s // h2 -> h3
+ bic $H2,#0xfc,lsl#24
+
+ ushr $T0.2s,$H0,#26
+ bic $H0,#0xfc,lsl#24
+ ushr $T1.2s,$H3,#26
+ bic $H3,#0xfc,lsl#24
+ add $H1,$H1,$T0.2s // h0 -> h1
+ add $H4,$H4,$T1.2s // h3 -> h4
+
+ b.hi .Loop_neon
+
+.Lskip_loop:
+ dup $IN23_2,${IN23_2}[0]
+ movi $MASK.2d,#-1
+ add $IN01_2,$IN01_2,$H2
+ ushr $MASK.2d,$MASK.2d,#38
+
+ ////////////////////////////////////////////////////////////////
+ // multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ adds $len,$len,#32
+ b.ne .Long_tail
+
+ dup $IN23_2,${IN01_2}[0]
+ add $IN23_0,$IN01_0,$H0
+ add $IN23_3,$IN01_3,$H3
+ add $IN23_1,$IN01_1,$H1
+ add $IN23_4,$IN01_4,$H4
+
+.Long_tail:
+ dup $IN23_0,${IN23_0}[0]
+ umull2 $ACC0,$IN23_2,${S3}
+ umull2 $ACC3,$IN23_2,${R1}
+ umull2 $ACC4,$IN23_2,${R2}
+ umull2 $ACC2,$IN23_2,${R0}
+ umull2 $ACC1,$IN23_2,${S4}
+
+ dup $IN23_1,${IN23_1}[0]
+ umlal2 $ACC0,$IN23_0,${R0}
+ umlal2 $ACC2,$IN23_0,${R2}
+ umlal2 $ACC3,$IN23_0,${R3}
+ umlal2 $ACC4,$IN23_0,${R4}
+ umlal2 $ACC1,$IN23_0,${R1}
+
+ dup $IN23_3,${IN23_3}[0]
+ umlal2 $ACC0,$IN23_1,${S4}
+ umlal2 $ACC3,$IN23_1,${R2}
+ umlal2 $ACC2,$IN23_1,${R1}
+ umlal2 $ACC4,$IN23_1,${R3}
+ umlal2 $ACC1,$IN23_1,${R0}
+
+ dup $IN23_4,${IN23_4}[0]
+ umlal2 $ACC3,$IN23_3,${R0}
+ umlal2 $ACC4,$IN23_3,${R1}
+ umlal2 $ACC0,$IN23_3,${S2}
+ umlal2 $ACC1,$IN23_3,${S3}
+ umlal2 $ACC2,$IN23_3,${S4}
+
+ umlal2 $ACC3,$IN23_4,${S4}
+ umlal2 $ACC0,$IN23_4,${S1}
+ umlal2 $ACC4,$IN23_4,${R0}
+ umlal2 $ACC1,$IN23_4,${S2}
+ umlal2 $ACC2,$IN23_4,${S3}
+
+ b.eq .Lshort_tail
+
+ ////////////////////////////////////////////////////////////////
+ // (hash+inp[0:1])*r^4:r^3 and accumulate
+
+ add $IN01_0,$IN01_0,$H0
+ umlal $ACC3,$IN01_2,${R1}
+ umlal $ACC0,$IN01_2,${S3}
+ umlal $ACC4,$IN01_2,${R2}
+ umlal $ACC1,$IN01_2,${S4}
+ umlal $ACC2,$IN01_2,${R0}
+
+ add $IN01_1,$IN01_1,$H1
+ umlal $ACC3,$IN01_0,${R3}
+ umlal $ACC0,$IN01_0,${R0}
+ umlal $ACC4,$IN01_0,${R4}
+ umlal $ACC1,$IN01_0,${R1}
+ umlal $ACC2,$IN01_0,${R2}
+
+ add $IN01_3,$IN01_3,$H3
+ umlal $ACC3,$IN01_1,${R2}
+ umlal $ACC0,$IN01_1,${S4}
+ umlal $ACC4,$IN01_1,${R3}
+ umlal $ACC1,$IN01_1,${R0}
+ umlal $ACC2,$IN01_1,${R1}
+
+ add $IN01_4,$IN01_4,$H4
+ umlal $ACC3,$IN01_3,${R0}
+ umlal $ACC0,$IN01_3,${S2}
+ umlal $ACC4,$IN01_3,${R1}
+ umlal $ACC1,$IN01_3,${S3}
+ umlal $ACC2,$IN01_3,${S4}
+
+ umlal $ACC3,$IN01_4,${S4}
+ umlal $ACC0,$IN01_4,${S1}
+ umlal $ACC4,$IN01_4,${R0}
+ umlal $ACC1,$IN01_4,${S2}
+ umlal $ACC2,$IN01_4,${S3}
+
+.Lshort_tail:
+ ////////////////////////////////////////////////////////////////
+ // horizontal add
+
+ addp $ACC3,$ACC3,$ACC3
+ ldp d8,d9,[sp,#16] // meet ABI requirements
+ addp $ACC0,$ACC0,$ACC0
+ ldp d10,d11,[sp,#32]
+ addp $ACC4,$ACC4,$ACC4
+ ldp d12,d13,[sp,#48]
+ addp $ACC1,$ACC1,$ACC1
+ ldp d14,d15,[sp,#64]
+ addp $ACC2,$ACC2,$ACC2
+
+ ////////////////////////////////////////////////////////////////
+ // lazy reduction, but without narrowing
+
+ ushr $T0.2d,$ACC3,#26
+ and $ACC3,$ACC3,$MASK.2d
+ ushr $T1.2d,$ACC0,#26
+ and $ACC0,$ACC0,$MASK.2d
+
+ add $ACC4,$ACC4,$T0.2d // h3 -> h4
+ add $ACC1,$ACC1,$T1.2d // h0 -> h1
+
+ ushr $T0.2d,$ACC4,#26
+ and $ACC4,$ACC4,$MASK.2d
+ ushr $T1.2d,$ACC1,#26
+ and $ACC1,$ACC1,$MASK.2d
+ add $ACC2,$ACC2,$T1.2d // h1 -> h2
+
+ add $ACC0,$ACC0,$T0.2d
+ shl $T0.2d,$T0.2d,#2
+ ushr $T1.2d,$ACC2,#26
+ and $ACC2,$ACC2,$MASK.2d
+ add $ACC0,$ACC0,$T0.2d // h4 -> h0
+ add $ACC3,$ACC3,$T1.2d // h2 -> h3
+
+ ushr $T0.2d,$ACC0,#26
+ and $ACC0,$ACC0,$MASK.2d
+ ushr $T1.2d,$ACC3,#26
+ and $ACC3,$ACC3,$MASK.2d
+ add $ACC1,$ACC1,$T0.2d // h0 -> h1
+ add $ACC4,$ACC4,$T1.2d // h3 -> h4
+
+ ////////////////////////////////////////////////////////////////
+ // write the result, can be partially reduced
+
+ st4 {$ACC0,$ACC1,$ACC2,$ACC3}[0],[$ctx],#16
+ st1 {$ACC4}[0],[$ctx]
+
+.Lno_data_neon:
+ ldr x29,[sp],#80
+ ret
+.size poly1305_blocks_neon,.-poly1305_blocks_neon
+
+.type poly1305_emit_neon,%function
+.align 5
+poly1305_emit_neon:
+ ldr $is_base2_26,[$ctx,#24]
+ cbz $is_base2_26,poly1305_emit
+
+ ldp w10,w11,[$ctx] // load hash value base 2^26
+ ldp w12,w13,[$ctx,#8]
+ ldr w14,[$ctx,#16]
+
+ add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64
+ lsr $h1,x12,#12
+ adds $h0,$h0,x12,lsl#52
+ add $h1,$h1,x13,lsl#14
+ adc $h1,$h1,xzr
+ lsr $h2,x14,#24
+ adds $h1,$h1,x14,lsl#40
+ adc $h2,$h2,xzr // can be partially reduced...
+
+ ldp $t0,$t1,[$nonce] // load nonce
+
+ and $d0,$h2,#-4 // ... so reduce
+ add $d0,$d0,$h2,lsr#2
+ and $h2,$h2,#3
+ adds $h0,$h0,$d0
+ adc $h1,$h1,xzr
+
+ adds $d0,$h0,#5 // compare to modulus
+ adcs $d1,$h1,xzr
+ adc $d2,$h2,xzr
+
+ tst $d2,#-4 // see if it's carried/borrowed
+
+ csel $h0,$h0,$d0,eq
+ csel $h1,$h1,$d1,eq
+
+#ifdef __ARMEB__
+ ror $t0,$t0,#32 // flip nonce words
+ ror $t1,$t1,#32
+#endif
+ adds $h0,$h0,$t0 // accumulate nonce
+ adc $h1,$h1,$t1
+#ifdef __ARMEB__
+ rev $h0,$h0 // flip output bytes
+ rev $h1,$h1
+#endif
+ stp $h0,$h1,[$mac] // write result
+
+ ret
+.size poly1305_emit_neon,.-poly1305_emit_neon
+
+.align 5
+.Lzeros:
+.long 0,0,0,0,0,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef __ILP32__
+.long OPENSSL_armcap_P-.
+#else
+.quad OPENSSL_armcap_P-.
+#endif
+.asciz "Poly1305 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+foreach (split("\n",$code)) {
+ s/\b(shrn\s+v[0-9]+)\.[24]d/$1.2s/ or
+ s/\b(fmov\s+)v([0-9]+)[^,]*,\s*x([0-9]+)/$1d$2,x$3/ or
+ (m/\bdup\b/ and (s/\.[24]s/.2d/g or 1)) or
+ (m/\b(eor|and)/ and (s/\.[248][sdh]/.16b/g or 1)) or
+ (m/\bum(ul|la)l\b/ and (s/\.4s/.2s/g or 1)) or
+ (m/\bum(ul|la)l2\b/ and (s/\.2s/.4s/g or 1)) or
+ (m/\bst[1-4]\s+{[^}]+}\[/ and (s/\.[24]d/.s/g or 1));
+
+ s/\.[124]([sd])\[/.$1\[/;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/poly1305/asm/poly1305-x86.pl b/src/crypto/poly1305/asm/poly1305-x86.pl
new file mode 100755
index 00000000..4ad2289e
--- /dev/null
+++ b/src/crypto/poly1305/asm/poly1305-x86.pl
@@ -0,0 +1,1788 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for x86.
+#
+# April 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone,
+# measured with rdtsc at fixed clock frequency.
+#
+# IALU/gcc-3.4(*) SSE2(**) AVX2
+# Pentium 15.7/+80% -
+# PIII 6.21/+90% -
+# P4 19.8/+40% 3.24
+# Core 2 4.85/+90% 1.80
+# Westmere 4.58/+100% 1.43
+# Sandy Bridge 3.90/+100% 1.36
+# Haswell 3.88/+70% 1.18 0.72
+# Silvermont 11.0/+40% 4.80
+# VIA Nano 6.71/+90% 2.47
+# Sledgehammer 3.51/+180% 4.27
+# Bulldozer 4.53/+140% 1.31
+#
+# (*) gcc 4.8 for some reason generated worse code;
+# (**) besides SSE2 there are floating-point and AVX options; FP
+# is deemed unnecessary, because pre-SSE2 processor are too
+# old to care about, while it's not the fastest option on
+# SSE2-capable ones; AVX is omitted, because it doesn't give
+# a lot of improvement, 5-10% depending on processor;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"poly1305-x86.pl",$ARGV[$#ARGV] eq "386");
+
+$sse2=$avx=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+if ($sse2) {
+ &static_label("const_sse2");
+ &static_label("enter_blocks");
+ &static_label("enter_emit");
+ &external_label("OPENSSL_ia32cap_P");
+
+ # This may be set to 2, but valgrind can't do AVX2 on 32-bit. Without a
+ # way to verify test coverage, keep it disabled.
+ $avx = 0;
+}
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^32
+# unsigned __int32 pad; # is_base2_26 in vector context
+# unsigned __int32 r[4]; # key value base 2^32
+
+&align(64);
+&function_begin("poly1305_init");
+ &mov ("edi",&wparam(0)); # context
+ &mov ("esi",&wparam(1)); # key
+ &mov ("ebp",&wparam(2)); # function table
+
+ &xor ("eax","eax");
+ &mov (&DWP(4*0,"edi"),"eax"); # zero hash value
+ &mov (&DWP(4*1,"edi"),"eax");
+ &mov (&DWP(4*2,"edi"),"eax");
+ &mov (&DWP(4*3,"edi"),"eax");
+ &mov (&DWP(4*4,"edi"),"eax");
+ &mov (&DWP(4*5,"edi"),"eax"); # is_base2_26
+
+ &cmp ("esi",0);
+ &je (&label("nokey"));
+
+ if ($sse2) {
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop("ebx");
+
+ &lea ("eax",&DWP("poly1305_blocks-".&label("pic_point"),"ebx"));
+ &lea ("edx",&DWP("poly1305_emit-".&label("pic_point"),"ebx"));
+
+ &picmeup("edi","OPENSSL_ia32cap_P","ebx",&label("pic_point"));
+ &mov ("ecx",&DWP(0,"edi"));
+ &and ("ecx",1<<26|1<<24);
+ &cmp ("ecx",1<<26|1<<24); # SSE2 and XMM?
+ &jne (&label("no_sse2"));
+
+ &lea ("eax",&DWP("_poly1305_blocks_sse2-".&label("pic_point"),"ebx"));
+ &lea ("edx",&DWP("_poly1305_emit_sse2-".&label("pic_point"),"ebx"));
+
+ if ($avx>1) {
+ &mov ("ecx",&DWP(8,"edi"));
+ &test ("ecx",1<<5); # AVX2?
+ &jz (&label("no_sse2"));
+
+ &lea ("eax",&DWP("_poly1305_blocks_avx2-".&label("pic_point"),"ebx"));
+ }
+ &set_label("no_sse2");
+ &mov ("edi",&wparam(0)); # reload context
+ &mov (&DWP(0,"ebp"),"eax"); # fill function table
+ &mov (&DWP(4,"ebp"),"edx");
+ }
+
+ &mov ("eax",&DWP(4*0,"esi")); # load input key
+ &mov ("ebx",&DWP(4*1,"esi"));
+ &mov ("ecx",&DWP(4*2,"esi"));
+ &mov ("edx",&DWP(4*3,"esi"));
+ &and ("eax",0x0fffffff);
+ &and ("ebx",0x0ffffffc);
+ &and ("ecx",0x0ffffffc);
+ &and ("edx",0x0ffffffc);
+ &mov (&DWP(4*6,"edi"),"eax");
+ &mov (&DWP(4*7,"edi"),"ebx");
+ &mov (&DWP(4*8,"edi"),"ecx");
+ &mov (&DWP(4*9,"edi"),"edx");
+
+ &mov ("eax",$sse2);
+&set_label("nokey");
+&function_end("poly1305_init");
+
+($h0,$h1,$h2,$h3,$h4,
+ $d0,$d1,$d2,$d3,
+ $r0,$r1,$r2,$r3,
+ $s1,$s2,$s3)=map(4*$_,(0..15));
+
+&function_begin("poly1305_blocks");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+&set_label("enter_blocks");
+ &and ("ecx",-15);
+ &jz (&label("nodata"));
+
+ &stack_push(16);
+ &mov ("eax",&DWP(4*6,"edi")); # r0
+ &mov ("ebx",&DWP(4*7,"edi")); # r1
+ &lea ("ebp",&DWP(0,"esi","ecx")); # end of input
+ &mov ("ecx",&DWP(4*8,"edi")); # r2
+ &mov ("edx",&DWP(4*9,"edi")); # r3
+
+ &mov (&wparam(2),"ebp");
+ &mov ("ebp","esi");
+
+ &mov (&DWP($r0,"esp"),"eax"); # r0
+ &mov ("eax","ebx");
+ &shr ("eax",2);
+ &mov (&DWP($r1,"esp"),"ebx"); # r1
+ &add ("eax","ebx"); # s1
+ &mov ("ebx","ecx");
+ &shr ("ebx",2);
+ &mov (&DWP($r2,"esp"),"ecx"); # r2
+ &add ("ebx","ecx"); # s2
+ &mov ("ecx","edx");
+ &shr ("ecx",2);
+ &mov (&DWP($r3,"esp"),"edx"); # r3
+ &add ("ecx","edx"); # s3
+ &mov (&DWP($s1,"esp"),"eax"); # s1
+ &mov (&DWP($s2,"esp"),"ebx"); # s2
+ &mov (&DWP($s3,"esp"),"ecx"); # s3
+
+ &mov ("eax",&DWP(4*0,"edi")); # load hash value
+ &mov ("ebx",&DWP(4*1,"edi"));
+ &mov ("ecx",&DWP(4*2,"edi"));
+ &mov ("esi",&DWP(4*3,"edi"));
+ &mov ("edi",&DWP(4*4,"edi"));
+ &jmp (&label("loop"));
+
+&set_label("loop",32);
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate input
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &adc ("esi",&DWP(4*3,"ebp"));
+ &lea ("ebp",&DWP(4*4,"ebp"));
+ &adc ("edi",&wparam(3)); # padbit
+
+ &mov (&DWP($h0,"esp"),"eax"); # put aside hash[+inp]
+ &mov (&DWP($h3,"esp"),"esi");
+
+ &mul (&DWP($r0,"esp")); # h0*r0
+ &mov (&DWP($h4,"esp"),"edi");
+ &mov ("edi","eax");
+ &mov ("eax","ebx"); # h1
+ &mov ("esi","edx");
+ &mul (&DWP($s3,"esp")); # h1*s3
+ &add ("edi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("esi","edx");
+ &mul (&DWP($s2,"esp")); # h2*s2
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("esi","edx");
+ &mul (&DWP($s1,"esp")); # h3*s1
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("esi","edx");
+
+ &mul (&DWP($r1,"esp")); # h0*r1
+ &mov (&DWP($d0,"esp"),"edi");
+ &xor ("edi","edi");
+ &add ("esi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("edi","edx");
+ &mul (&DWP($r0,"esp")); # h1*r0
+ &add ("esi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("edi","edx");
+ &mul (&DWP($s3,"esp")); # h2*s3
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("edi","edx");
+ &mul (&DWP($s2,"esp")); # h3*s2
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h4,"esp"));
+ &adc ("edi","edx");
+ &imul ("eax",&DWP($s1,"esp")); # h4*s1
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("edi",0);
+
+ &mul (&DWP($r2,"esp")); # h0*r2
+ &mov (&DWP($d1,"esp"),"esi");
+ &xor ("esi","esi");
+ &add ("edi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("esi","edx");
+ &mul (&DWP($r1,"esp")); # h1*r1
+ &add ("edi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("esi","edx");
+ &mul (&DWP($r0,"esp")); # h2*r0
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("esi","edx");
+ &mul (&DWP($s3,"esp")); # h3*s3
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h4,"esp"));
+ &adc ("esi","edx");
+ &imul ("eax",&DWP($s2,"esp")); # h4*s2
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("esi",0);
+
+ &mul (&DWP($r3,"esp")); # h0*r3
+ &mov (&DWP($d2,"esp"),"edi");
+ &xor ("edi","edi");
+ &add ("esi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("edi","edx");
+ &mul (&DWP($r2,"esp")); # h1*r2
+ &add ("esi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("edi","edx");
+ &mul (&DWP($r1,"esp")); # h2*r1
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("edi","edx");
+ &mul (&DWP($r0,"esp")); # h3*r0
+ &add ("esi","eax");
+ &mov ("ecx",&DWP($h4,"esp"));
+ &adc ("edi","edx");
+
+ &mov ("edx","ecx");
+ &imul ("ecx",&DWP($s3,"esp")); # h4*s3
+ &add ("esi","ecx");
+ &mov ("eax",&DWP($d0,"esp"));
+ &adc ("edi",0);
+
+ &imul ("edx",&DWP($r0,"esp")); # h4*r0
+ &add ("edx","edi");
+
+ &mov ("ebx",&DWP($d1,"esp"));
+ &mov ("ecx",&DWP($d2,"esp"));
+
+ &mov ("edi","edx"); # last reduction step
+ &shr ("edx",2);
+ &and ("edi",3);
+ &lea ("edx",&DWP(0,"edx","edx",4)); # *5
+ &add ("eax","edx");
+ &adc ("ebx",0);
+ &adc ("ecx",0);
+ &adc ("esi",0);
+
+ &cmp ("ebp",&wparam(2)); # done yet?
+ &jne (&label("loop"));
+
+ &mov ("edx",&wparam(0)); # ctx
+ &stack_pop(16);
+ &mov (&DWP(4*0,"edx"),"eax"); # store hash value
+ &mov (&DWP(4*1,"edx"),"ebx");
+ &mov (&DWP(4*2,"edx"),"ecx");
+ &mov (&DWP(4*3,"edx"),"esi");
+ &mov (&DWP(4*4,"edx"),"edi");
+&set_label("nodata");
+&function_end("poly1305_blocks");
+
+&function_begin("poly1305_emit");
+ &mov ("ebp",&wparam(0)); # context
+&set_label("enter_emit");
+ &mov ("edi",&wparam(1)); # output
+ &mov ("eax",&DWP(4*0,"ebp")); # load hash value
+ &mov ("ebx",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("esi",&DWP(4*4,"ebp"));
+
+ &add ("eax",5); # compare to modulus
+ &adc ("ebx",0);
+ &adc ("ecx",0);
+ &adc ("edx",0);
+ &adc ("esi",0);
+ &shr ("esi",2); # did it carry/borrow?
+ &neg ("esi"); # do we choose hash-modulus?
+
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+
+ &not ("esi"); # or original hash value?
+ &mov ("eax",&DWP(4*0,"ebp"));
+ &mov ("ebx",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("ebp",&wparam(2));
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &or ("eax",&DWP(4*0,"edi"));
+ &or ("ebx",&DWP(4*1,"edi"));
+ &or ("ecx",&DWP(4*2,"edi"));
+ &or ("edx",&DWP(4*3,"edi"));
+
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate key
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &adc ("edx",&DWP(4*3,"ebp"));
+
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+&function_end("poly1305_emit");
+
+if ($sse2) {
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^26
+# unsigned __int32 is_base2_26;
+# unsigned __int32 r[4]; # key value base 2^32
+# unsigned __int32 pad[2];
+# struct { unsigned __int32 r^4, r^3, r^2, r^1; } r[9];
+#
+# where r^n are base 2^26 digits of degrees of multiplier key. There are
+# 5 digits, but last four are interleaved with multiples of 5, totalling
+# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4.
+
+my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("xmm$_",(0..7));
+my $MASK=$T2; # borrow and keep in mind
+
+&align (32);
+&function_begin_B("_poly1305_init_sse2");
+ &movdqu ($D4,&QWP(4*6,"edi")); # key base 2^32
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &mov ("ebp","esp");
+ &sub ("esp",16*(9+5));
+ &and ("esp",-16);
+
+ #&pand ($D4,&QWP(96,"ebx")); # magic mask
+ &movq ($MASK,&QWP(64,"ebx"));
+
+ &movdqa ($D0,$D4);
+ &movdqa ($D1,$D4);
+ &movdqa ($D2,$D4);
+
+ &pand ($D0,$MASK); # -> base 2^26
+ &psrlq ($D1,26);
+ &psrldq ($D2,6);
+ &pand ($D1,$MASK);
+ &movdqa ($D3,$D2);
+ &psrlq ($D2,4)
+ &psrlq ($D3,30);
+ &pand ($D2,$MASK);
+ &pand ($D3,$MASK);
+ &psrldq ($D4,13);
+
+ &lea ("edx",&DWP(16*9,"esp")); # size optimization
+ &mov ("ecx",2);
+&set_label("square");
+ &movdqa (&QWP(16*0,"esp"),$D0);
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*2,"esp"),$D2);
+ &movdqa (&QWP(16*3,"esp"),$D3);
+ &movdqa (&QWP(16*4,"esp"),$D4);
+
+ &movdqa ($T1,$D1);
+ &movdqa ($T0,$D2);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D1); # *5
+ &paddd ($T0,$D2); # *5
+ &movdqa (&QWP(16*5,"esp"),$T1);
+ &movdqa (&QWP(16*6,"esp"),$T0);
+ &movdqa ($T1,$D3);
+ &movdqa ($T0,$D4);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D3); # *5
+ &paddd ($T0,$D4); # *5
+ &movdqa (&QWP(16*7,"esp"),$T1);
+ &movdqa (&QWP(16*8,"esp"),$T0);
+
+ &pshufd ($T1,$D0,0b01000100);
+ &movdqa ($T0,$D1);
+ &pshufd ($D1,$D1,0b01000100);
+ &pshufd ($D2,$D2,0b01000100);
+ &pshufd ($D3,$D3,0b01000100);
+ &pshufd ($D4,$D4,0b01000100);
+ &movdqa (&QWP(16*0,"edx"),$T1);
+ &movdqa (&QWP(16*1,"edx"),$D1);
+ &movdqa (&QWP(16*2,"edx"),$D2);
+ &movdqa (&QWP(16*3,"edx"),$D3);
+ &movdqa (&QWP(16*4,"edx"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($D4,$D0); # h4*r0
+ &pmuludq ($D3,$D0); # h3*r0
+ &pmuludq ($D2,$D0); # h2*r0
+ &pmuludq ($D1,$D0); # h1*r0
+ &pmuludq ($D0,$T1); # h0*r0
+
+sub pmuladd {
+my $load = shift;
+my $base = shift; $base = "esp" if (!defined($base));
+
+ ################################################################
+ # As for choice to "rotate" $T0-$T2 in order to move paddq
+ # past next multiplication. While it makes code harder to read
+ # and doesn't have significant effect on most processors, it
+ # makes a lot of difference on Atom, up to 30% improvement.
+
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*3,$base)); # r1*h3
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*2,$base)); # r1*h2
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*1,$base)); # r1*h1
+ &paddq ($D3,$T1);
+ &$load ($T1,5); # s1
+ &pmuludq ($T0,&QWP(16*0,$base)); # r1*h0
+ &paddq ($D2,$T2);
+ &pmuludq ($T1,&QWP(16*4,$base)); # s1*h4
+ &$load ($T2,2); # r2^n
+ &paddq ($D1,$T0);
+
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*2,$base)); # r2*h2
+ &paddq ($D0,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*1,$base)); # r2*h1
+ &paddq ($D4,$T2);
+ &$load ($T2,6); # s2^n
+ &pmuludq ($T1,&QWP(16*0,$base)); # r2*h0
+ &paddq ($D3,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*4,$base)); # s2*h4
+ &paddq ($D2,$T1);
+ &pmuludq ($T0,&QWP(16*3,$base)); # s2*h3
+ &$load ($T1,3); # r3^n
+ &paddq ($D1,$T2);
+
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*1,$base)); # r3*h1
+ &paddq ($D0,$T0);
+ &$load ($T0,7); # s3^n
+ &pmuludq ($T2,&QWP(16*0,$base)); # r3*h0
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*4,$base)); # s3*h4
+ &paddq ($D3,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*3,$base)); # s3*h3
+ &paddq ($D2,$T0);
+ &pmuludq ($T2,&QWP(16*2,$base)); # s3*h2
+ &$load ($T0,4); # r4^n
+ &paddq ($D1,$T1);
+
+ &$load ($T1,8); # s4^n
+ &pmuludq ($T0,&QWP(16*0,$base)); # r4*h0
+ &paddq ($D0,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*4,$base)); # s4*h4
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*1,$base)); # s4*h1
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*2,$base)); # s4*h2
+ &paddq ($D0,$T2);
+ &pmuludq ($T1,&QWP(16*3,$base)); # s4*h3
+ &movdqa ($MASK,&QWP(64,"ebx"));
+ &paddq ($D1,$T0);
+ &paddq ($D2,$T1);
+}
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &movdqa ($reg,&QWP(16*$i,"esp"));
+ },"edx");
+
+sub lazy_reduction {
+my $extra = shift;
+my $paddx = defined($extra) ? paddq : paddd;
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ &movdqa ($T0,$D3);
+ &pand ($D3,$MASK);
+ &psrlq ($T0,26);
+ &$extra () if (defined($extra));
+ &paddq ($T0,$D4); # h3 -> h4
+ &movdqa ($T1,$D0);
+ &pand ($D0,$MASK);
+ &psrlq ($T1,26);
+ &movdqa ($D4,$T0);
+ &paddq ($T1,$D1); # h0 -> h1
+ &psrlq ($T0,26);
+ &pand ($D4,$MASK);
+ &movdqa ($D1,$T1);
+ &psrlq ($T1,26);
+ &paddd ($D0,$T0); # favour paddd when
+ # possible, because
+ # paddq is "broken"
+ # on Atom
+ &psllq ($T0,2);
+ &paddq ($T1,$D2); # h1 -> h2
+ &$paddx ($T0,$D0); # h4 -> h0
+ &pand ($D1,$MASK);
+ &movdqa ($D2,$T1);
+ &psrlq ($T1,26);
+ &pand ($D2,$MASK);
+ &paddd ($T1,$D3); # h2 -> h3
+ &movdqa ($D0,$T0);
+ &psrlq ($T0,26);
+ &movdqa ($D3,$T1);
+ &psrlq ($T1,26);
+ &pand ($D0,$MASK);
+ &paddd ($D1,$T0); # h0 -> h1
+ &pand ($D3,$MASK);
+ &paddd ($D4,$T1); # h3 -> h4
+}
+ &lazy_reduction ();
+
+ &dec ("ecx");
+ &jz (&label("square_break"));
+
+ &punpcklqdq ($D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2
+ &punpcklqdq ($D1,&QWP(16*1,"esp"));
+ &punpcklqdq ($D2,&QWP(16*2,"esp"));
+ &punpcklqdq ($D3,&QWP(16*3,"esp"));
+ &punpcklqdq ($D4,&QWP(16*4,"esp"));
+ &jmp (&label("square"));
+
+&set_label("square_break");
+ &psllq ($D0,32); # -> r^3:0:r^4:0
+ &psllq ($D1,32);
+ &psllq ($D2,32);
+ &psllq ($D3,32);
+ &psllq ($D4,32);
+ &por ($D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2
+ &por ($D1,&QWP(16*1,"esp"));
+ &por ($D2,&QWP(16*2,"esp"));
+ &por ($D3,&QWP(16*3,"esp"));
+ &por ($D4,&QWP(16*4,"esp"));
+
+ &pshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4
+ &pshufd ($D1,$D1,0b10001101);
+ &pshufd ($D2,$D2,0b10001101);
+ &pshufd ($D3,$D3,0b10001101);
+ &pshufd ($D4,$D4,0b10001101);
+
+ &movdqu (&QWP(16*0,"edi"),$D0); # save the table
+ &movdqu (&QWP(16*1,"edi"),$D1);
+ &movdqu (&QWP(16*2,"edi"),$D2);
+ &movdqu (&QWP(16*3,"edi"),$D3);
+ &movdqu (&QWP(16*4,"edi"),$D4);
+
+ &movdqa ($T1,$D1);
+ &movdqa ($T0,$D2);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D1); # *5
+ &paddd ($T0,$D2); # *5
+ &movdqu (&QWP(16*5,"edi"),$T1);
+ &movdqu (&QWP(16*6,"edi"),$T0);
+ &movdqa ($T1,$D3);
+ &movdqa ($T0,$D4);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D3); # *5
+ &paddd ($T0,$D4); # *5
+ &movdqu (&QWP(16*7,"edi"),$T1);
+ &movdqu (&QWP(16*8,"edi"),$T0);
+
+ &mov ("esp","ebp");
+ &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization
+ &ret ();
+&function_end_B("_poly1305_init_sse2");
+
+&align (32);
+&function_begin("_poly1305_blocks_sse2");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+
+ &mov ("eax",&DWP(4*5,"edi")); # is_base2_26
+ &and ("ecx",-16);
+ &jz (&label("nodata"));
+ &cmp ("ecx",64);
+ &jae (&label("enter_sse2"));
+ &test ("eax","eax"); # is_base2_26?
+ &jz (&label("enter_blocks"));
+
+&set_label("enter_sse2",16);
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("ebx");
+ &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx"));
+
+ &test ("eax","eax"); # is_base2_26?
+ &jnz (&label("base2_26"));
+
+ &call ("_poly1305_init_sse2");
+
+ ################################################# base 2^32 -> base 2^26
+ &mov ("eax",&DWP(0,"edi"));
+ &mov ("ecx",&DWP(3,"edi"));
+ &mov ("edx",&DWP(6,"edi"));
+ &mov ("esi",&DWP(9,"edi"));
+ &mov ("ebp",&DWP(13,"edi"));
+ &mov (&DWP(4*5,"edi"),1); # is_base2_26
+
+ &shr ("ecx",2);
+ &and ("eax",0x3ffffff);
+ &shr ("edx",4);
+ &and ("ecx",0x3ffffff);
+ &shr ("esi",6);
+ &and ("edx",0x3ffffff);
+
+ &movd ($D0,"eax");
+ &movd ($D1,"ecx");
+ &movd ($D2,"edx");
+ &movd ($D3,"esi");
+ &movd ($D4,"ebp");
+
+ &mov ("esi",&wparam(1)); # [reload] inp
+ &mov ("ecx",&wparam(2)); # [reload] len
+ &jmp (&label("base2_32"));
+
+&set_label("base2_26",16);
+ &movd ($D0,&DWP(4*0,"edi")); # load hash value
+ &movd ($D1,&DWP(4*1,"edi"));
+ &movd ($D2,&DWP(4*2,"edi"));
+ &movd ($D3,&DWP(4*3,"edi"));
+ &movd ($D4,&DWP(4*4,"edi"));
+ &movdqa ($MASK,&QWP(64,"ebx"));
+
+&set_label("base2_32");
+ &mov ("eax",&wparam(3)); # padbit
+ &mov ("ebp","esp");
+
+ &sub ("esp",16*(5+5+5+9+9));
+ &and ("esp",-16);
+
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &shl ("eax",24); # padbit
+
+ &test ("ecx",31);
+ &jz (&label("even"));
+
+ ################################################################
+ # process single block, with SSE2, because it's still faster
+ # even though half of result is discarded
+
+ &movdqu ($T1,&QWP(0,"esi")); # input
+ &lea ("esi",&DWP(16,"esi"));
+
+ &movdqa ($T0,$T1); # -> base 2^26 ...
+ &pand ($T1,$MASK);
+ &paddd ($D0,$T1); # ... and accumuate
+
+ &movdqa ($T1,$T0);
+ &psrlq ($T0,26);
+ &psrldq ($T1,6);
+ &pand ($T0,$MASK);
+ &paddd ($D1,$T0);
+
+ &movdqa ($T0,$T1);
+ &psrlq ($T1,4);
+ &pand ($T1,$MASK);
+ &paddd ($D2,$T1);
+
+ &movdqa ($T1,$T0);
+ &psrlq ($T0,30);
+ &pand ($T0,$MASK);
+ &psrldq ($T1,7);
+ &paddd ($D3,$T0);
+
+ &movd ($T0,"eax"); # padbit
+ &paddd ($D4,$T1);
+ &movd ($T1,&DWP(16*0+12,"edi")); # r0
+ &paddd ($D4,$T0);
+
+ &movdqa (&QWP(16*0,"esp"),$D0);
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*2,"esp"),$D2);
+ &movdqa (&QWP(16*3,"esp"),$D3);
+ &movdqa (&QWP(16*4,"esp"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($D0,$T1); # h4*r0
+ &pmuludq ($D1,$T1); # h3*r0
+ &pmuludq ($D2,$T1); # h2*r0
+ &movd ($T0,&DWP(16*1+12,"edi")); # r1
+ &pmuludq ($D3,$T1); # h1*r0
+ &pmuludq ($D4,$T1); # h0*r0
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &movd ($reg,&DWP(16*$i+12,"edi"));
+ });
+
+ &lazy_reduction ();
+
+ &sub ("ecx",16);
+ &jz (&label("done"));
+
+&set_label("even");
+ &lea ("edx",&DWP(16*(5+5+5+9),"esp"));# size optimization
+ &lea ("eax",&DWP(-16*2,"esi"));
+ &sub ("ecx",64);
+
+ ################################################################
+ # expand and copy pre-calculated table to stack
+
+ &movdqu ($T0,&QWP(16*0,"edi")); # r^1:r^2:r^3:r^4
+ &pshufd ($T1,$T0,0b01000100); # duplicate r^3:r^4
+ &cmovb ("esi","eax");
+ &pshufd ($T0,$T0,0b11101110); # duplicate r^1:r^2
+ &movdqa (&QWP(16*0,"edx"),$T1);
+ &lea ("eax",&DWP(16*10,"esp"));
+ &movdqu ($T1,&QWP(16*1,"edi"));
+ &movdqa (&QWP(16*(0-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*1,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*2,"edi"));
+ &movdqa (&QWP(16*(1-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*2,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*3,"edi"));
+ &movdqa (&QWP(16*(2-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*3,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*4,"edi"));
+ &movdqa (&QWP(16*(3-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*4,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*5,"edi"));
+ &movdqa (&QWP(16*(4-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*5,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*6,"edi"));
+ &movdqa (&QWP(16*(5-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*6,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*7,"edi"));
+ &movdqa (&QWP(16*(6-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*7,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*8,"edi"));
+ &movdqa (&QWP(16*(7-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*8,"edx"),$T1);
+ &movdqa (&QWP(16*(8-9),"edx"),$T0);
+
+sub load_input {
+my ($inpbase,$offbase)=@_;
+
+ &movdqu ($T0,&QWP($inpbase+0,"esi")); # load input
+ &movdqu ($T1,&QWP($inpbase+16,"esi"));
+ &lea ("esi",&DWP(16*2,"esi"));
+
+ &movdqa (&QWP($offbase+16*2,"esp"),$D2);
+ &movdqa (&QWP($offbase+16*3,"esp"),$D3);
+ &movdqa (&QWP($offbase+16*4,"esp"),$D4);
+
+ &movdqa ($D2,$T0); # splat input
+ &movdqa ($D3,$T1);
+ &psrldq ($D2,6);
+ &psrldq ($D3,6);
+ &movdqa ($D4,$T0);
+ &punpcklqdq ($D2,$D3); # 2:3
+ &punpckhqdq ($D4,$T1); # 4
+ &punpcklqdq ($T0,$T1); # 0:1
+
+ &movdqa ($D3,$D2);
+ &psrlq ($D2,4);
+ &psrlq ($D3,30);
+ &movdqa ($T1,$T0);
+ &psrlq ($D4,40); # 4
+ &psrlq ($T1,26);
+ &pand ($T0,$MASK); # 0
+ &pand ($T1,$MASK); # 1
+ &pand ($D2,$MASK); # 2
+ &pand ($D3,$MASK); # 3
+ &por ($D4,&QWP(0,"ebx")); # padbit, yes, always
+
+ &movdqa (&QWP($offbase+16*0,"esp"),$D0) if ($offbase);
+ &movdqa (&QWP($offbase+16*1,"esp"),$D1) if ($offbase);
+}
+ &load_input (16*2,16*5);
+
+ &jbe (&label("skip_loop"));
+ &jmp (&label("loop"));
+
+&set_label("loop",32);
+ ################################################################
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ # \___________________/
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ # \___________________/ \____________________/
+ ################################################################
+
+ &movdqa ($T2,&QWP(16*(0-9),"edx")); # r0^2
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1
+ # d3 = h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4
+ # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+ # d1 = h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ # d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ &movdqa ($D1,$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &movdqa ($D0,$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &pmuludq ($D3,$T2); # h3*r0
+ &pmuludq ($D4,$T2); # h4*r0
+
+sub pmuladd_alt {
+my $addr = shift;
+
+ &pmuludq ($D0,&$addr(8)); # h1*s4
+ &movdqa ($T2,$D1);
+ &pmuludq ($D1,&$addr(1)); # h0*r1
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(2)); # h0*r2
+ &paddq ($D1,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(3)); # h0*r3
+ &paddq ($D2,$T2);
+ &movdqa ($T2,&QWP(16*1,"eax")); # pull h1
+ &pmuludq ($T1,&$addr(4)); # h0*r4
+ &paddq ($D3,$T0);
+
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(1)); # h1*r1
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(2)); # h1*r2
+ &paddq ($D2,$T2);
+ &movdqa ($T2,&QWP(16*2,"eax")); # pull h2
+ &pmuludq ($T1,&$addr(3)); # h1*r3
+ &paddq ($D3,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(7)); # h2*s3
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(8)); # h2*s4
+ &paddq ($D0,$T2);
+
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(1)); # h2*r1
+ &paddq ($D1,$T0);
+ &movdqa ($T0,&QWP(16*3,"eax")); # pull h3
+ &pmuludq ($T2,&$addr(2)); # h2*r2
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(6)); # h3*s2
+ &paddq ($D4,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(7)); # h3*s3
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(8)); # h3*s4
+ &paddq ($D1,$T1);
+
+ &movdqa ($T1,&QWP(16*4,"eax")); # pull h4
+ &pmuludq ($T0,&$addr(1)); # h3*r1
+ &paddq ($D2,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(8)); # h4*s4
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(5)); # h4*s1
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(6)); # h4*s2
+ &paddq ($D0,$T2);
+ &movdqa ($MASK,&QWP(64,"ebx"));
+ &pmuludq ($T1,&$addr(7)); # h4*s3
+ &paddq ($D1,$T0);
+ &paddq ($D2,$T1);
+}
+ &pmuladd_alt (sub { my $i=shift; &QWP(16*($i-9),"edx"); });
+
+ &load_input (-16*2,0);
+ &lea ("eax",&DWP(-16*2,"esi"));
+ &sub ("ecx",64);
+
+ &paddd ($T0,&QWP(16*(5+0),"esp")); # add hash value
+ &paddd ($T1,&QWP(16*(5+1),"esp"));
+ &paddd ($D2,&QWP(16*(5+2),"esp"));
+ &paddd ($D3,&QWP(16*(5+3),"esp"));
+ &paddd ($D4,&QWP(16*(5+4),"esp"));
+
+ &cmovb ("esi","eax");
+ &lea ("eax",&DWP(16*10,"esp"));
+
+ &movdqa ($T2,&QWP(16*0,"edx")); # r0^4
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 += h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1
+ # d3 += h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4
+ # d2 += h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+ # d1 += h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ # d0 += h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ &movdqa ($D1,$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &paddq ($T0,$D0);
+ &movdqa ($D0,$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &pmuludq ($D3,$T2); # h3*r0
+ &pmuludq ($D4,$T2); # h4*r0
+
+ &paddq ($T1,&QWP(16*1,"esp"));
+ &paddq ($D2,&QWP(16*2,"esp"));
+ &paddq ($D3,&QWP(16*3,"esp"));
+ &paddq ($D4,&QWP(16*4,"esp"));
+
+ &pmuladd_alt (sub { my $i=shift; &QWP(16*$i,"edx"); });
+
+ &lazy_reduction ();
+
+ &load_input (16*2,16*5);
+
+ &ja (&label("loop"));
+
+&set_label("skip_loop");
+ ################################################################
+ # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ &pshufd ($T2,&QWP(16*(0-9),"edx"),0x10);# r0^n
+ &add ("ecx",32);
+ &jnz (&label("long_tail"));
+
+ &paddd ($T0,$D0); # add hash value
+ &paddd ($T1,$D1);
+ &paddd ($D2,&QWP(16*7,"esp"));
+ &paddd ($D3,&QWP(16*8,"esp"));
+ &paddd ($D4,&QWP(16*9,"esp"));
+
+&set_label("long_tail");
+
+ &movdqa (&QWP(16*0,"eax"),$T0);
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($T0,$T2); # h0*r0
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &movdqa ($D0,$T0);
+ &pshufd ($T0,&QWP(16*(1-9),"edx"),0x10);# r1^n
+ &pmuludq ($D3,$T2); # h3*r0
+ &movdqa ($D1,$T1);
+ &pmuludq ($D4,$T2); # h4*r0
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &pshufd ($reg,&QWP(16*($i-9),"edx"),0x10);
+ },"eax");
+
+ &jz (&label("short_tail"));
+
+ &load_input (-16*2,0);
+
+ &pshufd ($T2,&QWP(16*0,"edx"),0x10); # r0^n
+ &paddd ($T0,&QWP(16*5,"esp")); # add hash value
+ &paddd ($T1,&QWP(16*6,"esp"));
+ &paddd ($D2,&QWP(16*7,"esp"));
+ &paddd ($D3,&QWP(16*8,"esp"));
+ &paddd ($D4,&QWP(16*9,"esp"));
+
+ ################################################################
+ # multiply inp[0:1] by r^4:r^3 and accumulate
+
+ &movdqa (&QWP(16*0,"esp"),$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &movdqa (&QWP(16*1,"esp"),$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$D2);
+ &pmuludq ($D2,$T2); # h2*r0
+ &paddq ($D1,$T1);
+ &movdqa ($T1,$D3);
+ &pmuludq ($D3,$T2); # h3*r0
+ &paddq ($D2,&QWP(16*2,"esp"));
+ &movdqa (&QWP(16*2,"esp"),$T0);
+ &pshufd ($T0,&QWP(16*1,"edx"),0x10); # r1^n
+ &paddq ($D3,&QWP(16*3,"esp"));
+ &movdqa (&QWP(16*3,"esp"),$T1);
+ &movdqa ($T1,$D4);
+ &pmuludq ($D4,$T2); # h4*r0
+ &paddq ($D4,&QWP(16*4,"esp"));
+ &movdqa (&QWP(16*4,"esp"),$T1);
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &pshufd ($reg,&QWP(16*$i,"edx"),0x10);
+ });
+
+&set_label("short_tail");
+
+ ################################################################
+ # horizontal addition
+
+ &pshufd ($T1,$D4,0b01001110);
+ &pshufd ($T0,$D3,0b01001110);
+ &paddq ($D4,$T1);
+ &paddq ($D3,$T0);
+ &pshufd ($T1,$D0,0b01001110);
+ &pshufd ($T0,$D1,0b01001110);
+ &paddq ($D0,$T1);
+ &paddq ($D1,$T0);
+ &pshufd ($T1,$D2,0b01001110);
+ #&paddq ($D2,$T1);
+
+ &lazy_reduction (sub { &paddq ($D2,$T1) });
+
+&set_label("done");
+ &movd (&DWP(-16*3+4*0,"edi"),$D0); # store hash value
+ &movd (&DWP(-16*3+4*1,"edi"),$D1);
+ &movd (&DWP(-16*3+4*2,"edi"),$D2);
+ &movd (&DWP(-16*3+4*3,"edi"),$D3);
+ &movd (&DWP(-16*3+4*4,"edi"),$D4);
+ &mov ("esp","ebp");
+&set_label("nodata");
+&function_end("_poly1305_blocks_sse2");
+
+&align (32);
+&function_begin("_poly1305_emit_sse2");
+ &mov ("ebp",&wparam(0)); # context
+
+ &cmp (&DWP(4*5,"ebp"),0); # is_base2_26?
+ &je (&label("enter_emit"));
+
+ &mov ("eax",&DWP(4*0,"ebp")); # load hash value
+ &mov ("edi",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("esi",&DWP(4*4,"ebp"));
+
+ &mov ("ebx","edi"); # base 2^26 -> base 2^32
+ &shl ("edi",26);
+ &shr ("ebx",6);
+ &add ("eax","edi");
+ &mov ("edi","ecx");
+ &adc ("ebx",0);
+
+ &shl ("edi",20);
+ &shr ("ecx",12);
+ &add ("ebx","edi");
+ &mov ("edi","edx");
+ &adc ("ecx",0);
+
+ &shl ("edi",14);
+ &shr ("edx",18);
+ &add ("ecx","edi");
+ &mov ("edi","esi");
+ &adc ("edx",0);
+
+ &shl ("edi",8);
+ &shr ("esi",24);
+ &add ("edx","edi");
+ &adc ("esi",0); # can be partially reduced
+
+ &mov ("edi","esi"); # final reduction
+ &and ("esi",3);
+ &shr ("edi",2);
+ &lea ("ebp",&DWP(0,"edi","edi",4)); # *5
+ &mov ("edi",&wparam(1)); # output
+ add ("eax","ebp");
+ &mov ("ebp",&wparam(2)); # key
+ adc ("ebx",0);
+ adc ("ecx",0);
+ adc ("edx",0);
+
+ &movd ($D0,"eax"); # offload original hash value
+ &add ("eax",5); # compare to modulus
+ &movd ($D1,"ebx");
+ &adc ("ebx",0);
+ &movd ($D2,"ecx");
+ &adc ("ecx",0);
+ &movd ($D3,"edx");
+ &adc ("edx",0);
+ &adc ("esi",0);
+ &shr ("esi",2); # did it carry/borrow?
+
+ &neg ("esi"); # do we choose (hash-modulus) ...
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &mov (&DWP(4*0,"edi"),"eax");
+ &movd ("eax",$D0);
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &movd ("ebx",$D1);
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &movd ("ecx",$D2);
+ &mov (&DWP(4*3,"edi"),"edx");
+ &movd ("edx",$D3);
+
+ &not ("esi"); # ... or original hash value?
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &or ("eax",&DWP(4*0,"edi"));
+ &and ("ecx","esi");
+ &or ("ebx",&DWP(4*1,"edi"));
+ &and ("edx","esi");
+ &or ("ecx",&DWP(4*2,"edi"));
+ &or ("edx",&DWP(4*3,"edi"));
+
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate key
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &mov (&DWP(4*0,"edi"),"eax");
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &adc ("edx",&DWP(4*3,"ebp"));
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+&function_end("_poly1305_emit_sse2");
+
+if ($avx>1) {
+########################################################################
+# Note that poly1305_init_avx2 operates on %xmm, I could have used
+# poly1305_init_sse2...
+
+&align (32);
+&function_begin_B("_poly1305_init_avx2");
+ &vmovdqu ($D4,&QWP(4*6,"edi")); # key base 2^32
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &mov ("ebp","esp");
+ &sub ("esp",16*(9+5));
+ &and ("esp",-16);
+
+ #&vpand ($D4,$D4,&QWP(96,"ebx")); # magic mask
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+
+ &vpand ($D0,$D4,$MASK); # -> base 2^26
+ &vpsrlq ($D1,$D4,26);
+ &vpsrldq ($D3,$D4,6);
+ &vpand ($D1,$D1,$MASK);
+ &vpsrlq ($D2,$D3,4)
+ &vpsrlq ($D3,$D3,30);
+ &vpand ($D2,$D2,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrldq ($D4,$D4,13);
+
+ &lea ("edx",&DWP(16*9,"esp")); # size optimization
+ &mov ("ecx",2);
+&set_label("square");
+ &vmovdqa (&QWP(16*0,"esp"),$D0);
+ &vmovdqa (&QWP(16*1,"esp"),$D1);
+ &vmovdqa (&QWP(16*2,"esp"),$D2);
+ &vmovdqa (&QWP(16*3,"esp"),$D3);
+ &vmovdqa (&QWP(16*4,"esp"),$D4);
+
+ &vpslld ($T1,$D1,2);
+ &vpslld ($T0,$D2,2);
+ &vpaddd ($T1,$T1,$D1); # *5
+ &vpaddd ($T0,$T0,$D2); # *5
+ &vmovdqa (&QWP(16*5,"esp"),$T1);
+ &vmovdqa (&QWP(16*6,"esp"),$T0);
+ &vpslld ($T1,$D3,2);
+ &vpslld ($T0,$D4,2);
+ &vpaddd ($T1,$T1,$D3); # *5
+ &vpaddd ($T0,$T0,$D4); # *5
+ &vmovdqa (&QWP(16*7,"esp"),$T1);
+ &vmovdqa (&QWP(16*8,"esp"),$T0);
+
+ &vpshufd ($T0,$D0,0b01000100);
+ &vmovdqa ($T1,$D1);
+ &vpshufd ($D1,$D1,0b01000100);
+ &vpshufd ($D2,$D2,0b01000100);
+ &vpshufd ($D3,$D3,0b01000100);
+ &vpshufd ($D4,$D4,0b01000100);
+ &vmovdqa (&QWP(16*0,"edx"),$T0);
+ &vmovdqa (&QWP(16*1,"edx"),$D1);
+ &vmovdqa (&QWP(16*2,"edx"),$D2);
+ &vmovdqa (&QWP(16*3,"edx"),$D3);
+ &vmovdqa (&QWP(16*4,"edx"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &vpmuludq ($D4,$D4,$D0); # h4*r0
+ &vpmuludq ($D3,$D3,$D0); # h3*r0
+ &vpmuludq ($D2,$D2,$D0); # h2*r0
+ &vpmuludq ($D1,$D1,$D0); # h1*r0
+ &vpmuludq ($D0,$T0,$D0); # h0*r0
+
+ &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # r1*h3
+ &vpaddq ($D4,$D4,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*2,"edx")); # r1*h2
+ &vpaddq ($D3,$D3,$T2);
+ &vpmuludq ($T0,$T1,&QWP(16*1,"edx")); # r1*h1
+ &vpaddq ($D2,$D2,$T0);
+ &vmovdqa ($T2,&QWP(16*5,"esp")); # s1
+ &vpmuludq ($T1,$T1,&QWP(16*0,"edx")); # r1*h0
+ &vpaddq ($D1,$D1,$T1);
+ &vmovdqa ($T0,&QWP(16*2,"esp")); # r2
+ &vpmuludq ($T2,$T2,&QWP(16*4,"edx")); # s1*h4
+ &vpaddq ($D0,$D0,$T2);
+
+ &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # r2*h2
+ &vpaddq ($D4,$D4,$T1);
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r2*h1
+ &vpaddq ($D3,$D3,$T2);
+ &vmovdqa ($T1,&QWP(16*6,"esp")); # s2
+ &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r2*h0
+ &vpaddq ($D2,$D2,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s2*h4
+ &vpaddq ($D1,$D1,$T2);
+ &vmovdqa ($T0,&QWP(16*3,"esp")); # r3
+ &vpmuludq ($T1,$T1,&QWP(16*3,"edx")); # s2*h3
+ &vpaddq ($D0,$D0,$T1);
+
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r3*h1
+ &vpaddq ($D4,$D4,$T2);
+ &vmovdqa ($T1,&QWP(16*7,"esp")); # s3
+ &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r3*h0
+ &vpaddq ($D3,$D3,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s3*h4
+ &vpaddq ($D2,$D2,$T2);
+ &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # s3*h3
+ &vpaddq ($D1,$D1,$T0);
+ &vmovdqa ($T2,&QWP(16*4,"esp")); # r4
+ &vpmuludq ($T1,$T1,&QWP(16*2,"edx")); # s3*h2
+ &vpaddq ($D0,$D0,$T1);
+
+ &vmovdqa ($T0,&QWP(16*8,"esp")); # s4
+ &vpmuludq ($T2,$T2,&QWP(16*0,"edx")); # r4*h0
+ &vpaddq ($D4,$D4,$T2);
+ &vpmuludq ($T1,$T0,&QWP(16*4,"edx")); # s4*h4
+ &vpaddq ($D3,$D3,$T1);
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # s4*h1
+ &vpaddq ($D0,$D0,$T2);
+ &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # s4*h2
+ &vpaddq ($D1,$D1,$T1);
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &vpmuludq ($T0,$T0,&QWP(16*3,"edx")); # s4*h3
+ &vpaddq ($D2,$D2,$T0);
+
+ ################################################################
+ # lazy reduction
+ &vpsrlq ($T0,$D3,26);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrlq ($T1,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpaddq ($D4,$D4,$T0); # h3 -> h4
+ &vpaddq ($D1,$D1,$T1); # h0 -> h1
+ &vpsrlq ($T0,$D4,26);
+ &vpand ($D4,$D4,$MASK);
+ &vpsrlq ($T1,$D1,26);
+ &vpand ($D1,$D1,$MASK);
+ &vpaddq ($D2,$D2,$T1); # h1 -> h2
+ &vpaddd ($D0,$D0,$T0);
+ &vpsllq ($T0,$T0,2);
+ &vpsrlq ($T1,$D2,26);
+ &vpand ($D2,$D2,$MASK);
+ &vpaddd ($D0,$D0,$T0); # h4 -> h0
+ &vpaddd ($D3,$D3,$T1); # h2 -> h3
+ &vpsrlq ($T1,$D3,26);
+ &vpsrlq ($T0,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpaddd ($D1,$D1,$T0); # h0 -> h1
+ &vpaddd ($D4,$D4,$T1); # h3 -> h4
+
+ &dec ("ecx");
+ &jz (&label("square_break"));
+
+ &vpunpcklqdq ($D0,$D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2
+ &vpunpcklqdq ($D1,$D1,&QWP(16*1,"esp"));
+ &vpunpcklqdq ($D2,$D2,&QWP(16*2,"esp"));
+ &vpunpcklqdq ($D3,$D3,&QWP(16*3,"esp"));
+ &vpunpcklqdq ($D4,$D4,&QWP(16*4,"esp"));
+ &jmp (&label("square"));
+
+&set_label("square_break");
+ &vpsllq ($D0,$D0,32); # -> r^3:0:r^4:0
+ &vpsllq ($D1,$D1,32);
+ &vpsllq ($D2,$D2,32);
+ &vpsllq ($D3,$D3,32);
+ &vpsllq ($D4,$D4,32);
+ &vpor ($D0,$D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2
+ &vpor ($D1,$D1,&QWP(16*1,"esp"));
+ &vpor ($D2,$D2,&QWP(16*2,"esp"));
+ &vpor ($D3,$D3,&QWP(16*3,"esp"));
+ &vpor ($D4,$D4,&QWP(16*4,"esp"));
+
+ &vpshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4
+ &vpshufd ($D1,$D1,0b10001101);
+ &vpshufd ($D2,$D2,0b10001101);
+ &vpshufd ($D3,$D3,0b10001101);
+ &vpshufd ($D4,$D4,0b10001101);
+
+ &vmovdqu (&QWP(16*0,"edi"),$D0); # save the table
+ &vmovdqu (&QWP(16*1,"edi"),$D1);
+ &vmovdqu (&QWP(16*2,"edi"),$D2);
+ &vmovdqu (&QWP(16*3,"edi"),$D3);
+ &vmovdqu (&QWP(16*4,"edi"),$D4);
+
+ &vpslld ($T1,$D1,2);
+ &vpslld ($T0,$D2,2);
+ &vpaddd ($T1,$T1,$D1); # *5
+ &vpaddd ($T0,$T0,$D2); # *5
+ &vmovdqu (&QWP(16*5,"edi"),$T1);
+ &vmovdqu (&QWP(16*6,"edi"),$T0);
+ &vpslld ($T1,$D3,2);
+ &vpslld ($T0,$D4,2);
+ &vpaddd ($T1,$T1,$D3); # *5
+ &vpaddd ($T0,$T0,$D4); # *5
+ &vmovdqu (&QWP(16*7,"edi"),$T1);
+ &vmovdqu (&QWP(16*8,"edi"),$T0);
+
+ &mov ("esp","ebp");
+ &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization
+ &ret ();
+&function_end_B("_poly1305_init_avx2");
+
+########################################################################
+# now it's time to switch to %ymm
+
+my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("ymm$_",(0..7));
+my $MASK=$T2;
+
+sub X { my $reg=shift; $reg=~s/^ymm/xmm/; $reg; }
+
+&align (32);
+&function_begin("_poly1305_blocks_avx2");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+
+ &mov ("eax",&DWP(4*5,"edi")); # is_base2_26
+ &and ("ecx",-16);
+ &jz (&label("nodata"));
+ &cmp ("ecx",64);
+ &jae (&label("enter_avx2"));
+ &test ("eax","eax"); # is_base2_26?
+ &jz (&label("enter_blocks"));
+
+&set_label("enter_avx2");
+ &vzeroupper ();
+
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("ebx");
+ &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx"));
+
+ &test ("eax","eax"); # is_base2_26?
+ &jnz (&label("base2_26"));
+
+ &call ("_poly1305_init_avx2");
+
+ ################################################# base 2^32 -> base 2^26
+ &mov ("eax",&DWP(0,"edi"));
+ &mov ("ecx",&DWP(3,"edi"));
+ &mov ("edx",&DWP(6,"edi"));
+ &mov ("esi",&DWP(9,"edi"));
+ &mov ("ebp",&DWP(13,"edi"));
+
+ &shr ("ecx",2);
+ &and ("eax",0x3ffffff);
+ &shr ("edx",4);
+ &and ("ecx",0x3ffffff);
+ &shr ("esi",6);
+ &and ("edx",0x3ffffff);
+
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ecx");
+ &mov (&DWP(4*2,"edi"),"edx");
+ &mov (&DWP(4*3,"edi"),"esi");
+ &mov (&DWP(4*4,"edi"),"ebp");
+ &mov (&DWP(4*5,"edi"),1); # is_base2_26
+
+ &mov ("esi",&wparam(1)); # [reload] inp
+ &mov ("ecx",&wparam(2)); # [reload] len
+
+&set_label("base2_26");
+ &mov ("eax",&wparam(3)); # padbit
+ &mov ("ebp","esp");
+
+ &sub ("esp",32*(5+9));
+ &and ("esp",-512); # ensure that frame
+ # doesn't cross page
+ # boundary, which is
+ # essential for
+ # misaligned 32-byte
+ # loads
+
+ ################################################################
+ # expand and copy pre-calculated table to stack
+
+ &vmovdqu (&X($D0),&QWP(16*(3+0),"edi"));
+ &lea ("edx",&DWP(32*5+128,"esp")); # +128 size optimization
+ &vmovdqu (&X($D1),&QWP(16*(3+1),"edi"));
+ &vmovdqu (&X($D2),&QWP(16*(3+2),"edi"));
+ &vmovdqu (&X($D3),&QWP(16*(3+3),"edi"));
+ &vmovdqu (&X($D4),&QWP(16*(3+4),"edi"));
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &vpermq ($D0,$D0,0b01000000); # 00001234 -> 12343434
+ &vpermq ($D1,$D1,0b01000000);
+ &vpermq ($D2,$D2,0b01000000);
+ &vpermq ($D3,$D3,0b01000000);
+ &vpermq ($D4,$D4,0b01000000);
+ &vpshufd ($D0,$D0,0b11001000); # 12343434 -> 14243444
+ &vpshufd ($D1,$D1,0b11001000);
+ &vpshufd ($D2,$D2,0b11001000);
+ &vpshufd ($D3,$D3,0b11001000);
+ &vpshufd ($D4,$D4,0b11001000);
+ &vmovdqa (&QWP(32*0-128,"edx"),$D0);
+ &vmovdqu (&X($D0),&QWP(16*5,"edi"));
+ &vmovdqa (&QWP(32*1-128,"edx"),$D1);
+ &vmovdqu (&X($D1),&QWP(16*6,"edi"));
+ &vmovdqa (&QWP(32*2-128,"edx"),$D2);
+ &vmovdqu (&X($D2),&QWP(16*7,"edi"));
+ &vmovdqa (&QWP(32*3-128,"edx"),$D3);
+ &vmovdqu (&X($D3),&QWP(16*8,"edi"));
+ &vmovdqa (&QWP(32*4-128,"edx"),$D4);
+ &vpermq ($D0,$D0,0b01000000);
+ &vpermq ($D1,$D1,0b01000000);
+ &vpermq ($D2,$D2,0b01000000);
+ &vpermq ($D3,$D3,0b01000000);
+ &vpshufd ($D0,$D0,0b11001000);
+ &vpshufd ($D1,$D1,0b11001000);
+ &vpshufd ($D2,$D2,0b11001000);
+ &vpshufd ($D3,$D3,0b11001000);
+ &vmovdqa (&QWP(32*5-128,"edx"),$D0);
+ &vmovd (&X($D0),&DWP(-16*3+4*0,"edi"));# load hash value
+ &vmovdqa (&QWP(32*6-128,"edx"),$D1);
+ &vmovd (&X($D1),&DWP(-16*3+4*1,"edi"));
+ &vmovdqa (&QWP(32*7-128,"edx"),$D2);
+ &vmovd (&X($D2),&DWP(-16*3+4*2,"edi"));
+ &vmovdqa (&QWP(32*8-128,"edx"),$D3);
+ &vmovd (&X($D3),&DWP(-16*3+4*3,"edi"));
+ &vmovd (&X($D4),&DWP(-16*3+4*4,"edi"));
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &neg ("eax"); # padbit
+
+ &test ("ecx",63);
+ &jz (&label("even"));
+
+ &mov ("edx","ecx");
+ &and ("ecx",-64);
+ &and ("edx",63);
+
+ &vmovdqu (&X($T0),&QWP(16*0,"esi"));
+ &cmp ("edx",32);
+ &jb (&label("one"));
+
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &je (&label("two"));
+
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &lea ("esi",&DWP(16*3,"esi"));
+ &lea ("ebx",&DWP(8,"ebx")); # three padbits
+ &lea ("edx",&DWP(32*5+128+8,"esp")); # --:r^1:r^2:r^3 (*)
+ &jmp (&label("tail"));
+
+&set_label("two");
+ &lea ("esi",&DWP(16*2,"esi"));
+ &lea ("ebx",&DWP(16,"ebx")); # two padbits
+ &lea ("edx",&DWP(32*5+128+16,"esp"));# --:--:r^1:r^2 (*)
+ &jmp (&label("tail"));
+
+&set_label("one");
+ &lea ("esi",&DWP(16*1,"esi"));
+ &vpxor ($T1,$T1,$T1);
+ &lea ("ebx",&DWP(32,"ebx","eax",8)); # one or no padbits
+ &lea ("edx",&DWP(32*5+128+24,"esp"));# --:--:--:r^1 (*)
+ &jmp (&label("tail"));
+
+# (*) spots marked with '--' are data from next table entry, but they
+# are multiplied by 0 and therefore rendered insignificant
+
+&set_label("even",32);
+ &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1);
+ &lea ("esi",&DWP(16*4,"esi"));
+ &sub ("ecx",64);
+ &jz (&label("tail"));
+
+&set_label("loop");
+ ################################################################
+ # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4
+ # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3
+ # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2
+ # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1
+ # \________/ \_______/
+ ################################################################
+
+sub vsplat_input {
+ &vmovdqa (&QWP(32*2,"esp"),$D2);
+ &vpsrldq ($D2,$T0,6); # splat input
+ &vmovdqa (&QWP(32*0,"esp"),$D0);
+ &vpsrldq ($D0,$T1,6);
+ &vmovdqa (&QWP(32*1,"esp"),$D1);
+ &vpunpckhqdq ($D1,$T0,$T1); # 4
+ &vpunpcklqdq ($T0,$T0,$T1); # 0:1
+ &vpunpcklqdq ($D2,$D2,$D0); # 2:3
+
+ &vpsrlq ($D0,$D2,30);
+ &vpsrlq ($D2,$D2,4);
+ &vpsrlq ($T1,$T0,26);
+ &vpsrlq ($D1,$D1,40); # 4
+ &vpand ($D2,$D2,$MASK); # 2
+ &vpand ($T0,$T0,$MASK); # 0
+ &vpand ($T1,$T1,$MASK); # 1
+ &vpand ($D0,$D0,$MASK); # 3 (*)
+ &vpor ($D1,$D1,&QWP(0,"ebx")); # padbit, yes, always
+
+ # (*) note that output is counterintuitive, inp[3:4] is
+ # returned in $D1-2, while $D3-4 are preserved;
+}
+ &vsplat_input ();
+
+sub vpmuladd {
+my $addr = shift;
+
+ &vpaddq ($D2,$D2,&QWP(32*2,"esp")); # add hash value
+ &vpaddq ($T0,$T0,&QWP(32*0,"esp"));
+ &vpaddq ($T1,$T1,&QWP(32*1,"esp"));
+ &vpaddq ($D0,$D0,$D3);
+ &vpaddq ($D1,$D1,$D4);
+
+ ################################################################
+ # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4
+ # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0
+ # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1
+ # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2
+ # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+
+ &vpmuludq ($D3,$D2,&$addr(1)); # d3 = h2*r1
+ &vmovdqa (QWP(32*1,"esp"),$T1);
+ &vpmuludq ($D4,$D2,&$addr(2)); # d4 = h2*r2
+ &vmovdqa (QWP(32*3,"esp"),$D0);
+ &vpmuludq ($D0,$D2,&$addr(7)); # d0 = h2*s3
+ &vmovdqa (QWP(32*4,"esp"),$D1);
+ &vpmuludq ($D1,$D2,&$addr(8)); # d1 = h2*s4
+ &vpmuludq ($D2,$D2,&$addr(0)); # d2 = h2*r0
+
+ &vpmuludq ($T2,$T0,&$addr(3)); # h0*r3
+ &vpaddq ($D3,$D3,$T2); # d3 += h0*r3
+ &vpmuludq ($T1,$T0,&$addr(4)); # h0*r4
+ &vpaddq ($D4,$D4,$T1); # d4 + h0*r4
+ &vpmuludq ($T2,$T0,&$addr(0)); # h0*r0
+ &vpaddq ($D0,$D0,$T2); # d0 + h0*r0
+ &vmovdqa ($T2,&QWP(32*1,"esp")); # h1
+ &vpmuludq ($T1,$T0,&$addr(1)); # h0*r1
+ &vpaddq ($D1,$D1,$T1); # d1 += h0*r1
+ &vpmuludq ($T0,$T0,&$addr(2)); # h0*r2
+ &vpaddq ($D2,$D2,$T0); # d2 += h0*r2
+
+ &vpmuludq ($T1,$T2,&$addr(2)); # h1*r2
+ &vpaddq ($D3,$D3,$T1); # d3 += h1*r2
+ &vpmuludq ($T0,$T2,&$addr(3)); # h1*r3
+ &vpaddq ($D4,$D4,$T0); # d4 += h1*r3
+ &vpmuludq ($T1,$T2,&$addr(8)); # h1*s4
+ &vpaddq ($D0,$D0,$T1); # d0 += h1*s4
+ &vmovdqa ($T1,&QWP(32*3,"esp")); # h3
+ &vpmuludq ($T0,$T2,&$addr(0)); # h1*r0
+ &vpaddq ($D1,$D1,$T0); # d1 += h1*r0
+ &vpmuludq ($T2,$T2,&$addr(1)); # h1*r1
+ &vpaddq ($D2,$D2,$T2); # d2 += h1*r1
+
+ &vpmuludq ($T0,$T1,&$addr(0)); # h3*r0
+ &vpaddq ($D3,$D3,$T0); # d3 += h3*r0
+ &vpmuludq ($T2,$T1,&$addr(1)); # h3*r1
+ &vpaddq ($D4,$D4,$T2); # d4 += h3*r1
+ &vpmuludq ($T0,$T1,&$addr(6)); # h3*s2
+ &vpaddq ($D0,$D0,$T0); # d0 += h3*s2
+ &vmovdqa ($T0,&QWP(32*4,"esp")); # h4
+ &vpmuludq ($T2,$T1,&$addr(7)); # h3*s3
+ &vpaddq ($D1,$D1,$T2); # d1+= h3*s3
+ &vpmuludq ($T1,$T1,&$addr(8)); # h3*s4
+ &vpaddq ($D2,$D2,$T1); # d2 += h3*s4
+
+ &vpmuludq ($T2,$T0,&$addr(8)); # h4*s4
+ &vpaddq ($D3,$D3,$T2); # d3 += h4*s4
+ &vpmuludq ($T1,$T0,&$addr(5)); # h4*s1
+ &vpaddq ($D0,$D0,$T1); # d0 += h4*s1
+ &vpmuludq ($T2,$T0,&$addr(0)); # h4*r0
+ &vpaddq ($D4,$D4,$T2); # d4 += h4*r0
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &vpmuludq ($T1,$T0,&$addr(6)); # h4*s2
+ &vpaddq ($D1,$D1,$T1); # d1 += h4*s2
+ &vpmuludq ($T0,$T0,&$addr(7)); # h4*s3
+ &vpaddq ($D2,$D2,$T0); # d2 += h4*s3
+}
+ &vpmuladd (sub { my $i=shift; &QWP(32*$i-128,"edx"); });
+
+sub vlazy_reduction {
+ ################################################################
+ # lazy reduction
+
+ &vpsrlq ($T0,$D3,26);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrlq ($T1,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpaddq ($D4,$D4,$T0); # h3 -> h4
+ &vpaddq ($D1,$D1,$T1); # h0 -> h1
+ &vpsrlq ($T0,$D4,26);
+ &vpand ($D4,$D4,$MASK);
+ &vpsrlq ($T1,$D1,26);
+ &vpand ($D1,$D1,$MASK);
+ &vpaddq ($D2,$D2,$T1); # h1 -> h2
+ &vpaddq ($D0,$D0,$T0);
+ &vpsllq ($T0,$T0,2);
+ &vpsrlq ($T1,$D2,26);
+ &vpand ($D2,$D2,$MASK);
+ &vpaddq ($D0,$D0,$T0); # h4 -> h0
+ &vpaddq ($D3,$D3,$T1); # h2 -> h3
+ &vpsrlq ($T1,$D3,26);
+ &vpsrlq ($T0,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpaddq ($D1,$D1,$T0); # h0 -> h1
+ &vpaddq ($D4,$D4,$T1); # h3 -> h4
+}
+ &vlazy_reduction();
+
+ &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1);
+ &lea ("esi",&DWP(16*4,"esi"));
+ &sub ("ecx",64);
+ &jnz (&label("loop"));
+
+&set_label("tail");
+ &vsplat_input ();
+ &and ("ebx",-64); # restore pointer
+
+ &vpmuladd (sub { my $i=shift; &QWP(4+32*$i-128,"edx"); });
+
+ ################################################################
+ # horizontal addition
+
+ &vpsrldq ($T0,$D4,8);
+ &vpsrldq ($T1,$D3,8);
+ &vpaddq ($D4,$D4,$T0);
+ &vpsrldq ($T0,$D0,8);
+ &vpaddq ($D3,$D3,$T1);
+ &vpsrldq ($T1,$D1,8);
+ &vpaddq ($D0,$D0,$T0);
+ &vpsrldq ($T0,$D2,8);
+ &vpaddq ($D1,$D1,$T1);
+ &vpermq ($T1,$D4,2); # keep folding
+ &vpaddq ($D2,$D2,$T0);
+ &vpermq ($T0,$D3,2);
+ &vpaddq ($D4,$D4,$T1);
+ &vpermq ($T1,$D0,2);
+ &vpaddq ($D3,$D3,$T0);
+ &vpermq ($T0,$D1,2);
+ &vpaddq ($D0,$D0,$T1);
+ &vpermq ($T1,$D2,2);
+ &vpaddq ($D1,$D1,$T0);
+ &vpaddq ($D2,$D2,$T1);
+
+ &vlazy_reduction();
+
+ &cmp ("ecx",0);
+ &je (&label("done"));
+
+ ################################################################
+ # clear all but single word
+
+ &vpshufd (&X($D0),&X($D0),0b11111100);
+ &lea ("edx",&DWP(32*5+128,"esp")); # restore pointer
+ &vpshufd (&X($D1),&X($D1),0b11111100);
+ &vpshufd (&X($D2),&X($D2),0b11111100);
+ &vpshufd (&X($D3),&X($D3),0b11111100);
+ &vpshufd (&X($D4),&X($D4),0b11111100);
+ &jmp (&label("even"));
+
+&set_label("done",16);
+ &vmovd (&DWP(-16*3+4*0,"edi"),&X($D0));# store hash value
+ &vmovd (&DWP(-16*3+4*1,"edi"),&X($D1));
+ &vmovd (&DWP(-16*3+4*2,"edi"),&X($D2));
+ &vmovd (&DWP(-16*3+4*3,"edi"),&X($D3));
+ &vmovd (&DWP(-16*3+4*4,"edi"),&X($D4));
+ &vzeroupper ();
+ &mov ("esp","ebp");
+&set_label("nodata");
+&function_end("_poly1305_blocks_avx2");
+}
+&set_label("const_sse2",64);
+ &data_word(1<<24,0, 1<<24,0, 1<<24,0, 1<<24,0);
+ &data_word(0,0, 0,0, 0,0, 0,0);
+ &data_word(0x03ffffff,0,0x03ffffff,0, 0x03ffffff,0, 0x03ffffff,0);
+ &data_word(0x0fffffff,0x0ffffffc,0x0ffffffc,0x0ffffffc);
+}
+&asciz ("Poly1305 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+&align (4);
+
+&asm_finish();
diff --git a/src/crypto/poly1305/asm/poly1305-x86_64.pl b/src/crypto/poly1305/asm/poly1305-x86_64.pl
new file mode 100755
index 00000000..3c810c5a
--- /dev/null
+++ b/src/crypto/poly1305/asm/poly1305-x86_64.pl
@@ -0,0 +1,2235 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for x86_64.
+#
+# March 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone,
+# measured with rdtsc at fixed clock frequency.
+#
+# IALU/gcc-4.8(*) AVX(**) AVX2
+# P4 4.90/+120% -
+# Core 2 2.39/+90% -
+# Westmere 1.86/+120% -
+# Sandy Bridge 1.39/+140% 1.10
+# Haswell 1.10/+175% 1.11 0.65
+# Skylake 1.12/+120% 0.96 0.51
+# Silvermont 2.83/+95% -
+# VIA Nano 1.82/+150% -
+# Sledgehammer 1.38/+160% -
+# Bulldozer 2.21/+130% 0.97
+#
+# (*) improvement coefficients relative to clang are more modest and
+# are ~50% on most processors, in both cases we are comparing to
+# __int128 code;
+# (**) SSE2 implementation was attempted, but among non-AVX processors
+# it was faster than integer-only code only on older Intel P4 and
+# Core processors, 50-30%, less newer processor is, but slower on
+# contemporary ones, for example almost 2x slower on Atom, and as
+# former are naturally disappearing, SSE2 is deemed unnecessary;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$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";
+
+$avx = 2;
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx");
+my ($mac,$nonce)=($inp,$len); # *_emit arguments
+my ($d1,$d2,$d3, $r0,$r1,$s1)=map("%r$_",(8..13));
+my ($h0,$h1,$h2)=("%r14","%rbx","%rbp");
+
+sub poly1305_iteration {
+# input: copy of $r1 in %rax, $h0-$h2, $r0-$r1
+# output: $h0-$h2 *= $r0-$r1
+$code.=<<___;
+ mulq $h0 # h0*r1
+ mov %rax,$d2
+ mov $r0,%rax
+ mov %rdx,$d3
+
+ mulq $h0 # h0*r0
+ mov %rax,$h0 # future $h0
+ mov $r0,%rax
+ mov %rdx,$d1
+
+ mulq $h1 # h1*r0
+ add %rax,$d2
+ mov $s1,%rax
+ adc %rdx,$d3
+
+ mulq $h1 # h1*s1
+ mov $h2,$h1 # borrow $h1
+ add %rax,$h0
+ adc %rdx,$d1
+
+ imulq $s1,$h1 # h2*s1
+ add $h1,$d2
+ mov $d1,$h1
+ adc \$0,$d3
+
+ imulq $r0,$h2 # h2*r0
+ add $d2,$h1
+ mov \$-4,%rax # mask value
+ adc $h2,$d3
+
+ and $d3,%rax # last reduction step
+ mov $d3,$h2
+ shr \$2,$d3
+ and \$3,$h2
+ add $d3,%rax
+ add %rax,$h0
+ adc \$0,$h1
+___
+}
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int64 h[3]; # current hash value base 2^64
+# unsigned __int64 r[2]; # key value base 2^64
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.globl poly1305_init
+.globl poly1305_blocks
+.globl poly1305_emit
+.type poly1305_init,\@function,3
+.align 32
+poly1305_init:
+ xor %rax,%rax
+ mov %rax,0($ctx) # initialize hash value
+ mov %rax,8($ctx)
+ mov %rax,16($ctx)
+
+ cmp \$0,$inp
+ je .Lno_key
+
+ lea poly1305_blocks(%rip),%r10
+ lea poly1305_emit(%rip),%r11
+___
+$code.=<<___ if ($avx);
+ mov OPENSSL_ia32cap_P+4(%rip),%r9
+ lea poly1305_blocks_avx(%rip),%rax
+ lea poly1305_emit_avx(%rip),%rcx
+ bt \$`60-32`,%r9 # AVX?
+ cmovc %rax,%r10
+ cmovc %rcx,%r11
+___
+$code.=<<___ if ($avx>1);
+ lea poly1305_blocks_avx2(%rip),%rax
+ bt \$`5+32`,%r9 # AVX2?
+ cmovc %rax,%r10
+___
+$code.=<<___;
+ mov \$0x0ffffffc0fffffff,%rax
+ mov \$0x0ffffffc0ffffffc,%rcx
+ and 0($inp),%rax
+ and 8($inp),%rcx
+ mov %rax,24($ctx)
+ mov %rcx,32($ctx)
+___
+$code.=<<___ if ($flavour !~ /elf32/);
+ mov %r10,0(%rdx)
+ mov %r11,8(%rdx)
+___
+$code.=<<___ if ($flavour =~ /elf32/);
+ mov %r10d,0(%rdx)
+ mov %r11d,4(%rdx)
+___
+$code.=<<___;
+ mov \$1,%eax
+.Lno_key:
+ ret
+.size poly1305_init,.-poly1305_init
+
+.type poly1305_blocks,\@function,4
+.align 32
+poly1305_blocks:
+.Lblocks:
+ sub \$16,$len # too short?
+ jc .Lno_data
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2
+
+ mov $s1,$r1
+ shr \$2,$s1
+ mov $r1,%rax
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+ jmp .Loop
+
+.align 32
+.Loop:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+___
+ &poly1305_iteration();
+$code.=<<___;
+ mov $r1,%rax
+ sub \$16,%r15 # len-=16
+ jnc .Loop
+
+ mov $h0,0($ctx) # store hash value
+ mov $h1,8($ctx)
+ mov $h2,16($ctx)
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data:
+.Lblocks_epilogue:
+ ret
+.size poly1305_blocks,.-poly1305_blocks
+
+.type poly1305_emit,\@function,3
+.align 32
+poly1305_emit:
+.Lemit:
+ mov 0($ctx),%r8 # load hash value
+ mov 8($ctx),%r9
+ mov 16($ctx),%r10
+
+ mov %r8,%rax
+ add \$5,%r8 # compare to modulus
+ mov %r9,%rcx
+ adc \$0,%r9
+ adc \$0,%r10
+ shr \$2,%r10 # did 130-bit value overfow?
+ cmovnz %r8,%rax
+ cmovnz %r9,%rcx
+
+ add 0($nonce),%rax # accumulate nonce
+ adc 8($nonce),%rcx
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+ ret
+.size poly1305_emit,.-poly1305_emit
+___
+if ($avx) {
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^26
+# unsigned __int32 is_base2_26;
+# unsigned __int64 r[2]; # key value base 2^64
+# unsigned __int64 pad;
+# struct { unsigned __int32 r^2, r^1, r^4, r^3; } r[9];
+#
+# where r^n are base 2^26 digits of degrees of multiplier key. There are
+# 5 digits, but last four are interleaved with multiples of 5, totalling
+# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4.
+
+my ($H0,$H1,$H2,$H3,$H4, $T0,$T1,$T2,$T3,$T4, $D0,$D1,$D2,$D3,$D4, $MASK) =
+ map("%xmm$_",(0..15));
+
+$code.=<<___;
+.type __poly1305_block,\@abi-omnipotent
+.align 32
+__poly1305_block:
+___
+ &poly1305_iteration();
+$code.=<<___;
+ ret
+.size __poly1305_block,.-__poly1305_block
+
+.type __poly1305_init_avx,\@abi-omnipotent
+.align 32
+__poly1305_init_avx:
+ mov $r0,$h0
+ mov $r1,$h1
+ xor $h2,$h2
+
+ lea 48+64($ctx),$ctx # size optimization
+
+ mov $r1,%rax
+ call __poly1305_block # r^2
+
+ mov \$0x3ffffff,%eax # save interleaved r^2 and r base 2^26
+ mov \$0x3ffffff,%edx
+ mov $h0,$d1
+ and $h0#d,%eax
+ mov $r0,$d2
+ and $r0#d,%edx
+ mov %eax,`16*0+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*0+4-64`($ctx)
+ shr \$26,$d2
+
+ mov \$0x3ffffff,%eax
+ mov \$0x3ffffff,%edx
+ and $d1#d,%eax
+ and $d2#d,%edx
+ mov %eax,`16*1+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*1+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*2+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*2+4-64`($ctx)
+ shr \$26,$d2
+
+ mov $h1,%rax
+ mov $r1,%rdx
+ shl \$12,%rax
+ shl \$12,%rdx
+ or $d1,%rax
+ or $d2,%rdx
+ and \$0x3ffffff,%eax
+ and \$0x3ffffff,%edx
+ mov %eax,`16*3+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*3+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*4+0-64`($ctx)
+ mov $h1,$d1
+ mov %edx,`16*4+4-64`($ctx)
+ mov $r1,$d2
+
+ mov \$0x3ffffff,%eax
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ shr \$14,$d2
+ and $d1#d,%eax
+ and $d2#d,%edx
+ mov %eax,`16*5+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*5+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*6+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*6+4-64`($ctx)
+ shr \$26,$d2
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+0-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d2#d,`16*7+4-64`($ctx)
+ lea ($d2,$d2,4),$d2 # *5
+ mov $d1#d,`16*8+0-64`($ctx)
+ mov $d2#d,`16*8+4-64`($ctx)
+
+ mov $r1,%rax
+ call __poly1305_block # r^3
+
+ mov \$0x3ffffff,%eax # save r^3 base 2^26
+ mov $h0,$d1
+ and $h0#d,%eax
+ shr \$26,$d1
+ mov %eax,`16*0+12-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ and $d1#d,%edx
+ mov %edx,`16*1+12-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*2+12-64`($ctx)
+
+ mov $h1,%rax
+ shl \$12,%rax
+ or $d1,%rax
+ and \$0x3ffffff,%eax
+ mov %eax,`16*3+12-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov $h1,$d1
+ mov %eax,`16*4+12-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ and $d1#d,%edx
+ mov %edx,`16*5+12-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*6+12-64`($ctx)
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+12-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d1#d,`16*8+12-64`($ctx)
+
+ mov $r1,%rax
+ call __poly1305_block # r^4
+
+ mov \$0x3ffffff,%eax # save r^4 base 2^26
+ mov $h0,$d1
+ and $h0#d,%eax
+ shr \$26,$d1
+ mov %eax,`16*0+8-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ and $d1#d,%edx
+ mov %edx,`16*1+8-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*2+8-64`($ctx)
+
+ mov $h1,%rax
+ shl \$12,%rax
+ or $d1,%rax
+ and \$0x3ffffff,%eax
+ mov %eax,`16*3+8-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov $h1,$d1
+ mov %eax,`16*4+8-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ and $d1#d,%edx
+ mov %edx,`16*5+8-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*6+8-64`($ctx)
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+8-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d1#d,`16*8+8-64`($ctx)
+
+ lea -48-64($ctx),$ctx # size [de-]optimization
+ ret
+.size __poly1305_init_avx,.-__poly1305_init_avx
+
+.type poly1305_blocks_avx,\@function,4
+.align 32
+poly1305_blocks_avx:
+ mov 20($ctx),%r8d # is_base2_26
+ cmp \$128,$len
+ jae .Lblocks_avx
+ test %r8d,%r8d
+ jz .Lblocks
+
+.Lblocks_avx:
+ and \$-16,$len
+ jz .Lno_data_avx
+
+ vzeroupper
+
+ test %r8d,%r8d
+ jz .Lbase2_64_avx
+
+ test \$31,$len
+ jz .Leven_avx
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_avx_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 0($ctx),$d1 # load hash value
+ mov 8($ctx),$d2
+ mov 16($ctx),$h2#d
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ ################################# base 2^26 -> base 2^64
+ mov $d1#d,$h0#d
+ and \$-1<<31,$d1
+ mov $d2,$r1 # borrow $r1
+ mov $d2#d,$h1#d
+ and \$-1<<31,$d2
+
+ shr \$6,$d1
+ shl \$52,$r1
+ add $d1,$h0
+ shr \$12,$h1
+ shr \$18,$d2
+ add $r1,$h0
+ adc $d2,$h1
+
+ mov $h2,$d1
+ shl \$40,$d1
+ shr \$24,$h2
+ add $d1,$h1
+ adc \$0,$h2 # can be partially reduced...
+
+ mov \$-4,$d2 # ... so reduce
+ mov $h2,$d1
+ and $h2,$d2
+ shr \$2,$d1
+ and \$3,$h2
+ add $d2,$d1 # =*5
+ add $d1,$h0
+ adc \$0,$h1
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+
+ call __poly1305_block
+
+ test $padbit,$padbit # if $padbit is zero,
+ jz .Lstore_base2_64_avx # store hash in base 2^64 format
+
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$r0
+ mov $h1,$r1
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$r0
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $r0,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$r1
+ and \$0x3ffffff,$h1 # h[3]
+ or $r1,$h2 # h[4]
+
+ sub \$16,%r15
+ jz .Lstore_base2_26_avx
+
+ vmovd %rax#d,$H0
+ vmovd %rdx#d,$H1
+ vmovd $h0#d,$H2
+ vmovd $h1#d,$H3
+ vmovd $h2#d,$H4
+ jmp .Lproceed_avx
+
+.align 32
+.Lstore_base2_64_avx:
+ mov $h0,0($ctx)
+ mov $h1,8($ctx)
+ mov $h2,16($ctx) # note that is_base2_26 is zeroed
+ jmp .Ldone_avx
+
+.align 16
+.Lstore_base2_26_avx:
+ mov %rax#d,0($ctx) # store hash value base 2^26
+ mov %rdx#d,4($ctx)
+ mov $h0#d,8($ctx)
+ mov $h1#d,12($ctx)
+ mov $h2#d,16($ctx)
+.align 16
+.Ldone_avx:
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data_avx:
+.Lblocks_avx_epilogue:
+ ret
+
+.align 32
+.Lbase2_64_avx:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lbase2_64_avx_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2#d
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ test \$31,$len
+ jz .Linit_avx
+
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+
+.Linit_avx:
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$d1
+ mov $h1,$d2
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$d1
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $d1,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$d2
+ and \$0x3ffffff,$h1 # h[3]
+ or $d2,$h2 # h[4]
+
+ vmovd %rax#d,$H0
+ vmovd %rdx#d,$H1
+ vmovd $h0#d,$H2
+ vmovd $h1#d,$H3
+ vmovd $h2#d,$H4
+ movl \$1,20($ctx) # set is_base2_26
+
+ call __poly1305_init_avx
+
+.Lproceed_avx:
+ mov %r15,$len
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rax
+ lea 48(%rsp),%rsp
+.Lbase2_64_avx_epilogue:
+ jmp .Ldo_avx
+
+.align 32
+.Leven_avx:
+ vmovd 4*0($ctx),$H0 # load hash value
+ vmovd 4*1($ctx),$H1
+ vmovd 4*2($ctx),$H2
+ vmovd 4*3($ctx),$H3
+ vmovd 4*4($ctx),$H4
+
+.Ldo_avx:
+___
+$code.=<<___ if (!$win64);
+ lea -0x58(%rsp),%r11
+ sub \$0x178,%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xf8(%rsp),%r11
+ sub \$0x218,%rsp
+ vmovdqa %xmm6,0x50(%r11)
+ vmovdqa %xmm7,0x60(%r11)
+ vmovdqa %xmm8,0x70(%r11)
+ vmovdqa %xmm9,0x80(%r11)
+ vmovdqa %xmm10,0x90(%r11)
+ vmovdqa %xmm11,0xa0(%r11)
+ vmovdqa %xmm12,0xb0(%r11)
+ vmovdqa %xmm13,0xc0(%r11)
+ vmovdqa %xmm14,0xd0(%r11)
+ vmovdqa %xmm15,0xe0(%r11)
+.Ldo_avx_body:
+___
+$code.=<<___;
+ sub \$64,$len
+ lea -32($inp),%rax
+ cmovc %rax,$inp
+
+ vmovdqu `16*3`($ctx),$D4 # preload r0^2
+ lea `16*3+64`($ctx),$ctx # size optimization
+ lea .Lconst(%rip),%rcx
+
+ ################################################################
+ # load input
+ vmovdqu 16*2($inp),$T0
+ vmovdqu 16*3($inp),$T1
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpsrldq \$6,$T1,$T3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+
+ vpsrlq \$40,$T4,$T4 # 4
+ vpsrlq \$26,$T0,$T1
+ vpand $MASK,$T0,$T0 # 0
+ vpsrlq \$4,$T3,$T2
+ vpand $MASK,$T1,$T1 # 1
+ vpsrlq \$30,$T3,$T3
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ jbe .Lskip_loop_avx
+
+ # expand and copy pre-calculated table to stack
+ vmovdqu `16*1-64`($ctx),$D1
+ vmovdqu `16*2-64`($ctx),$D2
+ vpshufd \$0xEE,$D4,$D3 # 34xx -> 3434
+ vpshufd \$0x44,$D4,$D0 # xx12 -> 1212
+ vmovdqa $D3,-0x90(%r11)
+ vmovdqa $D0,0x00(%rsp)
+ vpshufd \$0xEE,$D1,$D4
+ vmovdqu `16*3-64`($ctx),$D0
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D4,-0x80(%r11)
+ vmovdqa $D1,0x10(%rsp)
+ vpshufd \$0xEE,$D2,$D3
+ vmovdqu `16*4-64`($ctx),$D1
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D3,-0x70(%r11)
+ vmovdqa $D2,0x20(%rsp)
+ vpshufd \$0xEE,$D0,$D4
+ vmovdqu `16*5-64`($ctx),$D2
+ vpshufd \$0x44,$D0,$D0
+ vmovdqa $D4,-0x60(%r11)
+ vmovdqa $D0,0x30(%rsp)
+ vpshufd \$0xEE,$D1,$D3
+ vmovdqu `16*6-64`($ctx),$D0
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D3,-0x50(%r11)
+ vmovdqa $D1,0x40(%rsp)
+ vpshufd \$0xEE,$D2,$D4
+ vmovdqu `16*7-64`($ctx),$D1
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D4,-0x40(%r11)
+ vmovdqa $D2,0x50(%rsp)
+ vpshufd \$0xEE,$D0,$D3
+ vmovdqu `16*8-64`($ctx),$D2
+ vpshufd \$0x44,$D0,$D0
+ vmovdqa $D3,-0x30(%r11)
+ vmovdqa $D0,0x60(%rsp)
+ vpshufd \$0xEE,$D1,$D4
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D4,-0x20(%r11)
+ vmovdqa $D1,0x70(%rsp)
+ vpshufd \$0xEE,$D2,$D3
+ vmovdqa 0x00(%rsp),$D4 # preload r0^2
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D3,-0x10(%r11)
+ vmovdqa $D2,0x80(%rsp)
+
+ jmp .Loop_avx
+
+.align 32
+.Loop_avx:
+ ################################################################
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ # \___________________/
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ # \___________________/ \____________________/
+ #
+ # Note that we start with inp[2:3]*r^2. This is because it
+ # doesn't depend on reduction in previous iteration.
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ #
+ # though note that $Tx and $Hx are "reversed" in this section,
+ # and $D4 is preloaded with r0^2...
+
+ vpmuludq $T0,$D4,$D0 # d0 = h0*r0
+ vpmuludq $T1,$D4,$D1 # d1 = h1*r0
+ vmovdqa $H2,0x20(%r11) # offload hash
+ vpmuludq $T2,$D4,$D2 # d3 = h2*r0
+ vmovdqa 0x10(%rsp),$H2 # r1^2
+ vpmuludq $T3,$D4,$D3 # d3 = h3*r0
+ vpmuludq $T4,$D4,$D4 # d4 = h4*r0
+
+ vmovdqa $H0,0x00(%r11) #
+ vpmuludq 0x20(%rsp),$T4,$H0 # h4*s1
+ vmovdqa $H1,0x10(%r11) #
+ vpmuludq $T3,$H2,$H1 # h3*r1
+ vpaddq $H0,$D0,$D0 # d0 += h4*s1
+ vpaddq $H1,$D4,$D4 # d4 += h3*r1
+ vmovdqa $H3,0x30(%r11) #
+ vpmuludq $T2,$H2,$H0 # h2*r1
+ vpmuludq $T1,$H2,$H1 # h1*r1
+ vpaddq $H0,$D3,$D3 # d3 += h2*r1
+ vmovdqa 0x30(%rsp),$H3 # r2^2
+ vpaddq $H1,$D2,$D2 # d2 += h1*r1
+ vmovdqa $H4,0x40(%r11) #
+ vpmuludq $T0,$H2,$H2 # h0*r1
+ vpmuludq $T2,$H3,$H0 # h2*r2
+ vpaddq $H2,$D1,$D1 # d1 += h0*r1
+
+ vmovdqa 0x40(%rsp),$H4 # s2^2
+ vpaddq $H0,$D4,$D4 # d4 += h2*r2
+ vpmuludq $T1,$H3,$H1 # h1*r2
+ vpmuludq $T0,$H3,$H3 # h0*r2
+ vpaddq $H1,$D3,$D3 # d3 += h1*r2
+ vmovdqa 0x50(%rsp),$H2 # r3^2
+ vpaddq $H3,$D2,$D2 # d2 += h0*r2
+ vpmuludq $T4,$H4,$H0 # h4*s2
+ vpmuludq $T3,$H4,$H4 # h3*s2
+ vpaddq $H0,$D1,$D1 # d1 += h4*s2
+ vmovdqa 0x60(%rsp),$H3 # s3^2
+ vpaddq $H4,$D0,$D0 # d0 += h3*s2
+
+ vmovdqa 0x80(%rsp),$H4 # s4^2
+ vpmuludq $T1,$H2,$H1 # h1*r3
+ vpmuludq $T0,$H2,$H2 # h0*r3
+ vpaddq $H1,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $T4,$H3,$H0 # h4*s3
+ vpmuludq $T3,$H3,$H1 # h3*s3
+ vpaddq $H0,$D2,$D2 # d2 += h4*s3
+ vmovdqu 16*0($inp),$H0 # load input
+ vpaddq $H1,$D1,$D1 # d1 += h3*s3
+ vpmuludq $T2,$H3,$H3 # h2*s3
+ vpmuludq $T2,$H4,$T2 # h2*s4
+ vpaddq $H3,$D0,$D0 # d0 += h2*s3
+
+ vmovdqu 16*1($inp),$H1 #
+ vpaddq $T2,$D1,$D1 # d1 += h2*s4
+ vpmuludq $T3,$H4,$T3 # h3*s4
+ vpmuludq $T4,$H4,$T4 # h4*s4
+ vpsrldq \$6,$H0,$H2 # splat input
+ vpaddq $T3,$D2,$D2 # d2 += h3*s4
+ vpaddq $T4,$D3,$D3 # d3 += h4*s4
+ vpsrldq \$6,$H1,$H3 #
+ vpmuludq 0x70(%rsp),$T0,$T4 # h0*r4
+ vpmuludq $T1,$H4,$T0 # h1*s4
+ vpunpckhqdq $H1,$H0,$H4 # 4
+ vpaddq $T4,$D4,$D4 # d4 += h0*r4
+ vmovdqa -0x90(%r11),$T4 # r0^4
+ vpaddq $T0,$D0,$D0 # d0 += h1*s4
+
+ vpunpcklqdq $H1,$H0,$H0 # 0:1
+ vpunpcklqdq $H3,$H2,$H3 # 2:3
+
+ #vpsrlq \$40,$H4,$H4 # 4
+ vpsrldq \$`40/8`,$H4,$H4 # 4
+ vpsrlq \$26,$H0,$H1
+ vpand $MASK,$H0,$H0 # 0
+ vpsrlq \$4,$H3,$H2
+ vpand $MASK,$H1,$H1 # 1
+ vpand 0(%rcx),$H4,$H4 # .Lmask24
+ vpsrlq \$30,$H3,$H3
+ vpand $MASK,$H2,$H2 # 2
+ vpand $MASK,$H3,$H3 # 3
+ vpor 32(%rcx),$H4,$H4 # padbit, yes, always
+
+ vpaddq 0x00(%r11),$H0,$H0 # add hash value
+ vpaddq 0x10(%r11),$H1,$H1
+ vpaddq 0x20(%r11),$H2,$H2
+ vpaddq 0x30(%r11),$H3,$H3
+ vpaddq 0x40(%r11),$H4,$H4
+
+ lea 16*2($inp),%rax
+ lea 16*4($inp),$inp
+ sub \$64,$len
+ cmovc %rax,$inp
+
+ ################################################################
+ # Now we accumulate (inp[0:1]+hash)*r^4
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ vpmuludq $H0,$T4,$T0 # h0*r0
+ vpmuludq $H1,$T4,$T1 # h1*r0
+ vpaddq $T0,$D0,$D0
+ vpaddq $T1,$D1,$D1
+ vmovdqa -0x80(%r11),$T2 # r1^4
+ vpmuludq $H2,$T4,$T0 # h2*r0
+ vpmuludq $H3,$T4,$T1 # h3*r0
+ vpaddq $T0,$D2,$D2
+ vpaddq $T1,$D3,$D3
+ vpmuludq $H4,$T4,$T4 # h4*r0
+ vpmuludq -0x70(%r11),$H4,$T0 # h4*s1
+ vpaddq $T4,$D4,$D4
+
+ vpaddq $T0,$D0,$D0 # d0 += h4*s1
+ vpmuludq $H2,$T2,$T1 # h2*r1
+ vpmuludq $H3,$T2,$T0 # h3*r1
+ vpaddq $T1,$D3,$D3 # d3 += h2*r1
+ vmovdqa -0x60(%r11),$T3 # r2^4
+ vpaddq $T0,$D4,$D4 # d4 += h3*r1
+ vpmuludq $H1,$T2,$T1 # h1*r1
+ vpmuludq $H0,$T2,$T2 # h0*r1
+ vpaddq $T1,$D2,$D2 # d2 += h1*r1
+ vpaddq $T2,$D1,$D1 # d1 += h0*r1
+
+ vmovdqa -0x50(%r11),$T4 # s2^4
+ vpmuludq $H2,$T3,$T0 # h2*r2
+ vpmuludq $H1,$T3,$T1 # h1*r2
+ vpaddq $T0,$D4,$D4 # d4 += h2*r2
+ vpaddq $T1,$D3,$D3 # d3 += h1*r2
+ vmovdqa -0x40(%r11),$T2 # r3^4
+ vpmuludq $H0,$T3,$T3 # h0*r2
+ vpmuludq $H4,$T4,$T0 # h4*s2
+ vpaddq $T3,$D2,$D2 # d2 += h0*r2
+ vpaddq $T0,$D1,$D1 # d1 += h4*s2
+ vmovdqa -0x30(%r11),$T3 # s3^4
+ vpmuludq $H3,$T4,$T4 # h3*s2
+ vpmuludq $H1,$T2,$T1 # h1*r3
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+
+ vmovdqa -0x10(%r11),$T4 # s4^4
+ vpaddq $T1,$D4,$D4 # d4 += h1*r3
+ vpmuludq $H0,$T2,$T2 # h0*r3
+ vpmuludq $H4,$T3,$T0 # h4*s3
+ vpaddq $T2,$D3,$D3 # d3 += h0*r3
+ vpaddq $T0,$D2,$D2 # d2 += h4*s3
+ vmovdqu 16*2($inp),$T0 # load input
+ vpmuludq $H3,$T3,$T2 # h3*s3
+ vpmuludq $H2,$T3,$T3 # h2*s3
+ vpaddq $T2,$D1,$D1 # d1 += h3*s3
+ vmovdqu 16*3($inp),$T1 #
+ vpaddq $T3,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $H2,$T4,$H2 # h2*s4
+ vpmuludq $H3,$T4,$H3 # h3*s4
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpaddq $H2,$D1,$D1 # d1 += h2*s4
+ vpmuludq $H4,$T4,$H4 # h4*s4
+ vpsrldq \$6,$T1,$T3 #
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*s4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*s4
+ vpmuludq -0x20(%r11),$H0,$H4 # h0*r4
+ vpmuludq $H1,$T4,$H0
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+
+ #vpsrlq \$40,$T4,$T4 # 4
+ vpsrldq \$`40/8`,$T4,$T4 # 4
+ vpsrlq \$26,$T0,$T1
+ vmovdqa 0x00(%rsp),$D4 # preload r0^2
+ vpand $MASK,$T0,$T0 # 0
+ vpsrlq \$4,$T3,$T2
+ vpand $MASK,$T1,$T1 # 1
+ vpand 0(%rcx),$T4,$T4 # .Lmask24
+ vpsrlq \$30,$T3,$T3
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D0
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D0,$H0,$H0
+ vpsllq \$2,$D0,$D0
+ vpaddq $D0,$H0,$H0 # h4 -> h0
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ ja .Loop_avx
+
+.Lskip_loop_avx:
+ ################################################################
+ # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ vpshufd \$0x10,$D4,$D4 # r0^n, xx12 -> x1x2
+ add \$32,$len
+ jnz .Long_tail_avx
+
+ vpaddq $H2,$T2,$T2
+ vpaddq $H0,$T0,$T0
+ vpaddq $H1,$T1,$T1
+ vpaddq $H3,$T3,$T3
+ vpaddq $H4,$T4,$T4
+
+.Long_tail_avx:
+ vmovdqa $H2,0x20(%r11)
+ vmovdqa $H0,0x00(%r11)
+ vmovdqa $H1,0x10(%r11)
+ vmovdqa $H3,0x30(%r11)
+ vmovdqa $H4,0x40(%r11)
+
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ vpmuludq $T2,$D4,$D2 # d2 = h2*r0
+ vpmuludq $T0,$D4,$D0 # d0 = h0*r0
+ vpshufd \$0x10,`16*1-64`($ctx),$H2 # r1^n
+ vpmuludq $T1,$D4,$D1 # d1 = h1*r0
+ vpmuludq $T3,$D4,$D3 # d3 = h3*r0
+ vpmuludq $T4,$D4,$D4 # d4 = h4*r0
+
+ vpmuludq $T3,$H2,$H0 # h3*r1
+ vpaddq $H0,$D4,$D4 # d4 += h3*r1
+ vpshufd \$0x10,`16*2-64`($ctx),$H3 # s1^n
+ vpmuludq $T2,$H2,$H1 # h2*r1
+ vpaddq $H1,$D3,$D3 # d3 += h2*r1
+ vpshufd \$0x10,`16*3-64`($ctx),$H4 # r2^n
+ vpmuludq $T1,$H2,$H0 # h1*r1
+ vpaddq $H0,$D2,$D2 # d2 += h1*r1
+ vpmuludq $T0,$H2,$H2 # h0*r1
+ vpaddq $H2,$D1,$D1 # d1 += h0*r1
+ vpmuludq $T4,$H3,$H3 # h4*s1
+ vpaddq $H3,$D0,$D0 # d0 += h4*s1
+
+ vpshufd \$0x10,`16*4-64`($ctx),$H2 # s2^n
+ vpmuludq $T2,$H4,$H1 # h2*r2
+ vpaddq $H1,$D4,$D4 # d4 += h2*r2
+ vpmuludq $T1,$H4,$H0 # h1*r2
+ vpaddq $H0,$D3,$D3 # d3 += h1*r2
+ vpshufd \$0x10,`16*5-64`($ctx),$H3 # r3^n
+ vpmuludq $T0,$H4,$H4 # h0*r2
+ vpaddq $H4,$D2,$D2 # d2 += h0*r2
+ vpmuludq $T4,$H2,$H1 # h4*s2
+ vpaddq $H1,$D1,$D1 # d1 += h4*s2
+ vpshufd \$0x10,`16*6-64`($ctx),$H4 # s3^n
+ vpmuludq $T3,$H2,$H2 # h3*s2
+ vpaddq $H2,$D0,$D0 # d0 += h3*s2
+
+ vpmuludq $T1,$H3,$H0 # h1*r3
+ vpaddq $H0,$D4,$D4 # d4 += h1*r3
+ vpmuludq $T0,$H3,$H3 # h0*r3
+ vpaddq $H3,$D3,$D3 # d3 += h0*r3
+ vpshufd \$0x10,`16*7-64`($ctx),$H2 # r4^n
+ vpmuludq $T4,$H4,$H1 # h4*s3
+ vpaddq $H1,$D2,$D2 # d2 += h4*s3
+ vpshufd \$0x10,`16*8-64`($ctx),$H3 # s4^n
+ vpmuludq $T3,$H4,$H0 # h3*s3
+ vpaddq $H0,$D1,$D1 # d1 += h3*s3
+ vpmuludq $T2,$H4,$H4 # h2*s3
+ vpaddq $H4,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $T0,$H2,$H2 # h0*r4
+ vpaddq $H2,$D4,$D4 # h4 = d4 + h0*r4
+ vpmuludq $T4,$H3,$H1 # h4*s4
+ vpaddq $H1,$D3,$D3 # h3 = d3 + h4*s4
+ vpmuludq $T3,$H3,$H0 # h3*s4
+ vpaddq $H0,$D2,$D2 # h2 = d2 + h3*s4
+ vpmuludq $T2,$H3,$H1 # h2*s4
+ vpaddq $H1,$D1,$D1 # h1 = d1 + h2*s4
+ vpmuludq $T1,$H3,$H3 # h1*s4
+ vpaddq $H3,$D0,$D0 # h0 = d0 + h1*s4
+
+ jz .Lshort_tail_avx
+
+ vmovdqu 16*0($inp),$H0 # load input
+ vmovdqu 16*1($inp),$H1
+
+ vpsrldq \$6,$H0,$H2 # splat input
+ vpsrldq \$6,$H1,$H3
+ vpunpckhqdq $H1,$H0,$H4 # 4
+ vpunpcklqdq $H1,$H0,$H0 # 0:1
+ vpunpcklqdq $H3,$H2,$H3 # 2:3
+
+ vpsrlq \$40,$H4,$H4 # 4
+ vpsrlq \$26,$H0,$H1
+ vpand $MASK,$H0,$H0 # 0
+ vpsrlq \$4,$H3,$H2
+ vpand $MASK,$H1,$H1 # 1
+ vpsrlq \$30,$H3,$H3
+ vpand $MASK,$H2,$H2 # 2
+ vpand $MASK,$H3,$H3 # 3
+ vpor 32(%rcx),$H4,$H4 # padbit, yes, always
+
+ vpshufd \$0x32,`16*0-64`($ctx),$T4 # r0^n, 34xx -> x3x4
+ vpaddq 0x00(%r11),$H0,$H0
+ vpaddq 0x10(%r11),$H1,$H1
+ vpaddq 0x20(%r11),$H2,$H2
+ vpaddq 0x30(%r11),$H3,$H3
+ vpaddq 0x40(%r11),$H4,$H4
+
+ ################################################################
+ # multiply (inp[0:1]+hash) by r^4:r^3 and accumulate
+
+ vpmuludq $H0,$T4,$T0 # h0*r0
+ vpaddq $T0,$D0,$D0 # d0 += h0*r0
+ vpmuludq $H1,$T4,$T1 # h1*r0
+ vpaddq $T1,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H2,$T4,$T0 # h2*r0
+ vpaddq $T0,$D2,$D2 # d2 += h2*r0
+ vpshufd \$0x32,`16*1-64`($ctx),$T2 # r1^n
+ vpmuludq $H3,$T4,$T1 # h3*r0
+ vpaddq $T1,$D3,$D3 # d3 += h3*r0
+ vpmuludq $H4,$T4,$T4 # h4*r0
+ vpaddq $T4,$D4,$D4 # d4 += h4*r0
+
+ vpmuludq $H3,$T2,$T0 # h3*r1
+ vpaddq $T0,$D4,$D4 # d4 += h3*r1
+ vpshufd \$0x32,`16*2-64`($ctx),$T3 # s1
+ vpmuludq $H2,$T2,$T1 # h2*r1
+ vpaddq $T1,$D3,$D3 # d3 += h2*r1
+ vpshufd \$0x32,`16*3-64`($ctx),$T4 # r2
+ vpmuludq $H1,$T2,$T0 # h1*r1
+ vpaddq $T0,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H0,$T2,$T2 # h0*r1
+ vpaddq $T2,$D1,$D1 # d1 += h0*r1
+ vpmuludq $H4,$T3,$T3 # h4*s1
+ vpaddq $T3,$D0,$D0 # d0 += h4*s1
+
+ vpshufd \$0x32,`16*4-64`($ctx),$T2 # s2
+ vpmuludq $H2,$T4,$T1 # h2*r2
+ vpaddq $T1,$D4,$D4 # d4 += h2*r2
+ vpmuludq $H1,$T4,$T0 # h1*r2
+ vpaddq $T0,$D3,$D3 # d3 += h1*r2
+ vpshufd \$0x32,`16*5-64`($ctx),$T3 # r3
+ vpmuludq $H0,$T4,$T4 # h0*r2
+ vpaddq $T4,$D2,$D2 # d2 += h0*r2
+ vpmuludq $H4,$T2,$T1 # h4*s2
+ vpaddq $T1,$D1,$D1 # d1 += h4*s2
+ vpshufd \$0x32,`16*6-64`($ctx),$T4 # s3
+ vpmuludq $H3,$T2,$T2 # h3*s2
+ vpaddq $T2,$D0,$D0 # d0 += h3*s2
+
+ vpmuludq $H1,$T3,$T0 # h1*r3
+ vpaddq $T0,$D4,$D4 # d4 += h1*r3
+ vpmuludq $H0,$T3,$T3 # h0*r3
+ vpaddq $T3,$D3,$D3 # d3 += h0*r3
+ vpshufd \$0x32,`16*7-64`($ctx),$T2 # r4
+ vpmuludq $H4,$T4,$T1 # h4*s3
+ vpaddq $T1,$D2,$D2 # d2 += h4*s3
+ vpshufd \$0x32,`16*8-64`($ctx),$T3 # s4
+ vpmuludq $H3,$T4,$T0 # h3*s3
+ vpaddq $T0,$D1,$D1 # d1 += h3*s3
+ vpmuludq $H2,$T4,$T4 # h2*s3
+ vpaddq $T4,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $H0,$T2,$T2 # h0*r4
+ vpaddq $T2,$D4,$D4 # d4 += h0*r4
+ vpmuludq $H4,$T3,$T1 # h4*s4
+ vpaddq $T1,$D3,$D3 # d3 += h4*s4
+ vpmuludq $H3,$T3,$T0 # h3*s4
+ vpaddq $T0,$D2,$D2 # d2 += h3*s4
+ vpmuludq $H2,$T3,$T1 # h2*s4
+ vpaddq $T1,$D1,$D1 # d1 += h2*s4
+ vpmuludq $H1,$T3,$T3 # h1*s4
+ vpaddq $T3,$D0,$D0 # d0 += h1*s4
+
+.Lshort_tail_avx:
+ ################################################################
+ # horizontal addition
+
+ vpsrldq \$8,$D4,$T4
+ vpsrldq \$8,$D3,$T3
+ vpsrldq \$8,$D1,$T1
+ vpsrldq \$8,$D0,$T0
+ vpsrldq \$8,$D2,$T2
+ vpaddq $T3,$D3,$D3
+ vpaddq $T4,$D4,$D4
+ vpaddq $T0,$D0,$D0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$D2,$D2
+
+ ################################################################
+ # lazy reduction
+
+ vpsrlq \$26,$D3,$H3
+ vpand $MASK,$D3,$D3
+ vpaddq $H3,$D4,$D4 # h3 -> h4
+
+ vpsrlq \$26,$D0,$H0
+ vpand $MASK,$D0,$D0
+ vpaddq $H0,$D1,$D1 # h0 -> h1
+
+ vpsrlq \$26,$D4,$H4
+ vpand $MASK,$D4,$D4
+
+ vpsrlq \$26,$D1,$H1
+ vpand $MASK,$D1,$D1
+ vpaddq $H1,$D2,$D2 # h1 -> h2
+
+ vpaddq $H4,$D0,$D0
+ vpsllq \$2,$H4,$H4
+ vpaddq $H4,$D0,$D0 # h4 -> h0
+
+ vpsrlq \$26,$D2,$H2
+ vpand $MASK,$D2,$D2
+ vpaddq $H2,$D3,$D3 # h2 -> h3
+
+ vpsrlq \$26,$D0,$H0
+ vpand $MASK,$D0,$D0
+ vpaddq $H0,$D1,$D1 # h0 -> h1
+
+ vpsrlq \$26,$D3,$H3
+ vpand $MASK,$D3,$D3
+ vpaddq $H3,$D4,$D4 # h3 -> h4
+
+ vmovd $D0,`4*0-48-64`($ctx) # save partially reduced
+ vmovd $D1,`4*1-48-64`($ctx)
+ vmovd $D2,`4*2-48-64`($ctx)
+ vmovd $D3,`4*3-48-64`($ctx)
+ vmovd $D4,`4*4-48-64`($ctx)
+___
+$code.=<<___ if ($win64);
+ vmovdqa 0x50(%r11),%xmm6
+ vmovdqa 0x60(%r11),%xmm7
+ vmovdqa 0x70(%r11),%xmm8
+ vmovdqa 0x80(%r11),%xmm9
+ vmovdqa 0x90(%r11),%xmm10
+ vmovdqa 0xa0(%r11),%xmm11
+ vmovdqa 0xb0(%r11),%xmm12
+ vmovdqa 0xc0(%r11),%xmm13
+ vmovdqa 0xd0(%r11),%xmm14
+ vmovdqa 0xe0(%r11),%xmm15
+ lea 0xf8(%r11),%rsp
+.Ldo_avx_epilogue:
+___
+$code.=<<___ if (!$win64);
+ lea 0x58(%r11),%rsp
+___
+$code.=<<___;
+ vzeroupper
+ ret
+.size poly1305_blocks_avx,.-poly1305_blocks_avx
+
+.type poly1305_emit_avx,\@function,3
+.align 32
+poly1305_emit_avx:
+ cmpl \$0,20($ctx) # is_base2_26?
+ je .Lemit
+
+ mov 0($ctx),%eax # load hash value base 2^26
+ mov 4($ctx),%ecx
+ mov 8($ctx),%r8d
+ mov 12($ctx),%r11d
+ mov 16($ctx),%r10d
+
+ shl \$26,%rcx # base 2^26 -> base 2^64
+ mov %r8,%r9
+ shl \$52,%r8
+ add %rcx,%rax
+ shr \$12,%r9
+ add %rax,%r8 # h0
+ adc \$0,%r9
+
+ shl \$14,%r11
+ mov %r10,%rax
+ shr \$24,%r10
+ add %r11,%r9
+ shl \$40,%rax
+ add %rax,%r9 # h1
+ adc \$0,%r10 # h2
+
+ mov %r10,%rax # could be partially reduced, so reduce
+ mov %r10,%rcx
+ and \$3,%r10
+ shr \$2,%rax
+ and \$-4,%rcx
+ add %rcx,%rax
+ add %rax,%r8
+ adc \$0,%r9
+
+ mov %r8,%rax
+ add \$5,%r8 # compare to modulus
+ mov %r9,%rcx
+ adc \$0,%r9
+ adc \$0,%r10
+ shr \$2,%r10 # did 130-bit value overfow?
+ cmovnz %r8,%rax
+ cmovnz %r9,%rcx
+
+ add 0($nonce),%rax # accumulate nonce
+ adc 8($nonce),%rcx
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+ ret
+.size poly1305_emit_avx,.-poly1305_emit_avx
+___
+
+if ($avx>1) {
+my ($H0,$H1,$H2,$H3,$H4, $MASK, $T4,$T0,$T1,$T2,$T3, $D0,$D1,$D2,$D3,$D4) =
+ map("%ymm$_",(0..15));
+my $S4=$MASK;
+
+$code.=<<___;
+.type poly1305_blocks_avx2,\@function,4
+.align 32
+poly1305_blocks_avx2:
+ mov 20($ctx),%r8d # is_base2_26
+ cmp \$128,$len
+ jae .Lblocks_avx2
+ test %r8d,%r8d
+ jz .Lblocks
+
+.Lblocks_avx2:
+ and \$-16,$len
+ jz .Lno_data_avx2
+
+ vzeroupper
+
+ test %r8d,%r8d
+ jz .Lbase2_64_avx2
+
+ test \$63,$len
+ jz .Leven_avx2
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_avx2_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 0($ctx),$d1 # load hash value
+ mov 8($ctx),$d2
+ mov 16($ctx),$h2#d
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ ################################# base 2^26 -> base 2^64
+ mov $d1#d,$h0#d
+ and \$-1<<31,$d1
+ mov $d2,$r1 # borrow $r1
+ mov $d2#d,$h1#d
+ and \$-1<<31,$d2
+
+ shr \$6,$d1
+ shl \$52,$r1
+ add $d1,$h0
+ shr \$12,$h1
+ shr \$18,$d2
+ add $r1,$h0
+ adc $d2,$h1
+
+ mov $h2,$d1
+ shl \$40,$d1
+ shr \$24,$h2
+ add $d1,$h1
+ adc \$0,$h2 # can be partially reduced...
+
+ mov \$-4,$d2 # ... so reduce
+ mov $h2,$d1
+ and $h2,$d2
+ shr \$2,$d1
+ and \$3,$h2
+ add $d2,$d1 # =*5
+ add $d1,$h0
+ adc \$0,$h1
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+.Lbase2_26_pre_avx2:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+ mov $r1,%rax
+
+ test \$63,%r15
+ jnz .Lbase2_26_pre_avx2
+
+ test $padbit,$padbit # if $padbit is zero,
+ jz .Lstore_base2_64_avx2 # store hash in base 2^64 format
+
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$r0
+ mov $h1,$r1
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$r0
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $r0,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$r1
+ and \$0x3ffffff,$h1 # h[3]
+ or $r1,$h2 # h[4]
+
+ test %r15,%r15
+ jz .Lstore_base2_26_avx2
+
+ vmovd %rax#d,%x#$H0
+ vmovd %rdx#d,%x#$H1
+ vmovd $h0#d,%x#$H2
+ vmovd $h1#d,%x#$H3
+ vmovd $h2#d,%x#$H4
+ jmp .Lproceed_avx2
+
+.align 32
+.Lstore_base2_64_avx2:
+ mov $h0,0($ctx)
+ mov $h1,8($ctx)
+ mov $h2,16($ctx) # note that is_base2_26 is zeroed
+ jmp .Ldone_avx2
+
+.align 16
+.Lstore_base2_26_avx2:
+ mov %rax#d,0($ctx) # store hash value base 2^26
+ mov %rdx#d,4($ctx)
+ mov $h0#d,8($ctx)
+ mov $h1#d,12($ctx)
+ mov $h2#d,16($ctx)
+.align 16
+.Ldone_avx2:
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data_avx2:
+.Lblocks_avx2_epilogue:
+ ret
+
+.align 32
+.Lbase2_64_avx2:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lbase2_64_avx2_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2#d
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ test \$63,$len
+ jz .Linit_avx2
+
+.Lbase2_64_pre_avx2:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+ mov $r1,%rax
+
+ test \$63,%r15
+ jnz .Lbase2_64_pre_avx2
+
+.Linit_avx2:
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$d1
+ mov $h1,$d2
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$d1
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $d1,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$d2
+ and \$0x3ffffff,$h1 # h[3]
+ or $d2,$h2 # h[4]
+
+ vmovd %rax#d,%x#$H0
+ vmovd %rdx#d,%x#$H1
+ vmovd $h0#d,%x#$H2
+ vmovd $h1#d,%x#$H3
+ vmovd $h2#d,%x#$H4
+ movl \$1,20($ctx) # set is_base2_26
+
+ call __poly1305_init_avx
+
+.Lproceed_avx2:
+ mov %r15,$len
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rax
+ lea 48(%rsp),%rsp
+.Lbase2_64_avx2_epilogue:
+ jmp .Ldo_avx2
+
+.align 32
+.Leven_avx2:
+ vmovd 4*0($ctx),%x#$H0 # load hash value base 2^26
+ vmovd 4*1($ctx),%x#$H1
+ vmovd 4*2($ctx),%x#$H2
+ vmovd 4*3($ctx),%x#$H3
+ vmovd 4*4($ctx),%x#$H4
+
+.Ldo_avx2:
+___
+$code.=<<___ if (!$win64);
+ lea -8(%rsp),%r11
+ sub \$0x128,%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xf8(%rsp),%r11
+ sub \$0x1c8,%rsp
+ vmovdqa %xmm6,0x50(%r11)
+ vmovdqa %xmm7,0x60(%r11)
+ vmovdqa %xmm8,0x70(%r11)
+ vmovdqa %xmm9,0x80(%r11)
+ vmovdqa %xmm10,0x90(%r11)
+ vmovdqa %xmm11,0xa0(%r11)
+ vmovdqa %xmm12,0xb0(%r11)
+ vmovdqa %xmm13,0xc0(%r11)
+ vmovdqa %xmm14,0xd0(%r11)
+ vmovdqa %xmm15,0xe0(%r11)
+.Ldo_avx2_body:
+___
+$code.=<<___;
+ lea 48+64($ctx),$ctx # size optimization
+ lea .Lconst(%rip),%rcx
+
+ # expand and copy pre-calculated table to stack
+ vmovdqu `16*0-64`($ctx),%x#$T2
+ and \$-512,%rsp
+ vmovdqu `16*1-64`($ctx),%x#$T3
+ vmovdqu `16*2-64`($ctx),%x#$T4
+ vmovdqu `16*3-64`($ctx),%x#$D0
+ vmovdqu `16*4-64`($ctx),%x#$D1
+ vmovdqu `16*5-64`($ctx),%x#$D2
+ vmovdqu `16*6-64`($ctx),%x#$D3
+ vpermq \$0x15,$T2,$T2 # 00003412 -> 12343434
+ vmovdqu `16*7-64`($ctx),%x#$D4
+ vpermq \$0x15,$T3,$T3
+ vpshufd \$0xc8,$T2,$T2 # 12343434 -> 14243444
+ vmovdqu `16*8-64`($ctx),%x#$MASK
+ vpermq \$0x15,$T4,$T4
+ vpshufd \$0xc8,$T3,$T3
+ vmovdqa $T2,0x00(%rsp)
+ vpermq \$0x15,$D0,$D0
+ vpshufd \$0xc8,$T4,$T4
+ vmovdqa $T3,0x20(%rsp)
+ vpermq \$0x15,$D1,$D1
+ vpshufd \$0xc8,$D0,$D0
+ vmovdqa $T4,0x40(%rsp)
+ vpermq \$0x15,$D2,$D2
+ vpshufd \$0xc8,$D1,$D1
+ vmovdqa $D0,0x60(%rsp)
+ vpermq \$0x15,$D3,$D3
+ vpshufd \$0xc8,$D2,$D2
+ vmovdqa $D1,0x80(%rsp)
+ vpermq \$0x15,$D4,$D4
+ vpshufd \$0xc8,$D3,$D3
+ vmovdqa $D2,0xa0(%rsp)
+ vpermq \$0x15,$MASK,$MASK
+ vpshufd \$0xc8,$D4,$D4
+ vmovdqa $D3,0xc0(%rsp)
+ vpshufd \$0xc8,$MASK,$MASK
+ vmovdqa $D4,0xe0(%rsp)
+ vmovdqa $MASK,0x100(%rsp)
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+
+ ################################################################
+ # load input
+ vmovdqu 16*0($inp),%x#$T0
+ vmovdqu 16*1($inp),%x#$T1
+ vinserti128 \$1,16*2($inp),$T0,$T0
+ vinserti128 \$1,16*3($inp),$T1,$T1
+ lea 16*4($inp),$inp
+
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpsrldq \$6,$T1,$T3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpunpcklqdq $T3,$T2,$T2 # 2:3
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+
+ vpsrlq \$30,$T2,$T3
+ vpsrlq \$4,$T2,$T2
+ vpsrlq \$26,$T0,$T1
+ vpsrlq \$40,$T4,$T4 # 4
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T0,$T0 # 0
+ vpand $MASK,$T1,$T1 # 1
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ lea 0x90(%rsp),%rax # size optimization
+ vpaddq $H2,$T2,$H2 # accumulate input
+ sub \$64,$len
+ jz .Ltail_avx2
+ jmp .Loop_avx2
+
+.align 32
+.Loop_avx2:
+ ################################################################
+ # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4
+ # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3
+ # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2
+ # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1
+ # \________/\________/
+ ################################################################
+ #vpaddq $H2,$T2,$H2 # accumulate input
+ vpaddq $H0,$T0,$H0
+ vmovdqa `32*0`(%rsp),$T0 # r0^4
+ vpaddq $H1,$T1,$H1
+ vmovdqa `32*1`(%rsp),$T1 # r1^4
+ vpaddq $H3,$T3,$H3
+ vmovdqa `32*3`(%rsp),$T2 # r2^4
+ vpaddq $H4,$T4,$H4
+ vmovdqa `32*6-0x90`(%rax),$T3 # s3^4
+ vmovdqa `32*8-0x90`(%rax),$S4 # s4^4
+
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ #
+ # however, as h2 is "chronologically" first one available pull
+ # corresponding operations up, so it's
+ #
+ # d4 = h2*r2 + h4*r0 + h3*r1 + h1*r3 + h0*r4
+ # d3 = h2*r1 + h3*r0 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h2*5*r4 + h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3
+ # d0 = h2*5*r3 + h0*r0 + h4*5*r1 + h3*5*r2 + h1*5*r4
+
+ vpmuludq $H2,$T0,$D2 # d2 = h2*r0
+ vpmuludq $H2,$T1,$D3 # d3 = h2*r1
+ vpmuludq $H2,$T2,$D4 # d4 = h2*r2
+ vpmuludq $H2,$T3,$D0 # d0 = h2*s3
+ vpmuludq $H2,$S4,$D1 # d1 = h2*s4
+
+ vpmuludq $H0,$T1,$T4 # h0*r1
+ vpmuludq $H1,$T1,$H2 # h1*r1, borrow $H2 as temp
+ vpaddq $T4,$D1,$D1 # d1 += h0*r1
+ vpaddq $H2,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H3,$T1,$T4 # h3*r1
+ vpmuludq `32*2`(%rsp),$H4,$H2 # h4*s1
+ vpaddq $T4,$D4,$D4 # d4 += h3*r1
+ vpaddq $H2,$D0,$D0 # d0 += h4*s1
+ vmovdqa `32*4-0x90`(%rax),$T1 # s2
+
+ vpmuludq $H0,$T0,$T4 # h0*r0
+ vpmuludq $H1,$T0,$H2 # h1*r0
+ vpaddq $T4,$D0,$D0 # d0 += h0*r0
+ vpaddq $H2,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H3,$T0,$T4 # h3*r0
+ vpmuludq $H4,$T0,$H2 # h4*r0
+ vmovdqu 16*0($inp),%x#$T0 # load input
+ vpaddq $T4,$D3,$D3 # d3 += h3*r0
+ vpaddq $H2,$D4,$D4 # d4 += h4*r0
+ vinserti128 \$1,16*2($inp),$T0,$T0
+
+ vpmuludq $H3,$T1,$T4 # h3*s2
+ vpmuludq $H4,$T1,$H2 # h4*s2
+ vmovdqu 16*1($inp),%x#$T1
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+ vpaddq $H2,$D1,$D1 # d1 += h4*s2
+ vmovdqa `32*5-0x90`(%rax),$H2 # r3
+ vpmuludq $H1,$T2,$T4 # h1*r2
+ vpmuludq $H0,$T2,$T2 # h0*r2
+ vpaddq $T4,$D3,$D3 # d3 += h1*r2
+ vpaddq $T2,$D2,$D2 # d2 += h0*r2
+ vinserti128 \$1,16*3($inp),$T1,$T1
+ lea 16*4($inp),$inp
+
+ vpmuludq $H1,$H2,$T4 # h1*r3
+ vpmuludq $H0,$H2,$H2 # h0*r3
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpaddq $T4,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $H3,$T3,$T4 # h3*s3
+ vpmuludq $H4,$T3,$H2 # h4*s3
+ vpsrldq \$6,$T1,$T3
+ vpaddq $T4,$D1,$D1 # d1 += h3*s3
+ vpaddq $H2,$D2,$D2 # d2 += h4*s3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+
+ vpmuludq $H3,$S4,$H3 # h3*s4
+ vpmuludq $H4,$S4,$H4 # h4*s4
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+ vpmuludq `32*7-0x90`(%rax),$H0,$H4 # h0*r4
+ vpmuludq $H1,$S4,$H0 # h1*s4
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ ################################################################
+ # lazy reduction (interleaved with tail of input splat)
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D4
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$4,$T3,$T2
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D4,$H0,$H0
+ vpsllq \$2,$D4,$D4
+ vpaddq $D4,$H0,$H0 # h4 -> h0
+
+ vpand $MASK,$T2,$T2 # 2
+ vpsrlq \$26,$T0,$T1
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpaddq $T2,$H2,$H2 # modulo-scheduled
+ vpsrlq \$30,$T3,$T3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$40,$T4,$T4 # 4
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpand $MASK,$T0,$T0 # 0
+ vpand $MASK,$T1,$T1 # 1
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ sub \$64,$len
+ jnz .Loop_avx2
+
+ .byte 0x66,0x90
+.Ltail_avx2:
+ ################################################################
+ # while above multiplications were by r^4 in all lanes, in last
+ # iteration we multiply least significant lane by r^4 and most
+ # significant one by r, so copy of above except that references
+ # to the precomputed table are displaced by 4...
+
+ #vpaddq $H2,$T2,$H2 # accumulate input
+ vpaddq $H0,$T0,$H0
+ vmovdqu `32*0+4`(%rsp),$T0 # r0^4
+ vpaddq $H1,$T1,$H1
+ vmovdqu `32*1+4`(%rsp),$T1 # r1^4
+ vpaddq $H3,$T3,$H3
+ vmovdqu `32*3+4`(%rsp),$T2 # r2^4
+ vpaddq $H4,$T4,$H4
+ vmovdqu `32*6+4-0x90`(%rax),$T3 # s3^4
+ vmovdqu `32*8+4-0x90`(%rax),$S4 # s4^4
+
+ vpmuludq $H2,$T0,$D2 # d2 = h2*r0
+ vpmuludq $H2,$T1,$D3 # d3 = h2*r1
+ vpmuludq $H2,$T2,$D4 # d4 = h2*r2
+ vpmuludq $H2,$T3,$D0 # d0 = h2*s3
+ vpmuludq $H2,$S4,$D1 # d1 = h2*s4
+
+ vpmuludq $H0,$T1,$T4 # h0*r1
+ vpmuludq $H1,$T1,$H2 # h1*r1
+ vpaddq $T4,$D1,$D1 # d1 += h0*r1
+ vpaddq $H2,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H3,$T1,$T4 # h3*r1
+ vpmuludq `32*2+4`(%rsp),$H4,$H2 # h4*s1
+ vpaddq $T4,$D4,$D4 # d4 += h3*r1
+ vpaddq $H2,$D0,$D0 # d0 += h4*s1
+
+ vpmuludq $H0,$T0,$T4 # h0*r0
+ vpmuludq $H1,$T0,$H2 # h1*r0
+ vpaddq $T4,$D0,$D0 # d0 += h0*r0
+ vmovdqu `32*4+4-0x90`(%rax),$T1 # s2
+ vpaddq $H2,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H3,$T0,$T4 # h3*r0
+ vpmuludq $H4,$T0,$H2 # h4*r0
+ vpaddq $T4,$D3,$D3 # d3 += h3*r0
+ vpaddq $H2,$D4,$D4 # d4 += h4*r0
+
+ vpmuludq $H3,$T1,$T4 # h3*s2
+ vpmuludq $H4,$T1,$H2 # h4*s2
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+ vpaddq $H2,$D1,$D1 # d1 += h4*s2
+ vmovdqu `32*5+4-0x90`(%rax),$H2 # r3
+ vpmuludq $H1,$T2,$T4 # h1*r2
+ vpmuludq $H0,$T2,$T2 # h0*r2
+ vpaddq $T4,$D3,$D3 # d3 += h1*r2
+ vpaddq $T2,$D2,$D2 # d2 += h0*r2
+
+ vpmuludq $H1,$H2,$T4 # h1*r3
+ vpmuludq $H0,$H2,$H2 # h0*r3
+ vpaddq $T4,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $H3,$T3,$T4 # h3*s3
+ vpmuludq $H4,$T3,$H2 # h4*s3
+ vpaddq $T4,$D1,$D1 # d1 += h3*s3
+ vpaddq $H2,$D2,$D2 # d2 += h4*s3
+
+ vpmuludq $H3,$S4,$H3 # h3*s4
+ vpmuludq $H4,$S4,$H4 # h4*s4
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4
+ vpmuludq `32*7+4-0x90`(%rax),$H0,$H4 # h0*r4
+ vpmuludq $H1,$S4,$H0 # h1*s4
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ ################################################################
+ # horizontal addition
+
+ vpsrldq \$8,$D1,$T1
+ vpsrldq \$8,$H2,$T2
+ vpsrldq \$8,$H3,$T3
+ vpsrldq \$8,$H4,$T4
+ vpsrldq \$8,$H0,$T0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$H2,$H2
+ vpaddq $T3,$H3,$H3
+ vpaddq $T4,$H4,$H4
+ vpaddq $T0,$H0,$H0
+
+ vpermq \$0x2,$H3,$T3
+ vpermq \$0x2,$H4,$T4
+ vpermq \$0x2,$H0,$T0
+ vpermq \$0x2,$D1,$T1
+ vpermq \$0x2,$H2,$T2
+ vpaddq $T3,$H3,$H3
+ vpaddq $T4,$H4,$H4
+ vpaddq $T0,$H0,$H0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$H2,$H2
+
+ ################################################################
+ # lazy reduction
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D4
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D4,$H0,$H0
+ vpsllq \$2,$D4,$D4
+ vpaddq $D4,$H0,$H0 # h4 -> h0
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced
+ vmovd %x#$H1,`4*1-48-64`($ctx)
+ vmovd %x#$H2,`4*2-48-64`($ctx)
+ vmovd %x#$H3,`4*3-48-64`($ctx)
+ vmovd %x#$H4,`4*4-48-64`($ctx)
+___
+$code.=<<___ if ($win64);
+ vmovdqa 0x50(%r11),%xmm6
+ vmovdqa 0x60(%r11),%xmm7
+ vmovdqa 0x70(%r11),%xmm8
+ vmovdqa 0x80(%r11),%xmm9
+ vmovdqa 0x90(%r11),%xmm10
+ vmovdqa 0xa0(%r11),%xmm11
+ vmovdqa 0xb0(%r11),%xmm12
+ vmovdqa 0xc0(%r11),%xmm13
+ vmovdqa 0xd0(%r11),%xmm14
+ vmovdqa 0xe0(%r11),%xmm15
+ lea 0xf8(%r11),%rsp
+.Ldo_avx2_epilogue:
+___
+$code.=<<___ if (!$win64);
+ lea 8(%r11),%rsp
+___
+$code.=<<___;
+ vzeroupper
+ ret
+.size poly1305_blocks_avx2,.-poly1305_blocks_avx2
+___
+}
+$code.=<<___;
+.align 64
+.Lconst:
+.Lmask24:
+.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0
+.L129:
+.long 1<<24,0,1<<24,0,1<<24,0,1<<24,0
+.Lmask26:
+.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0
+.Lfive:
+.long 5,0,5,0,5,0,5,0
+___
+}
+
+$code.=<<___;
+.asciz "Poly1305 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 16
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lcommon_seh_tail
+
+ lea 48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R14
+
+ jmp .Lcommon_seh_tail
+.size se_handler,.-se_handler
+
+.type avx_handler,\@abi-omnipotent
+.align 16
+avx_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 208($context),%rax # pull context->R11
+
+ lea 0x50(%rax),%rsi
+ lea 0xf8(%rax),%rax
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size avx_handler,.-avx_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_poly1305_init
+ .rva .LSEH_end_poly1305_init
+ .rva .LSEH_info_poly1305_init
+
+ .rva .LSEH_begin_poly1305_blocks
+ .rva .LSEH_end_poly1305_blocks
+ .rva .LSEH_info_poly1305_blocks
+
+ .rva .LSEH_begin_poly1305_emit
+ .rva .LSEH_end_poly1305_emit
+ .rva .LSEH_info_poly1305_emit
+___
+$code.=<<___ if ($avx);
+ .rva .LSEH_begin_poly1305_blocks_avx
+ .rva .Lbase2_64_avx
+ .rva .LSEH_info_poly1305_blocks_avx_1
+
+ .rva .Lbase2_64_avx
+ .rva .Leven_avx
+ .rva .LSEH_info_poly1305_blocks_avx_2
+
+ .rva .Leven_avx
+ .rva .LSEH_end_poly1305_blocks_avx
+ .rva .LSEH_info_poly1305_blocks_avx_3
+
+ .rva .LSEH_begin_poly1305_emit_avx
+ .rva .LSEH_end_poly1305_emit_avx
+ .rva .LSEH_info_poly1305_emit_avx
+___
+$code.=<<___ if ($avx>1);
+ .rva .LSEH_begin_poly1305_blocks_avx2
+ .rva .Lbase2_64_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_1
+
+ .rva .Lbase2_64_avx2
+ .rva .Leven_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_2
+
+ .rva .Leven_avx2
+ .rva .LSEH_end_poly1305_blocks_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_3
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_poly1305_init:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_init,.LSEH_begin_poly1305_init
+
+.LSEH_info_poly1305_blocks:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_body,.Lblocks_epilogue
+
+.LSEH_info_poly1305_emit:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_emit,.LSEH_begin_poly1305_emit
+___
+$code.=<<___ if ($avx);
+.LSEH_info_poly1305_blocks_avx_1:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_avx_body,.Lblocks_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx_2:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lbase2_64_avx_body,.Lbase2_64_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx_3:
+ .byte 9,0,0,0
+ .rva avx_handler
+ .rva .Ldo_avx_body,.Ldo_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_emit_avx:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_emit_avx,.LSEH_begin_poly1305_emit_avx
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_poly1305_blocks_avx2_1:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_avx2_body,.Lblocks_avx2_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx2_2:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lbase2_64_avx2_body,.Lbase2_64_avx2_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx2_3:
+ .byte 9,0,0,0
+ .rva avx_handler
+ .rva .Ldo_avx2_body,.Ldo_avx2_epilogue # HandlerData[]
+___
+}
+
+foreach (split('\n',$code)) {
+ s/\`([^\`]*)\`/eval($1)/ge;
+ s/%r([a-z]+)#d/%e$1/g;
+ s/%r([0-9]+)#d/%r$1d/g;
+ s/%x#%y/%x/g;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/poly1305/internal.h b/src/crypto/poly1305/internal.h
new file mode 100644
index 00000000..df6769ea
--- /dev/null
+++ b/src/crypto/poly1305/internal.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_POLY1305_INTERNAL_H
+#define OPENSSL_HEADER_POLY1305_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/poly1305.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
+
+void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
+ size_t in_len);
+
+void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_POLY1305_INTERNAL_H */
diff --git a/src/crypto/poly1305/poly1305.c b/src/crypto/poly1305/poly1305.c
index 5a49e2df..dc2d6a68 100644
--- a/src/crypto/poly1305/poly1305.c
+++ b/src/crypto/poly1305/poly1305.c
@@ -22,6 +22,8 @@
#include <openssl/cpu.h>
+#include "internal.h"
+
#if defined(OPENSSL_WINDOWS) || !defined(OPENSSL_X86_64)
@@ -48,15 +50,6 @@ static void U32TO8_LE(uint8_t *m, uint32_t v) {
}
#endif
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
-
-void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
- size_t in_len);
-
-void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
-#endif
-
static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
struct poly1305_state_st {
@@ -170,7 +163,7 @@ void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
uint32_t t0, t1, t2, t3;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_init_neon(statep, key);
return;
}
@@ -217,7 +210,7 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_update_neon(statep, in, in_len);
return;
}
@@ -263,7 +256,7 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
uint32_t b, nb;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_finish_neon(statep, mac);
return;
}
diff --git a/src/crypto/poly1305/poly1305_arm.c b/src/crypto/poly1305/poly1305_arm.c
index 5e78dc06..de31d6b2 100644
--- a/src/crypto/poly1305/poly1305_arm.c
+++ b/src/crypto/poly1305/poly1305_arm.c
@@ -21,6 +21,9 @@
#include <string.h>
+#include "../internal.h"
+#include "internal.h"
+
typedef struct {
uint32_t v[12]; /* for alignment; only using 10 */
@@ -170,7 +173,7 @@ static void fe1305x2_frombytearray(fe1305x2 *r, const uint8_t *x,
}
}
-static const fe1305x2 zero __attribute__((aligned(16)));
+static const alignas(16) fe1305x2 zero;
struct poly1305_state_st {
uint8_t data[sizeof(fe1305x2[5]) + 128];
diff --git a/src/crypto/poly1305/poly1305_test.cc b/src/crypto/poly1305/poly1305_test.cc
index 3a726683..2c25e93b 100644
--- a/src/crypto/poly1305/poly1305_test.cc
+++ b/src/crypto/poly1305/poly1305_test.cc
@@ -20,16 +20,57 @@
#include <openssl/crypto.h>
#include <openssl/poly1305.h>
+#include "../internal.h"
#include "../test/file_test.h"
-// |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
-#if defined(OPENSSL_WINDOWS)
-// MSVC doesn't support C++11 |alignas|.
-#define ALIGNED __declspec(align(16))
-#else
-#define ALIGNED alignas(16)
-#endif
+static bool TestSIMD(FileTest *t, unsigned excess,
+ const std::vector<uint8_t> &key,
+ const std::vector<uint8_t> &in,
+ const std::vector<uint8_t> &mac) {
+ poly1305_state state;
+ CRYPTO_poly1305_init(&state, key.data());
+
+ size_t done = 0;
+
+ // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade
+ // on-demand. Stress the upgrade path.
+ size_t todo = 16;
+ if (todo > in.size()) {
+ todo = in.size();
+ }
+ CRYPTO_poly1305_update(&state, in.data(), todo);
+ done += todo;
+
+ for (;;) {
+ // Feed 128 + |excess| bytes to test SIMD mode.
+ if (done + 128 + excess > in.size()) {
+ break;
+ }
+ CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess);
+ done += 128 + excess;
+
+ // Feed |excess| bytes to ensure SIMD mode can handle short inputs.
+ if (done + excess > in.size()) {
+ break;
+ }
+ CRYPTO_poly1305_update(&state, in.data() + done, excess);
+ done += excess;
+ }
+
+ // Consume the remainder and finish.
+ CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done);
+
+ // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
+ alignas(16) uint8_t out[16];
+ CRYPTO_poly1305_finish(&state, out);
+ if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
+ t->PrintLine("SIMD pattern %u failed.", excess);
+ return false;
+ }
+
+ return true;
+}
static bool TestPoly1305(FileTest *t, void *arg) {
std::vector<uint8_t> key, in, mac;
@@ -47,7 +88,8 @@ static bool TestPoly1305(FileTest *t, void *arg) {
poly1305_state state;
CRYPTO_poly1305_init(&state, key.data());
CRYPTO_poly1305_update(&state, in.data(), in.size());
- ALIGNED uint8_t out[16];
+ // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
+ alignas(16) uint8_t out[16];
CRYPTO_poly1305_finish(&state, out);
if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
t->PrintLine("Single-shot Poly1305 failed.");
@@ -60,11 +102,20 @@ static bool TestPoly1305(FileTest *t, void *arg) {
CRYPTO_poly1305_update(&state, &in[i], 1);
}
CRYPTO_poly1305_finish(&state, out);
- if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
+ if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
t->PrintLine("Streaming Poly1305 failed.");
return false;
}
+ // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of
+ // four blocks, so test up to three blocks of excess.
+ if (!TestSIMD(t, 0, key, in, mac) ||
+ !TestSIMD(t, 16, key, in, mac) ||
+ !TestSIMD(t, 32, key, in, mac) ||
+ !TestSIMD(t, 48, key, in, mac)) {
+ return false;
+ }
+
return true;
}
diff --git a/src/crypto/poly1305/poly1305_test.txt b/src/crypto/poly1305/poly1305_test.txt
index ad40699e..611007a0 100644
--- a/src/crypto/poly1305/poly1305_test.txt
+++ b/src/crypto/poly1305/poly1305_test.txt
@@ -50,3 +50,110 @@ MAC = 14000000000000005500000000000000
Key = 0100000000000000040000000000000000000000000000000000000000000000
Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000
MAC = 13000000000000000000000000000000
+
+
+# Additional test vectors that are long enough to ensure OpenSSL's SIMD
+# assembly is fully tested.
+
+# Length 2048.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfed
+MAC = 69d28f73dd09d39a92aa179da354b7ea
+
+# Length 2049.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8
+MAC = d6a26654b88572e875d9661c83471c1b
+
+# Length 2050.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852
+MAC = 9fbbb7f7adcd0cd5b46a4a520b22499a
+
+# Length 2051.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5
+MAC = eb7cdceb97ade2a07622f8f5a4b1ce15
+
+# Length 2052.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f590
+MAC = d41c310927cd92e14784ea78b85503db
+
+# Length 2053.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073
+MAC = 16af133c423f783a14c49d9f526384cf
+
+# Length 2054.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4
+MAC = 00c75db8f0636b22f195645b03091f5f
+
+# Length 2055.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f434
+MAC = 4a532bc740f581555831345f3b75bf33
+
+# Length 2056.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a
+MAC = 698c7d32c5923871d124a2479e521706
+
+# Length 2057.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c
+MAC = a677187dbf3c927aeeafb9ebce0f61dc
+
+# Length 2058.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a
+MAC = 201fed7eee981b31d2cc42ff6c38141a
+
+# Length 2059.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28
+MAC = 0c3d3d01a37f347c4f7c5826bcafb3e1
+
+# Length 2060.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c9
+MAC = 33a4e0e0bed7c84c5cc5dd4784410f07
+
+# Length 2061.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e
+MAC = 8e41c40a2f8ec58fe594f3a3a2de4ae1
+
+# Length 2062.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21
+MAC = c6e5d1810fd878ac6b844c66cef36a22
+
+# Length 2063.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df
+MAC = f6eaae369c3cb5c05748e8d919178e00
+
+# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439
+Key = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea
+Input = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595
+MAC = c85d15ed44c378d6b00e23064c7bcd51
+
+# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483
+
+Key = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc
+Input = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc
+MAC = 8559b876eceed66eb37798c0457baff9
+
+Key = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+Input = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264
+MAC = 00bd1258978e205444c9aaaa82006fed
+
+Key = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+Input = 02fc
+MAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c
+
+Key = 00ff000000000000000000000000000000000000001e00000000000000007b7b
+Input = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc
+MAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5
diff --git a/src/crypto/poly1305/poly1305_vec.c b/src/crypto/poly1305/poly1305_vec.c
index 07578d08..3045a2f1 100644
--- a/src/crypto/poly1305/poly1305_vec.c
+++ b/src/crypto/poly1305/poly1305_vec.c
@@ -20,42 +20,40 @@
#include <openssl/poly1305.h>
+#include "../internal.h"
+
#if !defined(OPENSSL_WINDOWS) && defined(OPENSSL_X86_64)
#include <emmintrin.h>
-#define ALIGN(x) __attribute__((aligned(x)))
-/* inline is not a keyword in C89. */
-#define INLINE
-#define U8TO64_LE(m) (*(uint64_t *)(m))
-#define U8TO32_LE(m) (*(uint32_t *)(m))
+#define U8TO64_LE(m) (*(const uint64_t *)(m))
+#define U8TO32_LE(m) (*(const uint32_t *)(m))
#define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v
typedef __m128i xmmi;
-typedef unsigned __int128 uint128_t;
-static const uint32_t ALIGN(16) poly1305_x64_sse2_message_mask[4] = {
+static const alignas(16) uint32_t poly1305_x64_sse2_message_mask[4] = {
(1 << 26) - 1, 0, (1 << 26) - 1, 0};
-static const uint32_t ALIGN(16) poly1305_x64_sse2_5[4] = {5, 0, 5, 0};
-static const uint32_t ALIGN(16) poly1305_x64_sse2_1shl128[4] = {(1 << 24), 0,
- (1 << 24), 0};
+static const alignas(16) uint32_t poly1305_x64_sse2_5[4] = {5, 0, 5, 0};
+static const alignas(16) uint32_t poly1305_x64_sse2_1shl128[4] = {
+ (1 << 24), 0, (1 << 24), 0};
-static uint128_t INLINE add128(uint128_t a, uint128_t b) { return a + b; }
+static inline uint128_t add128(uint128_t a, uint128_t b) { return a + b; }
-static uint128_t INLINE add128_64(uint128_t a, uint64_t b) { return a + b; }
+static inline uint128_t add128_64(uint128_t a, uint64_t b) { return a + b; }
-static uint128_t INLINE mul64x64_128(uint64_t a, uint64_t b) {
+static inline uint128_t mul64x64_128(uint64_t a, uint64_t b) {
return (uint128_t)a * b;
}
-static uint64_t INLINE lo128(uint128_t a) { return (uint64_t)a; }
+static inline uint64_t lo128(uint128_t a) { return (uint64_t)a; }
-static uint64_t INLINE shr128(uint128_t v, const int shift) {
+static inline uint64_t shr128(uint128_t v, const int shift) {
return (uint64_t)(v >> shift);
}
-static uint64_t INLINE shr128_pair(uint64_t hi, uint64_t lo, const int shift) {
+static inline uint64_t shr128_pair(uint64_t hi, uint64_t lo, const int shift) {
return (uint64_t)((((uint128_t)hi << 64) | lo) >> shift);
}
@@ -82,32 +80,32 @@ typedef struct poly1305_state_internal_t {
} poly1305_state_internal; /* 448 bytes total + 63 bytes for
alignment = 511 bytes raw */
-static poly1305_state_internal INLINE *poly1305_aligned_state(
+static inline poly1305_state_internal *poly1305_aligned_state(
poly1305_state *state) {
return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63);
}
/* copy 0-63 bytes */
-static void INLINE
+static inline void
poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) {
size_t offset = src - dst;
if (bytes & 32) {
_mm_storeu_si128((xmmi *)(dst + 0),
- _mm_loadu_si128((xmmi *)(dst + offset + 0)));
+ _mm_loadu_si128((const xmmi *)(dst + offset + 0)));
_mm_storeu_si128((xmmi *)(dst + 16),
- _mm_loadu_si128((xmmi *)(dst + offset + 16)));
+ _mm_loadu_si128((const xmmi *)(dst + offset + 16)));
dst += 32;
}
if (bytes & 16) {
- _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((xmmi *)(dst + offset)));
+ _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((const xmmi *)(dst + offset)));
dst += 16;
}
if (bytes & 8) {
- *(uint64_t *)dst = *(uint64_t *)(dst + offset);
+ *(uint64_t *)dst = *(const uint64_t *)(dst + offset);
dst += 8;
}
if (bytes & 4) {
- *(uint32_t *)dst = *(uint32_t *)(dst + offset);
+ *(uint32_t *)dst = *(const uint32_t *)(dst + offset);
dst += 4;
}
if (bytes & 2) {
@@ -120,7 +118,7 @@ poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) {
}
/* zero 0-15 bytes */
-static void INLINE poly1305_block_zero(uint8_t *dst, size_t bytes) {
+static inline void poly1305_block_zero(uint8_t *dst, size_t bytes) {
if (bytes & 8) {
*(uint64_t *)dst = 0;
dst += 8;
@@ -138,7 +136,7 @@ static void INLINE poly1305_block_zero(uint8_t *dst, size_t bytes) {
}
}
-static size_t INLINE poly1305_min(size_t a, size_t b) {
+static inline size_t poly1305_min(size_t a, size_t b) {
return (a < b) ? a : b;
}
@@ -186,9 +184,9 @@ void CRYPTO_poly1305_init(poly1305_state *state, const uint8_t key[32]) {
static void poly1305_first_block(poly1305_state_internal *st,
const uint8_t *m) {
- const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
- const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
- const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+ const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
+ const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
xmmi T5, T6;
poly1305_power *p;
uint128_t d[3];
@@ -265,10 +263,10 @@ static void poly1305_first_block(poly1305_state_internal *st,
p->R24.d[3] = (uint32_t)(pad1 >> 32);
/* H = [Mx,My] */
- T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
- _mm_loadl_epi64((xmmi *)(m + 16)));
- T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
- _mm_loadl_epi64((xmmi *)(m + 24)));
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+ _mm_loadl_epi64((const xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+ _mm_loadl_epi64((const xmmi *)(m + 24)));
st->H[0] = _mm_and_si128(MMASK, T5);
st->H[1] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -279,9 +277,9 @@ static void poly1305_first_block(poly1305_state_internal *st,
static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
size_t bytes) {
- const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
- const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
- const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+ const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
+ const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
poly1305_power *p;
xmmi H0, H1, H2, H3, H4;
@@ -345,10 +343,10 @@ static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
T4 = _mm_add_epi64(T4, T5);
/* H += [Mx,My]*[r^2,r^2] */
- T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
- _mm_loadl_epi64((xmmi *)(m + 16)));
- T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
- _mm_loadl_epi64((xmmi *)(m + 24)));
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+ _mm_loadl_epi64((const xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+ _mm_loadl_epi64((const xmmi *)(m + 24)));
M0 = _mm_and_si128(MMASK, T5);
M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -409,10 +407,10 @@ static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
T4 = _mm_add_epi64(T4, T5);
/* H += [Mx,My] */
- T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 32)),
- _mm_loadl_epi64((xmmi *)(m + 48)));
- T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 40)),
- _mm_loadl_epi64((xmmi *)(m + 56)));
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 32)),
+ _mm_loadl_epi64((const xmmi *)(m + 48)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 40)),
+ _mm_loadl_epi64((const xmmi *)(m + 56)));
M0 = _mm_and_si128(MMASK, T5);
M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -469,9 +467,9 @@ static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
size_t bytes) {
- const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
- const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
- const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
+ const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
+ const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
poly1305_power *p;
xmmi H0, H1, H2, H3, H4;
@@ -542,10 +540,10 @@ static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
T4 = _mm_add_epi64(T4, T5);
/* H += [Mx,My] */
- T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
- _mm_loadl_epi64((xmmi *)(m + 16)));
- T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
- _mm_loadl_epi64((xmmi *)(m + 24)));
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+ _mm_loadl_epi64((const xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+ _mm_loadl_epi64((const xmmi *)(m + 24)));
M0 = _mm_and_si128(MMASK, T5);
M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -703,9 +701,9 @@ static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
t0 &= 0x3ffffff;
t1 = t1 + c;
- st->HH[0] = ((t0) | (t1 << 26)) & 0xfffffffffffull;
- st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & 0xfffffffffffull;
- st->HH[2] = ((t3 >> 10) | (t4 << 16)) & 0x3ffffffffffull;
+ st->HH[0] = ((t0) | (t1 << 26)) & UINT64_C(0xfffffffffff);
+ st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & UINT64_C(0xfffffffffff);
+ st->HH[2] = ((t3 >> 10) | (t4 << 16)) & UINT64_C(0x3ffffffffff);
return consumed;
}
diff --git a/src/crypto/rand/CMakeLists.txt b/src/crypto/rand/CMakeLists.txt
index eedf81b8..c66d2eeb 100644
--- a/src/crypto/rand/CMakeLists.txt
+++ b/src/crypto/rand/CMakeLists.txt
@@ -13,6 +13,7 @@ add_library(
OBJECT
+ deterministic.c
rand.c
urandom.c
windows.c
diff --git a/src/crypto/rand/deterministic.c b/src/crypto/rand/deterministic.c
new file mode 100644
index 00000000..e6b7bb7e
--- /dev/null
+++ b/src/crypto/rand/deterministic.c
@@ -0,0 +1,49 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/rand.h>
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+
+#include <string.h>
+
+#include <openssl/chacha.h>
+
+#include "internal.h"
+
+
+/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured.
+ *
+ * TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is
+ * ever used in a multi-threaded program, replace this with a thread-local. (A
+ * mutex would not be deterministic.) */
+static uint64_t g_num_calls = 0;
+
+void RAND_cleanup(void) {}
+
+void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
+
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
+ static const uint8_t kZeroKey[32];
+
+ uint8_t nonce[12];
+ memset(nonce, 0, sizeof(nonce));
+ memcpy(nonce, &g_num_calls, sizeof(g_num_calls));
+
+ memset(out, 0, requested);
+ CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0);
+ g_num_calls++;
+}
+
+#endif /* BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/src/crypto/rand/rand.c b/src/crypto/rand/rand.c
index 892b4ba8..5a1bec2e 100644
--- a/src/crypto/rand/rand.c
+++ b/src/crypto/rand/rand.c
@@ -72,7 +72,8 @@ static void rand_thread_state_free(void *state) {
OPENSSL_free(state);
}
-#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
+ !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
/* These functions are defined in asm/rdrand-x86_64.pl */
extern int CRYPTO_rdrand(uint8_t out[8]);
@@ -209,6 +210,8 @@ int RAND_load_file(const char *path, long num) {
}
}
+const char *RAND_file_name(char *buf, size_t num) { return NULL; }
+
void RAND_add(const void *buf, int num, double entropy) {}
int RAND_egd(const char *path) {
diff --git a/src/crypto/rand/urandom.c b/src/crypto/rand/urandom.c
index 5bf5c739..a519983c 100644
--- a/src/crypto/rand/urandom.c
+++ b/src/crypto/rand/urandom.c
@@ -14,7 +14,7 @@
#include <openssl/rand.h>
-#if !defined(OPENSSL_WINDOWS)
+#if !defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
#include <assert.h>
#include <errno.h>
@@ -220,4 +220,4 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
}
}
-#endif /* !OPENSSL_WINDOWS */
+#endif /* !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/src/crypto/rand/windows.c b/src/crypto/rand/windows.c
index 1a0cb8b0..9d7dd782 100644
--- a/src/crypto/rand/windows.c
+++ b/src/crypto/rand/windows.c
@@ -14,7 +14,7 @@
#include <openssl/rand.h>
-#if defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
#include <limits.h>
#include <stdlib.h>
@@ -53,4 +53,4 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
return;
}
-#endif /* OPENSSL_WINDOWS */
+#endif /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/src/crypto/rc4/asm/rc4-586.pl b/src/crypto/rc4/asm/rc4-586.pl
index fc860ae2..8d3ccb72 100644
--- a/src/crypto/rc4/asm/rc4-586.pl
+++ b/src/crypto/rc4/asm/rc4-586.pl
@@ -384,31 +384,5 @@ $idx="edx";
&mov (&DWP(-4,$out),"eax"); # key->y=0;
&function_end("asm_RC4_set_key");
-# const char *RC4_options(void);
-&function_begin_B("RC4_options");
- &call (&label("pic_point"));
-&set_label("pic_point");
- &blindpop("eax");
- &lea ("eax",&DWP(&label("opts")."-".&label("pic_point"),"eax"));
- &picmeup("edx","OPENSSL_ia32cap_P");
- &mov ("edx",&DWP(0,"edx"));
- &bt ("edx",20);
- &jc (&label("1xchar"));
- &bt ("edx",26);
- &jnc (&label("ret"));
- &add ("eax",25);
- &ret ();
-&set_label("1xchar");
- &add ("eax",12);
-&set_label("ret");
- &ret ();
-&set_label("opts",64);
-&asciz ("rc4(4x,int)");
-&asciz ("rc4(1x,char)");
-&asciz ("rc4(8x,mmx)");
-&asciz ("RC4 for x86, CRYPTOGAMS by <appro\@openssl.org>");
-&align (64);
-&function_end_B("RC4_options");
-
&asm_finish();
diff --git a/src/crypto/rsa/blinding.c b/src/crypto/rsa/blinding.c
index d21633f8..d9d90c2b 100644
--- a/src/crypto/rsa/blinding.c
+++ b/src/crypto/rsa/blinding.c
@@ -113,7 +113,6 @@
#include <openssl/bn.h>
#include <openssl/mem.h>
#include <openssl/err.h>
-#include <openssl/thread.h>
#include "internal.h"
@@ -121,54 +120,35 @@
#define BN_BLINDING_COUNTER 32
struct bn_blinding_st {
- BIGNUM *A;
- BIGNUM *Ai;
- BIGNUM *e;
- BIGNUM *mod; /* just a reference */
- int counter;
- unsigned long flags;
- /* mont is the Montgomery context used for this |BN_BLINDING|. It is not
- * owned and must outlive this structure. */
- const BN_MONT_CTX *mont;
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont);
+ BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
+ BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
+ unsigned counter;
};
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) {
- BN_BLINDING *ret = NULL;
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx);
- ret = (BN_BLINDING*) OPENSSL_malloc(sizeof(BN_BLINDING));
+BN_BLINDING *BN_BLINDING_new(void) {
+ BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING));
if (ret == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(ret, 0, sizeof(BN_BLINDING));
- if (A != NULL) {
- ret->A = BN_dup(A);
- if (ret->A == NULL) {
- goto err;
- }
- }
- if (Ai != NULL) {
- ret->Ai = BN_dup(Ai);
- if (ret->Ai == NULL) {
- goto err;
- }
- }
- /* save a copy of mod in the BN_BLINDING structure */
- ret->mod = BN_dup(mod);
- if (ret->mod == NULL) {
+ ret->A = BN_new();
+ if (ret->A == NULL) {
goto err;
}
- if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) {
- BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+
+ ret->Ai = BN_new();
+ if (ret->Ai == NULL) {
+ goto err;
}
- /* Set the counter to the special value -1
- * to indicate that this is never-used fresh blinding
- * that does not need updating before first use. */
- ret->counter = -1;
+ /* The blinding values need to be created before this blinding can be used. */
+ ret->counter = BN_BLINDING_COUNTER - 1;
+
return ret;
err:
@@ -183,280 +163,105 @@ void BN_BLINDING_free(BN_BLINDING *r) {
BN_free(r->A);
BN_free(r->Ai);
- BN_free(r->e);
- BN_free(r->mod);
OPENSSL_free(r);
}
-int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) {
- int ret = 0;
-
- if (b->A == NULL || b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
- goto err;
- }
-
- if (b->counter == -1) {
- b->counter = 0;
- }
-
- if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
- !(b->flags & BN_BLINDING_NO_RECREATE)) {
+static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ if (++b->counter == BN_BLINDING_COUNTER) {
/* re-create blinding parameters */
- if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) {
+ if (!bn_blinding_create_param(b, e, mont, ctx)) {
goto err;
}
- } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
- if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) {
- goto err;
- }
- if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) {
+ b->counter = 0;
+ } else {
+ if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) ||
+ !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) {
goto err;
}
}
- ret = 1;
+ return 1;
err:
- if (b->counter == BN_BLINDING_COUNTER) {
- b->counter = 0;
- }
- return ret;
-}
+ /* |A| and |Ai| may be in an inconsistent state so they both need to be
+ * replaced the next time this blinding is used. Note that this is only
+ * sufficient because support for |BN_BLINDING_NO_UPDATE| and
+ * |BN_BLINDING_NO_RECREATE| was previously dropped. */
+ b->counter = BN_BLINDING_COUNTER - 1;
-int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
- return BN_BLINDING_convert_ex(n, NULL, b, ctx);
+ return 0;
}
-int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) {
- int ret = 1;
-
- if (b->A == NULL || b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+ * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+ */
+ if (!bn_blinding_update(b, e, mont, ctx) ||
+ !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
return 0;
}
- if (b->counter == -1) {
- /* Fresh blinding, doesn't need updating. */
- b->counter = 0;
- } else if (!BN_BLINDING_update(b, ctx)) {
- return 0;
- }
-
- if (r != NULL) {
- if (!BN_copy(r, b->Ai)) {
- ret = 0;
- }
- }
-
- if (!BN_mod_mul(n, n, b->A, b->mod, ctx)) {
- ret = 0;
- }
-
- return ret;
+ return 1;
}
-int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
- return BN_BLINDING_invert_ex(n, NULL, b, ctx);
+int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
+ BN_CTX *ctx) {
+ /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+ * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+ */
+ return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
}
-int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
- BN_CTX *ctx) {
- int ret;
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ BIGNUM mont_N_consttime;
+ BN_init(&mont_N_consttime);
+ BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME);
+ int retry_counter = 32;
- if (r != NULL) {
- ret = BN_mod_mul(n, n, r, b->mod, ctx);
- } else {
- if (b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
+ do {
+ if (!BN_rand_range(b->A, &mont->N)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
- ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
- }
-
- return ret;
-}
-
-unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) { return b->flags; }
-
-void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) {
- b->flags = flags;
-}
-
-BN_BLINDING *BN_BLINDING_create_param(
- BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
- const BN_MONT_CTX *mont) {
- int retry_counter = 32;
- BN_BLINDING *ret = NULL;
-
- if (b == NULL) {
- ret = BN_BLINDING_new(NULL, NULL, m);
- } else {
- ret = b;
- }
-
- if (ret == NULL) {
- goto err;
- }
-
- if (ret->A == NULL && (ret->A = BN_new()) == NULL) {
- goto err;
- }
- if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) {
- goto err;
- }
-
- if (e != NULL) {
- BN_free(ret->e);
- ret->e = BN_dup(e);
- }
- if (ret->e == NULL) {
- goto err;
- }
-
- if (bn_mod_exp != NULL) {
- ret->bn_mod_exp = bn_mod_exp;
- }
- if (mont != NULL) {
- ret->mont = mont;
- }
- do {
- if (!BN_rand_range(ret->A, ret->mod)) {
- goto err;
+ /* |BN_from_montgomery| + |BN_mod_inverse_no_branch| is equivalent to, but
+ * more efficient than, |BN_mod_inverse_no_branch| + |BN_to_montgomery|. */
+ if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
int no_inverse;
- if (BN_mod_inverse_ex(ret->Ai, &no_inverse, ret->A, ret->mod, ctx) == NULL) {
+ if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->Ai, &mont_N_consttime, ctx) ==
+ NULL) {
/* this should almost never happen for good RSA keys */
if (no_inverse) {
if (retry_counter-- == 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
- goto err;
+ return 0;
}
ERR_clear_error();
} else {
- goto err;
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
} else {
break;
}
} while (1);
- if (ret->bn_mod_exp != NULL && ret->mont != NULL) {
- if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->mont)) {
- goto err;
- }
- } else {
- if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) {
- goto err;
- }
- }
-
- return ret;
-
-err:
- if (b == NULL) {
- BN_BLINDING_free(ret);
- ret = NULL;
- }
-
- return ret;
-}
-
-static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
- const BIGNUM *q, BN_CTX *ctx) {
- BIGNUM *ret = NULL, *r0, *r1, *r2;
-
- if (d == NULL || p == NULL || q == NULL) {
- return NULL;
- }
-
- BN_CTX_start(ctx);
- r0 = BN_CTX_get(ctx);
- r1 = BN_CTX_get(ctx);
- r2 = BN_CTX_get(ctx);
- if (r2 == NULL) {
- goto err;
- }
-
- if (!BN_sub(r1, p, BN_value_one())) {
- goto err;
- }
- if (!BN_sub(r2, q, BN_value_one())) {
- goto err;
- }
- if (!BN_mul(r0, r1, r2, ctx)) {
- goto err;
- }
-
- ret = BN_mod_inverse(NULL, d, r0, ctx);
-
-err:
- BN_CTX_end(ctx);
- return ret;
-}
-
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
- BIGNUM local_n;
- BIGNUM *e, *n;
- BN_CTX *ctx;
- BN_BLINDING *ret = NULL;
- BN_MONT_CTX *mont_ctx = NULL;
-
- if (in_ctx == NULL) {
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- } else {
- ctx = in_ctx;
- }
-
- BN_CTX_start(ctx);
- e = BN_CTX_get(ctx);
- if (e == NULL) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (rsa->e == NULL) {
- e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
- if (e == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
- goto err;
- }
- } else {
- e = rsa->e;
- }
-
- n = &local_n;
- BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
-
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- mont_ctx = BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx);
- if (mont_ctx == NULL) {
- goto err;
- }
- }
-
- ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
- mont_ctx);
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
- goto err;
+ if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
-err:
- BN_CTX_end(ctx);
- if (in_ctx == NULL) {
- BN_CTX_free(ctx);
- }
- if (rsa->e == NULL) {
- BN_free(e);
+ if (!BN_to_montgomery(b->A, b->A, mont, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- return ret;
+ return 1;
}
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
index 4e896e28..c6ea97f0 100644
--- a/src/crypto/rsa/internal.h
+++ b/src/crypto/rsa/internal.h
@@ -77,9 +77,6 @@ int rsa_default_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out,
int padding);
int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
- size_t max_out, const uint8_t *in, size_t in_len,
- int padding);
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len);
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
@@ -90,25 +87,12 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
#define RSA_PKCS1_PADDING_SIZE 11
-/* BN_BLINDING flags */
-#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(void);
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);
-int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
-int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
-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,
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
- const BN_MONT_CTX *mont);
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont_ctx, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
+ BN_CTX *ctx);
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
index 032df2e6..12147ea4 100644
--- a/src/crypto/rsa/padding.c
+++ b/src/crypto/rsa/padding.c
@@ -59,6 +59,7 @@
#include <limits.h>
#include <string.h>
+#include <openssl/bn.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -73,7 +74,6 @@
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned j;
- uint8_t *p;
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
@@ -85,7 +85,7 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
return 0;
}
- p = (uint8_t *)to;
+ uint8_t *p = to;
*(p++) = 0;
*(p++) = 1; /* Private Key BT (Block Type) */
@@ -95,7 +95,7 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
memset(p, 0xff, j);
p += j;
*(p++) = 0;
- memcpy(p, from, (unsigned int)from_len);
+ memcpy(p, from, from_len);
return 1;
}
@@ -154,7 +154,6 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned i, j;
- uint8_t *p;
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
@@ -166,7 +165,7 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
return 0;
}
- p = (unsigned char *)to;
+ uint8_t *p = to;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
@@ -189,7 +188,7 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
*(p++) = 0;
- memcpy(p, from, (unsigned int)from_len);
+ memcpy(p, from, from_len);
return 1;
}
@@ -271,12 +270,12 @@ int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
return 0;
}
- memcpy(to, from, (unsigned int)from_len);
+ memcpy(to, from, from_len);
return 1;
}
-int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
- unsigned seedlen, const EVP_MD *dgst) {
+static int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
+ unsigned seedlen, const EVP_MD *dgst) {
unsigned outlen = 0;
uint32_t i;
uint8_t cnt[4];
@@ -357,7 +356,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
seed = to + 1;
db = to + mdlen + 1;
- if (!EVP_Digest((void *)param, param_len, db, NULL, md, NULL)) {
+ if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
return 0;
}
memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
@@ -443,7 +442,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
db[i] ^= maskeddb[i];
}
- if (!EVP_Digest((void *)param, param_len, phash, NULL, md, NULL)) {
+ if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
goto err;
}
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
index 6c28ad76..e5f98916 100644
--- a/src/crypto/rsa/rsa.c
+++ b/src/crypto/rsa/rsa.c
@@ -64,7 +64,7 @@
#include <openssl/err.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/thread.h>
#include "internal.h"
@@ -76,7 +76,7 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
RSA *RSA_new(void) { return RSA_new_method(NULL); }
RSA *RSA_new_method(const ENGINE *engine) {
- RSA *rsa = (RSA *)OPENSSL_malloc(sizeof(RSA));
+ RSA *rsa = OPENSSL_malloc(sizeof(RSA));
if (rsa == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -258,16 +258,6 @@ int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
return out_len;
}
-int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
- const uint8_t *in, size_t in_len, int padding) {
- if (rsa->meth->verify_raw) {
- return rsa->meth->verify_raw(rsa, out_len, out, max_out, in, in_len, padding);
- }
-
- return rsa_default_verify_raw(rsa, out_len, out, max_out, in, in_len,
- padding);
-}
-
int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
int padding) {
size_t out_len;
@@ -473,6 +463,11 @@ finish:
int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
const uint8_t *sig, size_t sig_len, RSA *rsa) {
+ if (rsa->n == NULL || rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
const size_t rsa_size = RSA_size(rsa);
uint8_t *buf = NULL;
int ret = 0;
@@ -480,15 +475,6 @@ int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
size_t signed_msg_len, len;
int signed_msg_is_alloced = 0;
- if (rsa->meth->verify) {
- return rsa->meth->verify(hash_nid, msg, msg_len, sig, sig_len, rsa);
- }
-
- if (sig_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
- return 0;
- }
-
if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
return 0;
@@ -510,7 +496,7 @@ int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
goto out;
}
- if (len != signed_msg_len || CRYPTO_memcmp(buf, signed_msg, len) != 0) {
+ if (len != signed_msg_len || memcmp(buf, signed_msg, len) != 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
goto out;
}
diff --git a/src/crypto/rsa/rsa_asn1.c b/src/crypto/rsa/rsa_asn1.c
index b73a0e19..d14ecaee 100644
--- a/src/crypto/rsa/rsa_asn1.c
+++ b/src/crypto/rsa/rsa_asn1.c
@@ -59,14 +59,13 @@
#include <limits.h>
#include <string.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
+#include "../bytestring/internal.h"
static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) {
@@ -76,9 +75,9 @@ static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) {
return 0;
}
if (buggy) {
- return BN_cbs2unsigned_buggy(cbs, *out);
+ return BN_parse_asn1_unsigned_buggy(cbs, *out);
}
- return BN_cbs2unsigned(cbs, *out);
+ return BN_parse_asn1_unsigned(cbs, *out);
}
static int parse_integer(CBS *cbs, BIGNUM **out) {
@@ -91,7 +90,7 @@ static int marshal_integer(CBB *cbb, BIGNUM *bn) {
OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
return 0;
}
- return BN_bn2cbb(cbb, bn);
+ return BN_marshal_asn1(cbb, bn);
}
static RSA *parse_public_key(CBS *cbs, int buggy) {
@@ -232,9 +231,11 @@ RSA *RSA_parse_private_key(CBS *cbs) {
goto err;
}
- /* Multi-prime RSA requires a newer version. */
- if (version == kVersionMulti &&
- CBS_peek_asn1_tag(&child, CBS_ASN1_SEQUENCE)) {
+ if (version == kVersionMulti) {
+ /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later
+ * says "[otherPrimeInfos] shall be omitted if version is 0 and shall
+ * contain at least one instance of OtherPrimeInfo if version is 1." The
+ * OPTIONAL is just so both versions share a single definition. */
CBS other_prime_infos;
if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) ||
CBS_len(&other_prime_infos) == 0) {
@@ -379,32 +380,18 @@ RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) {
RSA_free(*out);
*out = ret;
}
- *inp += (size_t)len - CBS_len(&cbs);
+ *inp = CBS_data(&cbs);
return ret;
}
int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) {
- uint8_t *der;
- size_t der_len;
- if (!RSA_public_key_to_bytes(&der, &der_len, in)) {
- return -1;
- }
- if (der_len > INT_MAX) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
- OPENSSL_free(der);
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !RSA_marshal_public_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
- if (outp != NULL) {
- if (*outp == NULL) {
- *outp = der;
- der = NULL;
- } else {
- memcpy(*outp, der, der_len);
- *outp += der_len;
- }
- }
- OPENSSL_free(der);
- return (int)der_len;
+ return CBB_finish_i2d(&cbb, outp);
}
RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) {
@@ -421,43 +408,20 @@ RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) {
RSA_free(*out);
*out = ret;
}
- *inp += (size_t)len - CBS_len(&cbs);
+ *inp = CBS_data(&cbs);
return ret;
}
int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) {
- uint8_t *der;
- size_t der_len;
- if (!RSA_private_key_to_bytes(&der, &der_len, in)) {
- return -1;
- }
- if (der_len > INT_MAX) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
- OPENSSL_free(der);
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !RSA_marshal_private_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
- if (outp != NULL) {
- if (*outp == NULL) {
- *outp = der;
- der = NULL;
- } else {
- memcpy(*outp, der, der_len);
- *outp += der_len;
- }
- }
- OPENSSL_free(der);
- return (int)der_len;
+ return CBB_finish_i2d(&cbb, outp);
}
-ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
- ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
-} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
-
-IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
-
RSA *RSAPublicKey_dup(const RSA *rsa) {
uint8_t *der;
size_t der_len;
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index b1cfaa63..3e30d898 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -56,6 +56,7 @@
#include <openssl/rsa.h>
+#include <assert.h>
#include <string.h>
#include <openssl/bn.h>
@@ -67,11 +68,42 @@
#include "../internal.h"
-#define OPENSSL_RSA_MAX_MODULUS_BITS 16384
-#define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
-#define OPENSSL_RSA_MAX_PUBEXP_BITS \
- 64 /* exponent limit enforced for "large" modulus only */
+static int check_modulus_and_exponent_sizes(const RSA *rsa) {
+ unsigned rsa_bits = BN_num_bits(rsa->n);
+ if (rsa_bits > 16 * 1024) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ /* Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as
+ * the limit based on the recommendations in [1] and [2]. Windows CryptoAPI
+ * doesn't support values larger than 32 bits [3], so it is unlikely that
+ * exponents larger than 32 bits are being used for anything Windows commonly
+ * does.
+ *
+ * [1] https://www.imperialviolet.org/2012/03/16/rsae.html
+ * [2] https://www.imperialviolet.org/2012/03/17/rsados.html
+ * [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx */
+ static const unsigned kMaxExponentBits = 33;
+
+ if (BN_num_bits(rsa->e) > kMaxExponentBits) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+ return 0;
+ }
+
+ /* Verify |n > e|. Comparing |rsa_bits| to |kMaxExponentBits| is a small
+ * shortcut to comparing |n| and |e| directly. In reality, |kMaxExponentBits|
+ * is much smaller than the minimum RSA key size that any application should
+ * accept. */
+ if (rsa_bits <= kMaxExponentBits) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+ assert(BN_ucmp(rsa->n, rsa->e) > 0);
+
+ return 1;
+}
size_t rsa_default_size(const RSA *rsa) {
return BN_num_bytes(rsa->n);
@@ -85,25 +117,12 @@ int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
BN_CTX *ctx = NULL;
int i, ret = 0;
- if (rsa_size > OPENSSL_RSA_MAX_MODULUS_BITS) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
- return 0;
- }
-
if (max_out < rsa_size) {
OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
- if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
- return 0;
- }
-
- /* for large moduli, enforce exponent limit */
- if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
- BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+ if (!check_modulus_and_exponent_sizes(rsa)) {
return 0;
}
@@ -152,13 +171,8 @@ int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
goto err;
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
- }
-
- if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+ !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
goto err;
}
@@ -199,6 +213,9 @@ err:
* |*index_used| and must be passed to |rsa_blinding_release| when finished. */
static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
BN_CTX *ctx) {
+ assert(ctx != NULL);
+ assert(rsa->mont_n != NULL);
+
BN_BLINDING *ret = NULL;
BN_BLINDING **new_blindings;
uint8_t *new_blindings_inuse;
@@ -227,7 +244,7 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
* the arrays by one and use the newly created element. */
CRYPTO_MUTEX_unlock(&rsa->lock);
- ret = rsa_setup_blinding(rsa, ctx);
+ ret = BN_BLINDING_new();
if (ret == NULL) {
return NULL;
}
@@ -407,46 +424,49 @@ err:
return ret;
}
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
- size_t max_out, const uint8_t *in, size_t in_len,
- int padding) {
+static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+
+int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->n == NULL || rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
const unsigned rsa_size = RSA_size(rsa);
BIGNUM *f, *result;
- int ret = 0;
int r = -1;
- uint8_t *buf = NULL;
- BN_CTX *ctx = NULL;
- if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
+ if (max_out < rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
- if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+ if (in_len != rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
return 0;
}
- if (max_out < rsa_size) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ if (!check_modulus_and_exponent_sizes(rsa)) {
return 0;
}
- /* for large moduli, enforce exponent limit */
- if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
- BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+ BN_CTX *ctx = BN_CTX_new();
+ if (ctx == NULL) {
return 0;
}
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- goto err;
- }
+ int ret = 0;
+ uint8_t *buf = NULL;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
result = BN_CTX_get(ctx);
+ if (f == NULL || result == NULL) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (padding == RSA_NO_PADDING) {
buf = out;
} else {
@@ -457,15 +477,6 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
goto err;
}
}
- if (!f || !result) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (in_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
- goto err;
- }
if (BN_bin2bn(in, in_len, f) == NULL) {
goto err;
@@ -476,13 +487,8 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
goto err;
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
- }
-
- if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+ !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
goto err;
}
@@ -511,12 +517,9 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
}
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
- if (padding != RSA_NO_PADDING && buf != NULL) {
- OPENSSL_cleanse(buf, rsa_size);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ if (buf != out) {
OPENSSL_free(buf);
}
return ret;
@@ -554,20 +557,31 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
}
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+ /* Keys without public exponents must have blinding explicitly disabled to
+ * be used. */
+ if (rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
+ goto err;
+ }
+
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
if (blinding == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (!BN_BLINDING_convert_ex(f, NULL, blinding, ctx)) {
+ if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) {
goto err;
}
}
- if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
- ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
- (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
- if (!rsa->meth->mod_exp(result, f, rsa, ctx)) {
+ if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL &&
+ rsa->dmq1 != NULL && rsa->iqmp != NULL) {
+ if (!mod_exp(result, f, rsa, ctx)) {
goto err;
}
} else {
@@ -578,20 +592,14 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
d = &local_d;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ==
- NULL) {
- goto err;
- }
- }
-
- if (!rsa->meth->bn_mod_exp(result, f, d, rsa->n, ctx, rsa->mont_n)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+ !BN_mod_exp_mont_consttime(result, f, d, rsa->n, ctx, rsa->mont_n)) {
goto err;
}
}
if (blinding) {
- if (!BN_BLINDING_invert_ex(result, NULL, blinding, ctx)) {
+ if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
goto err;
}
}
@@ -616,6 +624,17 @@ err:
}
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
+ assert(ctx != NULL);
+
+ assert(rsa->n != NULL);
+ assert(rsa->e != NULL);
+ assert(rsa->d != NULL);
+ assert(rsa->p != NULL);
+ assert(rsa->q != NULL);
+ assert(rsa->dmp1 != NULL);
+ assert(rsa->dmq1 != NULL);
+ assert(rsa->iqmp != NULL);
+
BIGNUM *r1, *m1, *vrfy;
BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
BIGNUM *dmp1, *dmq1, *c, *pr1;
@@ -630,6 +649,11 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
r1 = BN_CTX_get(ctx);
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
+ if (r1 == NULL ||
+ m1 == NULL ||
+ vrfy == NULL) {
+ goto err;
+ }
{
BIGNUM local_p, local_q;
@@ -645,20 +669,14 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
q = &local_q;
BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
- if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) == NULL) {
- goto err;
- }
- if (BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx) == NULL) {
- goto err;
- }
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) ||
+ !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) {
+ goto err;
}
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+ goto err;
}
/* compute I mod q */
@@ -671,7 +689,7 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
/* compute r1^dmq1 mod q */
dmq1 = &local_dmq1;
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
+ if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
goto err;
}
@@ -685,7 +703,7 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
/* compute r1^dmp1 mod p */
dmp1 = &local_dmp1;
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
+ if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
goto err;
}
@@ -745,12 +763,8 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
goto err;
}
- if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
- !BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx)) {
- goto err;
- }
-
- if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->mont)) {
+ if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) ||
+ !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) {
goto err;
}
@@ -766,38 +780,35 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
}
}
- if (rsa->e && rsa->n) {
- if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, rsa->mont_n)) {
- goto err;
- }
- /* If 'I' was greater than (or equal to) rsa->n, the operation
- * will be equivalent to using 'I mod n'. However, the result of
- * the verify will *always* be less than 'n' so we don't check
- * for absolute equality, just congruency. */
- if (!BN_sub(vrfy, vrfy, I)) {
- goto err;
- }
- if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
+ if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+ goto err;
+ }
+ /* If 'I' was greater than (or equal to) rsa->n, the operation will be
+ * equivalent to using 'I mod n'. However, the result of the verify will
+ * *always* be less than 'n' so we don't check for absolute equality, just
+ * congruency. */
+ if (!BN_sub(vrfy, vrfy, I)) {
+ goto err;
+ }
+ if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
+ goto err;
+ }
+ if (BN_is_negative(vrfy)) {
+ if (!BN_add(vrfy, vrfy, rsa->n)) {
goto err;
}
- if (BN_is_negative(vrfy)) {
- if (!BN_add(vrfy, vrfy, rsa->n)) {
- goto err;
- }
- }
- if (!BN_is_zero(vrfy)) {
- /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
- * miscalculated CRT output, just do a raw (slower)
- * mod_exp and return that instead. */
+ }
+ if (!BN_is_zero(vrfy)) {
+ /* 'I' and 'vrfy' aren't congruent mod n. Don't leak miscalculated CRT
+ * output, just do a raw (slower) mod_exp and return that instead. */
- BIGNUM local_d;
- BIGNUM *d = NULL;
+ BIGNUM local_d;
+ BIGNUM *d = NULL;
- d = &local_d;
- BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->mont_n)) {
- goto err;
- }
+ d = &local_d;
+ BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+ if (!BN_mod_exp_mont_consttime(r0, I, d, rsa->n, ctx, rsa->mont_n)) {
+ goto err;
}
}
ret = 1;
@@ -1101,9 +1112,9 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
cb);
}
-/* Many of these methods are NULL to more easily drop unused functions. The
- * wrapper functions will select the appropriate |rsa_default_*| for all
- * methods. */
+/* All of the methods are NULL to make it easier for the compiler/linker to drop
+ * unused functions. The wrapper functions will select the appropriate
+ * |rsa_default_*| implementation. */
const RSA_METHOD RSA_default_method = {
{
0 /* references */,
@@ -1126,8 +1137,8 @@ const RSA_METHOD RSA_default_method = {
NULL /* private_transform (defaults to rsa_default_private_transform) */,
- mod_exp,
- BN_mod_exp_mont /* bn_mod_exp */,
+ NULL /* mod_exp (ignored) */,
+ NULL /* bn_mod_exp (ignored) */,
RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
diff --git a/src/crypto/rsa/rsa_test.cc b/src/crypto/rsa/rsa_test.cc
index 5545161c..62177a4c 100644
--- a/src/crypto/rsa/rsa_test.cc
+++ b/src/crypto/rsa/rsa_test.cc
@@ -63,7 +63,7 @@
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "../test/scoped_types.h"
@@ -593,6 +593,7 @@ static bool TestRSA(const uint8_t *der, size_t der_len,
fprintf(stderr, "Corrupt data decrypted!\n");
return false;
}
+ ERR_clear_error();
ciphertext[i] ^= 1;
}
@@ -603,6 +604,7 @@ static bool TestRSA(const uint8_t *der, size_t der_len,
fprintf(stderr, "Corrupt data decrypted!\n");
return false;
}
+ ERR_clear_error();
}
return true;
@@ -693,25 +695,27 @@ static bool TestBadKey() {
}
static bool TestOnlyDGiven() {
+ static const char kN[] =
+ "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662"
+ "1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659";
+ static const char kE[] = "010001";
+ static const char kD[] =
+ "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a"
+ "73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01";
+
uint8_t buf[64];
unsigned buf_len = sizeof(buf);
ScopedRSA key(RSA_new());
if (!key ||
- !BN_hex2bn(&key->n,
- "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd"
- "09ac42b26621cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e"
- "5808c659") ||
- !BN_hex2bn(&key->e, "010001") ||
- !BN_hex2bn(&key->d,
- "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea"
- "316eaeca21a73ac365e58713195f2ae9849348525ca855386b6d028e437a9"
- "495a01") ||
+ !BN_hex2bn(&key->n, kN) ||
+ !BN_hex2bn(&key->e, kE) ||
+ !BN_hex2bn(&key->d, kD) ||
RSA_size(key.get()) > sizeof(buf)) {
return false;
}
if (!RSA_check_key(key.get())) {
- fprintf(stderr, "RSA_check_key failed with only d given.\n");
+ fprintf(stderr, "RSA_check_key failed with only n, d, and e given.\n");
ERR_print_errors_fp(stderr);
return false;
}
@@ -720,14 +724,46 @@ static bool TestOnlyDGiven() {
if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
key.get())) {
- fprintf(stderr, "RSA_sign failed with only d given.\n");
+ fprintf(stderr, "RSA_sign failed with only n, d, and e given.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
+ key.get())) {
+ fprintf(stderr, "RSA_verify failed with only n, d, and e given.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ // Keys without the public exponent must continue to work when blinding is
+ // disabled to support Java's RSAPrivateKeySpec API. See
+ // https://bugs.chromium.org/p/boringssl/issues/detail?id=12.
+ ScopedRSA key2(RSA_new());
+ if (!key2 ||
+ !BN_hex2bn(&key2->n, kN) ||
+ !BN_hex2bn(&key2->d, kD)) {
+ return false;
+ }
+ key2->flags |= RSA_FLAG_NO_BLINDING;
+
+ if (RSA_size(key2.get()) > sizeof(buf)) {
+ return false;
+ }
+
+ if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
+ key2.get())) {
+ fprintf(stderr, "RSA_sign failed with only n and d given.\n");
ERR_print_errors_fp(stderr);
return false;
}
+ // Verify the signature with |key|. |key2| has no public exponent.
if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
key.get())) {
- fprintf(stderr, "RSA_verify failed with only d given.\n");
+ fprintf(stderr,
+ "Could not verify signature produced from key with only n and d "
+ "given.\n");
ERR_print_errors_fp(stderr);
return false;
}
diff --git a/src/crypto/sha/asm/sha512-armv4.pl b/src/crypto/sha/asm/sha512-armv4.pl
index cd3662a5..15d50f28 100644
--- a/src/crypto/sha/asm/sha512-armv4.pl
+++ b/src/crypto/sha/asm/sha512-armv4.pl
@@ -291,7 +291,7 @@ sha512_block_data_order:
#ifdef __APPLE__
ldr r12,[r12]
#endif
- tst r12,#1
+ tst r12,#ARMV7_NEON
bne .LNEON
#endif
add $len,$inp,$len,lsl#7 @ len to point at the end of inp
diff --git a/src/crypto/sha/sha256.c b/src/crypto/sha/sha256.c
index 0ddacbad..58f7c42c 100644
--- a/src/crypto/sha/sha256.c
+++ b/src/crypto/sha/sha256.c
@@ -104,8 +104,8 @@ uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
out = buf;
}
SHA224_Init(&ctx);
- SHA256_Update(&ctx, data, len);
- SHA256_Final(out, &ctx);
+ SHA224_Update(&ctx, data, len);
+ SHA224_Final(out, &ctx);
OPENSSL_cleanse(&ctx, sizeof(ctx));
return out;
}
diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c
index 6ad8d40c..f4730463 100644
--- a/src/crypto/sha/sha512.c
+++ b/src/crypto/sha/sha512.c
@@ -129,8 +129,8 @@ uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
}
SHA384_Init(&ctx);
- SHA512_Update(&ctx, data, len);
- SHA512_Final(out, &ctx);
+ SHA384_Update(&ctx, data, len);
+ SHA384_Final(out, &ctx);
OPENSSL_cleanse(&ctx, sizeof(ctx));
return out;
}
diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c
index c5845159..e8932217 100644
--- a/src/crypto/stack/stack.c
+++ b/src/crypto/stack/stack.c
@@ -329,7 +329,7 @@ err:
void sk_sort(_STACK *sk) {
int (*comp_func)(const void *,const void *);
- if (sk == NULL || sk->sorted) {
+ if (sk == NULL || sk->comp == NULL || sk->sorted) {
return;
}
diff --git a/src/crypto/test/file_test.cc b/src/crypto/test/file_test.cc
index 4752f04a..d684aa09 100644
--- a/src/crypto/test/file_test.cc
+++ b/src/crypto/test/file_test.cc
@@ -14,6 +14,8 @@
#include "file_test.h"
+#include <memory>
+
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
@@ -63,30 +65,23 @@ static std::string StripSpace(const char *str, size_t len) {
}
FileTest::ReadResult FileTest::ReadNext() {
- // If the previous test had unused attributes or block, it is an error.
+ // If the previous test had unused attributes, it is an error.
if (!unused_attributes_.empty()) {
for (const std::string &key : unused_attributes_) {
PrintLine("Unused attribute: %s", key.c_str());
}
return kReadError;
}
- if (!block_.empty() && !used_block_) {
- PrintLine("Unused block");
- return kReadError;
- }
ClearTest();
- bool in_block = false;
+ static const size_t kBufLen = 64 + 8192*2;
+ std::unique_ptr<char[]> buf(new char[kBufLen]);
+
while (true) {
// Read the next line.
- char buf[4096];
- if (fgets(buf, sizeof(buf), file_) == nullptr) {
+ if (fgets(buf.get(), kBufLen, file_) == nullptr) {
if (feof(file_)) {
- if (in_block) {
- fprintf(stderr, "Unterminated block.\n");
- return kReadError;
- }
// EOF is a valid terminator for a test.
return start_line_ > 0 ? kReadSuccess : kReadEOF;
}
@@ -95,42 +90,28 @@ FileTest::ReadResult FileTest::ReadNext() {
}
line_++;
- size_t len = strlen(buf);
+ size_t len = strlen(buf.get());
// Check for truncation.
if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) {
fprintf(stderr, "Line %u too long.\n", line_);
return kReadError;
}
- bool is_delimiter = strncmp(buf, "---", 3) == 0;
- if (in_block) {
- block_ += buf;
- if (is_delimiter) {
- // Ending the block completes the test.
- return kReadSuccess;
- }
- } else if (is_delimiter) {
- if (start_line_ == 0) {
- fprintf(stderr, "Line %u: Unexpected block.\n", line_);
- return kReadError;
- }
- in_block = true;
- block_ += buf;
- } else if (buf[0] == '\n' || buf[0] == '\0') {
+ if (buf[0] == '\n' || buf[0] == '\0') {
// Empty lines delimit tests.
if (start_line_ > 0) {
return kReadSuccess;
}
} else if (buf[0] != '#') { // Comment lines are ignored.
// Parse the line as an attribute.
- const char *delimiter = FindDelimiter(buf);
+ const char *delimiter = FindDelimiter(buf.get());
if (delimiter == nullptr) {
fprintf(stderr, "Line %u: Could not parse attribute.\n", line_);
return kReadError;
}
- std::string key = StripSpace(buf, delimiter - buf);
+ std::string key = StripSpace(buf.get(), delimiter - buf.get());
std::string value = StripSpace(delimiter + 1,
- buf + len - delimiter - 1);
+ buf.get() + len - delimiter - 1);
unused_attributes_.insert(key);
attributes_[key] = value;
@@ -165,11 +146,6 @@ const std::string &FileTest::GetParameter() {
return parameter_;
}
-const std::string &FileTest::GetBlock() {
- used_block_ = true;
- return block_;
-}
-
bool FileTest::HasAttribute(const std::string &key) {
OnKeyUsed(key);
return attributes_.count(key) > 0;
@@ -224,6 +200,7 @@ bool FileTest::GetBytes(std::vector<uint8_t> *out, const std::string &key) {
PrintLine("Error decoding value: %s", value.c_str());
return false;
}
+ out->clear();
out->reserve(value.size() / 2);
for (size_t i = 0; i < value.size(); i += 2) {
uint8_t hi, lo;
@@ -266,9 +243,7 @@ void FileTest::ClearTest() {
type_.clear();
parameter_.clear();
attributes_.clear();
- block_.clear();
unused_attributes_.clear();
- used_block_ = false;
}
void FileTest::OnKeyUsed(const std::string &key) {
@@ -304,6 +279,7 @@ int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
t.GetAttributeOrDie("Error").c_str(),
ERR_reason_error_string(err));
failed = true;
+ ERR_clear_error();
continue;
}
ERR_clear_error();
diff --git a/src/crypto/test/file_test.h b/src/crypto/test/file_test.h
index 24651ab8..e90cc86a 100644
--- a/src/crypto/test/file_test.h
+++ b/src/crypto/test/file_test.h
@@ -15,6 +15,8 @@
#ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
#define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
+#include <openssl/base.h>
+
#include <stdint.h>
#include <stdio.h>
@@ -36,7 +38,7 @@
//
// This module provides a file-based test framework. The file format is based on
// that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input
-// file is a sequence of attributes, blocks, and blank lines.
+// file is a sequence of attributes and blank lines.
//
// Each attribute has the form:
//
@@ -45,15 +47,11 @@
// Either '=' or ':' may be used to delimit the name from the value. Both the
// name and value have leading and trailing spaces stripped.
//
-// Blocks are delimited by lines beginning with three hyphens, "---". One such
-// line begins a block and another ends it. Blocks are intended as a convenient
-// way to embed PEM data and include their delimiters.
-//
-// Outside a block, lines beginning with # are ignored.
+// Lines beginning with # are ignored.
//
-// A test is a sequence of one or more attributes followed by a block or blank
-// line. Blank lines are otherwise ignored. For tests that process multiple
-// kinds of test cases, the first attribute is parsed out as the test's type and
+// A test is a sequence of one or more attributes followed by a blank line.
+// Blank lines are otherwise ignored. For tests that process multiple kinds of
+// test cases, the first attribute is parsed out as the test's type and
// parameter. Otherwise, attributes are unordered. The first attribute is also
// included in the set of attributes, so tests which do not dispatch may ignore
// this mechanism.
@@ -88,11 +86,7 @@ class FileTest {
// PrintLine is a variant of printf which prepends the line number and appends
// a trailing newline.
- void PrintLine(const char *format, ...)
-#ifdef __GNUC__
- __attribute__((__format__(__printf__, 2, 3)))
-#endif
- ;
+ void PrintLine(const char *format, ...) OPENSSL_PRINTF_FORMAT_FUNC(2, 3);
unsigned start_line() const { return start_line_; }
@@ -100,9 +94,6 @@ class FileTest {
const std::string &GetType();
// GetParameter returns the value of the first attribute of the current test.
const std::string &GetParameter();
- // GetBlock returns the optional block of the current test, or the empty
- // if there was no block.
- const std::string &GetBlock();
// HasAttribute returns true if the current test has an attribute named |key|.
bool HasAttribute(const std::string &key);
@@ -113,7 +104,7 @@ class FileTest {
bool GetAttribute(std::string *out_value, const std::string &key);
// GetAttributeOrDie looks up the attribute with key |key| and aborts if it is
- // missing. It only be used after a |HasAttribute| call.
+ // missing. It should only be used after a |HasAttribute| call.
const std::string &GetAttributeOrDie(const std::string &key);
// GetBytes looks up the attribute with key |key| and decodes it as a byte
@@ -144,13 +135,9 @@ class FileTest {
std::string parameter_;
// attributes_ contains all attributes in the test, including the first.
std::map<std::string, std::string> attributes_;
- // block_, if non-empty, is the test's optional trailing block.
- std::string block_;
// unused_attributes_ is the set of attributes that have been queried.
std::set<std::string> unused_attributes_;
- // used_block_ is true if the block has been queried.
- bool used_block_ = false;
FileTest(const FileTest&) = delete;
FileTest &operator=(const FileTest&) = delete;
diff --git a/src/crypto/test/scoped_types.h b/src/crypto/test/scoped_types.h
index 590f926a..5c49a7ee 100644
--- a/src/crypto/test/scoped_types.h
+++ b/src/crypto/test/scoped_types.h
@@ -21,13 +21,16 @@
#include <memory>
#include <openssl/aead.h>
+#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/cmac.h>
+#include <openssl/curve25519.h>
#include <openssl/dh.h>
+#include <openssl/ecdsa.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
@@ -95,6 +98,7 @@ class ScopedOpenSSLContext {
T ctx_;
};
+using ScopedASN1_TYPE = ScopedOpenSSLType<ASN1_TYPE, ASN1_TYPE_free>;
using ScopedBIO = ScopedOpenSSLType<BIO, BIO_vfree>;
using ScopedBIGNUM = ScopedOpenSSLType<BIGNUM, BN_free>;
using ScopedBN_CTX = ScopedOpenSSLType<BN_CTX, BN_CTX_free>;
@@ -110,10 +114,12 @@ using ScopedEVP_PKEY_CTX = ScopedOpenSSLType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType<PKCS8_PRIV_KEY_INFO,
PKCS8_PRIV_KEY_INFO_free>;
using ScopedPKCS12 = ScopedOpenSSLType<PKCS12, PKCS12_free>;
+using ScopedSPAKE2_CTX = ScopedOpenSSLType<SPAKE2_CTX, SPAKE2_CTX_free>;
using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
using ScopedX509 = ScopedOpenSSLType<X509, X509_free>;
using ScopedX509_ALGOR = ScopedOpenSSLType<X509_ALGOR, X509_ALGOR_free>;
using ScopedX509_SIG = ScopedOpenSSLType<X509_SIG, X509_SIG_free>;
+using ScopedX509_STORE_CTX = ScopedOpenSSLType<X509_STORE_CTX, X509_STORE_CTX_free>;
using ScopedX509Stack = ScopedOpenSSLStack<STACK_OF(X509), X509, X509_free>;
diff --git a/src/crypto/test/test_util.h b/src/crypto/test/test_util.h
index 972e2065..89e70c6d 100644
--- a/src/crypto/test/test_util.h
+++ b/src/crypto/test/test_util.h
@@ -28,6 +28,14 @@ extern "C" {
void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
+#if defined(_MSC_VER) && _MSC_VER < 1900
+/* https://msdn.microsoft.com/en-us/library/tcxf1dw6(v=vs.120).aspx */
+#define OPENSSL_PR_SIZE_T "Iu"
+#else
+#define OPENSSL_PR_SIZE_T "zu"
+#endif
+
+
#if defined(__cplusplus)
}
#endif
diff --git a/src/crypto/thread_pthread.c b/src/crypto/thread_pthread.c
index 68aaab5b..2a1c9f8a 100644
--- a/src/crypto/thread_pthread.c
+++ b/src/crypto/thread_pthread.c
@@ -17,7 +17,6 @@
#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
#include <pthread.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,8 +75,6 @@ void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
if (pthread_once(once, init) != 0) {
- fprintf(stderr,
- "pthread_once failed. Did you link against a threading library?\n");
abort();
}
}
diff --git a/src/crypto/thread_test.c b/src/crypto/thread_test.c
index e028b1be..92a5373b 100644
--- a/src/crypto/thread_test.c
+++ b/src/crypto/thread_test.c
@@ -53,6 +53,8 @@ static int wait_for_thread(thread_t thread) {
#else
#include <pthread.h>
+#include <string.h>
+#include <time.h>
typedef pthread_t thread_t;
@@ -77,6 +79,17 @@ static unsigned g_once_init_called = 0;
static void once_init(void) {
g_once_init_called++;
+
+ /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once|
+ * while the other is running this function. */
+#if defined(OPENSSL_WINDOWS)
+ Sleep(1 /* milliseconds */);
+#else
+ struct timespec req;
+ memset(&req, 0, sizeof(req));
+ req.tv_nsec = 1000000;
+ nanosleep(&req, NULL);
+#endif
}
static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT;
@@ -91,9 +104,11 @@ static int test_once(void) {
return 0;
}
- thread_t thread;
- if (!run_thread(&thread, call_once_thread) ||
- !wait_for_thread(thread)) {
+ thread_t thread1, thread2;
+ if (!run_thread(&thread1, call_once_thread) ||
+ !run_thread(&thread2, call_once_thread) ||
+ !wait_for_thread(thread1) ||
+ !wait_for_thread(thread2)) {
fprintf(stderr, "thread failed.\n");
return 0;
}
diff --git a/src/crypto/thread_win.c b/src/crypto/thread_win.c
index 5efd8be3..26325656 100644
--- a/src/crypto/thread_win.c
+++ b/src/crypto/thread_win.c
@@ -20,7 +20,6 @@
#include <windows.h>
#pragma warning(pop)
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -31,61 +30,16 @@
OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(CRITICAL_SECTION),
CRYPTO_MUTEX_too_small);
-static void run_once(CRYPTO_once_t *in_once, void (*init)(void *), void *arg) {
- volatile LONG *once = in_once;
-
- /* Values must be aligned. */
- assert((((uintptr_t) once) & 3) == 0);
-
- /* This assumes that reading *once has acquire semantics. This should be true
- * on x86 and x86-64, where we expect Windows to run. */
-#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
-#error "Windows once code may not work on other platforms." \
- "You can use InitOnceBeginInitialize on >=Vista"
-#endif
- if (*once == 1) {
- return;
- }
-
- for (;;) {
- switch (InterlockedCompareExchange(once, 2, 0)) {
- case 0:
- /* The value was zero so we are the first thread to call |CRYPTO_once|
- * on it. */
- init(arg);
- /* Write one to indicate that initialisation is complete. */
- InterlockedExchange(once, 1);
- return;
-
- case 1:
- /* Another thread completed initialisation between our fast-path check
- * and |InterlockedCompareExchange|. */
- return;
-
- case 2:
- /* Another thread is running the initialisation. Switch to it then try
- * again. */
- SwitchToThread();
- break;
-
- default:
- abort();
- }
- }
+static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) {
+ void (**init)(void) = (void (**)(void))arg;
+ (**init)();
+ return TRUE;
}
-static void call_once_init(void *arg) {
- void (*init_func)(void);
- /* MSVC does not like casting between data and function pointers. */
- memcpy(&init_func, &arg, sizeof(void *));
- init_func();
-}
-
-void CRYPTO_once(CRYPTO_once_t *in_once, void (*init)(void)) {
- void *arg;
- /* MSVC does not like casting between data and function pointers. */
- memcpy(&arg, &init, sizeof(void *));
- run_once(in_once, call_once_init, arg);
+void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
+ if (!InitOnceExecuteOnce(once, call_once_init, &init, NULL)) {
+ abort();
+ }
}
void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
@@ -111,16 +65,21 @@ void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
DeleteCriticalSection((CRITICAL_SECTION *) lock);
}
-static void static_lock_init(void *arg) {
+static BOOL CALLBACK static_lock_init(INIT_ONCE *once, void *arg, void **out) {
struct CRYPTO_STATIC_MUTEX *lock = arg;
if (!InitializeCriticalSectionAndSpinCount(&lock->lock, 0x400)) {
abort();
}
+ return TRUE;
}
void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
- /* Since we have to support Windows XP, read locks are actually exclusive. */
- run_once(&lock->once, static_lock_init, lock);
+ /* TODO(davidben): Consider replacing these with SRWLOCK now that we no longer
+ * need to support Windows XP. Currently, read locks are actually
+ * exclusive. */
+ if (!InitOnceExecuteOnce(&lock->once, static_lock_init, lock, NULL)) {
+ abort();
+ }
EnterCriticalSection(&lock->lock);
}
@@ -148,9 +107,14 @@ static void thread_local_init(void) {
g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES);
}
-static void NTAPI thread_local_destructor(PVOID module,
- DWORD reason, PVOID reserved) {
- if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) {
+static void NTAPI thread_local_destructor(PVOID module, DWORD reason,
+ PVOID reserved) {
+ /* Only free memory on |DLL_THREAD_DETACH|, not |DLL_PROCESS_DETACH|. In
+ * VS2015's debug runtime, the C runtime has been unloaded by the time
+ * |DLL_PROCESS_DETACH| runs. See https://crbug.com/575795. This is consistent
+ * with |pthread_key_create| which does not call destructors on process exit,
+ * only thread exit. */
+ if (reason != DLL_THREAD_DETACH) {
return;
}
diff --git a/src/crypto/x509/CMakeLists.txt b/src/crypto/x509/CMakeLists.txt
index 8ffeaa0d..5d82e0a9 100644
--- a/src/crypto/x509/CMakeLists.txt
+++ b/src/crypto/x509/CMakeLists.txt
@@ -9,11 +9,13 @@ add_library(
a_sign.c
a_strex.c
a_verify.c
+ algorithm.c
asn1_gen.c
by_dir.c
by_file.c
i2d_pr.c
pkcs7.c
+ rsa_pss.c
t_crl.c
t_req.c
t_x509.c
@@ -64,5 +66,14 @@ add_executable(
$<TARGET_OBJECTS:test_support>
)
+add_executable(
+ x509_test
+
+ x509_test.cc
+
+ $<TARGET_OBJECTS:test_support>
+)
+
target_link_libraries(pkcs7_test crypto)
-add_dependencies(all_tests pkcs7_test)
+target_link_libraries(x509_test crypto)
+add_dependencies(all_tests pkcs7_test x509_test)
diff --git a/src/crypto/x509/a_digest.c b/src/crypto/x509/a_digest.c
index 430e2e6c..b88d6ac7 100644
--- a/src/crypto/x509/a_digest.c
+++ b/src/crypto/x509/a_digest.c
@@ -61,37 +61,36 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-
int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
- unsigned char *md, unsigned int *len)
- {
- int i, ret;
- unsigned char *str,*p;
+ unsigned char *md, unsigned int *len)
+{
+ int i, ret;
+ unsigned char *str, *p;
- i=i2d(data,NULL);
- if ((str=(unsigned char *)OPENSSL_malloc(i)) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return(0);
- }
- p=str;
- i2d(data,&p);
+ i = i2d(data, NULL);
+ if ((str = (unsigned char *)OPENSSL_malloc(i)) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ p = str;
+ i2d(data, &p);
- ret = EVP_Digest(str, i, md, len, type, NULL);
- OPENSSL_free(str);
- return ret;
- }
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+}
int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
- unsigned char *md, unsigned int *len)
- {
- int i, ret;
- unsigned char *str = NULL;
+ unsigned char *md, unsigned int *len)
+{
+ int i, ret;
+ unsigned char *str = NULL;
- i=ASN1_item_i2d(asn,&str, it);
- if (!str) return(0);
+ i = ASN1_item_i2d(asn, &str, it);
+ if (!str)
+ return (0);
- ret = EVP_Digest(str, i, md, len, type, NULL);
- OPENSSL_free(str);
- return ret;
- }
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+}
diff --git a/src/crypto/x509/a_sign.c b/src/crypto/x509/a_sign.c
index 4e9be8a4..13a3ac25 100644
--- a/src/crypto/x509/a_sign.c
+++ b/src/crypto/x509/a_sign.c
@@ -62,75 +62,74 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
+#include "internal.h"
-
-int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
- ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
- const EVP_MD *type)
- {
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
- if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
- {
- EVP_MD_CTX_cleanup(&ctx);
- return 0;
- }
- return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
- }
-
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
+ EVP_PKEY *pkey, const EVP_MD *type)
+{
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
+ EVP_MD_CTX_cleanup(&ctx);
+ return 0;
+ }
+ return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+}
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
- X509_ALGOR *algor1, X509_ALGOR *algor2,
- ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
- {
- EVP_PKEY *pkey;
- unsigned char *buf_in=NULL,*buf_out=NULL;
- size_t inl=0,outl=0,outll=0;
+ X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+{
+ EVP_PKEY *pkey;
+ unsigned char *buf_in = NULL, *buf_out = NULL;
+ size_t inl = 0, outl = 0, outll = 0;
- pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
- /* Write out the requested copies of the AlgorithmIdentifier. */
- if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1))
- {
- goto err;
- }
- if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2))
- {
- goto err;
- }
+ /* Write out the requested copies of the AlgorithmIdentifier. */
+ if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) {
+ goto err;
+ }
+ if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) {
+ goto err;
+ }
- inl=ASN1_item_i2d(asn,&buf_in, it);
- outll=outl=EVP_PKEY_size(pkey);
- buf_out=OPENSSL_malloc((unsigned int)outl);
- if ((buf_in == NULL) || (buf_out == NULL))
- {
- outl=0;
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ inl = ASN1_item_i2d(asn, &buf_in, it);
+ outll = outl = EVP_PKEY_size(pkey);
+ buf_out = OPENSSL_malloc((unsigned int)outl);
+ if ((buf_in == NULL) || (buf_out == NULL)) {
+ outl = 0;
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
- || !EVP_DigestSignFinal(ctx, buf_out, &outl))
- {
- outl=0;
- OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
- goto err;
- }
- if (signature->data != NULL) OPENSSL_free(signature->data);
- signature->data=buf_out;
- buf_out=NULL;
- signature->length=outl;
- /* In the interests of compatibility, I'll make sure that
- * the bit string has a 'not-used bits' value of 0
- */
- signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
- signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
-err:
- EVP_MD_CTX_cleanup(ctx);
- if (buf_in != NULL)
- { OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
- if (buf_out != NULL)
- { OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
- return(outl);
- }
+ if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
+ || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
+ outl = 0;
+ OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (signature->data != NULL)
+ OPENSSL_free(signature->data);
+ signature->data = buf_out;
+ buf_out = NULL;
+ signature->length = outl;
+ /*
+ * In the interests of compatibility, I'll make sure that the bit string
+ * has a 'not-used bits' value of 0
+ */
+ signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ err:
+ EVP_MD_CTX_cleanup(ctx);
+ if (buf_in != NULL) {
+ OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
+ OPENSSL_free(buf_in);
+ }
+ if (buf_out != NULL) {
+ OPENSSL_cleanse((char *)buf_out, outll);
+ OPENSSL_free(buf_out);
+ }
+ return (outl);
+}
diff --git a/src/crypto/x509/a_strex.c b/src/crypto/x509/a_strex.c
index b194d180..aa2501a4 100644
--- a/src/crypto/x509/a_strex.c
+++ b/src/crypto/x509/a_strex.c
@@ -64,501 +64,570 @@
#include "charmap.h"
-
-/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
- * Enhanced string and name printing routines handling
- * multibyte characters, RFC2253 and a host of other
- * options.
+/*
+ * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
+ * printing routines handling multibyte characters, RFC2253 and a host of
+ * other options.
*/
-
-#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
+#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
- ASN1_STRFLGS_ESC_QUOTE | \
- ASN1_STRFLGS_ESC_CTRL | \
- ASN1_STRFLGS_ESC_MSB)
-
+ ASN1_STRFLGS_ESC_QUOTE | \
+ ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB)
static int send_bio_chars(void *arg, const void *buf, int len)
{
- if(!arg) return 1;
- if(BIO_write(arg, buf, len) != len) return 0;
- return 1;
+ if (!arg)
+ return 1;
+ if (BIO_write(arg, buf, len) != len)
+ return 0;
+ return 1;
}
static int send_fp_chars(void *arg, const void *buf, int len)
{
- if(!arg) return 1;
- if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0;
- return 1;
+ if (!arg)
+ return 1;
+ if (fwrite(buf, 1, len, arg) != (unsigned int)len)
+ return 0;
+ return 1;
}
-typedef int char_io(void *arg, const void *buf, int len);
+typedef int char_io (void *arg, const void *buf, int len);
-/* This function handles display of
- * strings, one character at a time.
- * It is passed an unsigned long for each
- * character because it could come from 2 or even
- * 4 byte forms.
+/*
+ * This function handles display of strings, one character at a time. It is
+ * passed an unsigned long for each character because it could come from 2 or
+ * even 4 byte forms.
*/
#define HEX_SIZE(type) (sizeof(type)*2)
-static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg)
+static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
+ char_io *io_ch, void *arg)
{
- unsigned char chflgs, chtmp;
- char tmphex[HEX_SIZE(long)+3];
-
- if(c > 0xffffffffL)
- return -1;
- if(c > 0xffff) {
- BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
- if(!io_ch(arg, tmphex, 10)) return -1;
- return 10;
- }
- if(c > 0xff) {
- BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
- if(!io_ch(arg, tmphex, 6)) return -1;
- return 6;
- }
- chtmp = (unsigned char)c;
- if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB;
- else chflgs = char_type[chtmp] & flags;
- if(chflgs & CHARTYPE_BS_ESC) {
- /* If we don't escape with quotes, signal we need quotes */
- if(chflgs & ASN1_STRFLGS_ESC_QUOTE) {
- if(do_quotes) *do_quotes = 1;
- if(!io_ch(arg, &chtmp, 1)) return -1;
- return 1;
- }
- if(!io_ch(arg, "\\", 1)) return -1;
- if(!io_ch(arg, &chtmp, 1)) return -1;
- return 2;
- }
- if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
- BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
- if(!io_ch(arg, tmphex, 3)) return -1;
- return 3;
- }
- /* If we get this far and do any escaping at all must escape
- * the escape character itself: backslash.
- */
- if (chtmp == '\\' && flags & ESC_FLAGS) {
- if(!io_ch(arg, "\\\\", 2)) return -1;
- return 2;
- }
- if(!io_ch(arg, &chtmp, 1)) return -1;
- return 1;
+ unsigned char chflgs, chtmp;
+ char tmphex[HEX_SIZE(long) + 3];
+
+ if (c > 0xffffffffL)
+ return -1;
+ if (c > 0xffff) {
+ BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+ if (!io_ch(arg, tmphex, 10))
+ return -1;
+ return 10;
+ }
+ if (c > 0xff) {
+ BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
+ if (!io_ch(arg, tmphex, 6))
+ return -1;
+ return 6;
+ }
+ chtmp = (unsigned char)c;
+ if (chtmp > 0x7f)
+ chflgs = flags & ASN1_STRFLGS_ESC_MSB;
+ else
+ chflgs = char_type[chtmp] & flags;
+ if (chflgs & CHARTYPE_BS_ESC) {
+ /* If we don't escape with quotes, signal we need quotes */
+ if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
+ if (do_quotes)
+ *do_quotes = 1;
+ if (!io_ch(arg, &chtmp, 1))
+ return -1;
+ return 1;
+ }
+ if (!io_ch(arg, "\\", 1))
+ return -1;
+ if (!io_ch(arg, &chtmp, 1))
+ return -1;
+ return 2;
+ }
+ if (chflgs & (ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB)) {
+ BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
+ if (!io_ch(arg, tmphex, 3))
+ return -1;
+ return 3;
+ }
+ /*
+ * If we get this far and do any escaping at all must escape the escape
+ * character itself: backslash.
+ */
+ if (chtmp == '\\' && flags & ESC_FLAGS) {
+ if (!io_ch(arg, "\\\\", 2))
+ return -1;
+ return 2;
+ }
+ if (!io_ch(arg, &chtmp, 1))
+ return -1;
+ return 1;
}
-#define BUF_TYPE_WIDTH_MASK 0x7
-#define BUF_TYPE_CONVUTF8 0x8
+#define BUF_TYPE_WIDTH_MASK 0x7
+#define BUF_TYPE_CONVUTF8 0x8
-/* This function sends each character in a buffer to
- * do_esc_char(). It interprets the content formats
- * and converts to or from UTF8 as appropriate.
+/*
+ * This function sends each character in a buffer to do_esc_char(). It
+ * interprets the content formats and converts to or from UTF8 as
+ * appropriate.
*/
static int do_buf(unsigned char *buf, int buflen,
- int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg)
+ int type, unsigned char flags, char *quotes, char_io *io_ch,
+ void *arg)
{
- int i, outlen, len;
- unsigned char orflags, *p, *q;
- unsigned long c;
- p = buf;
- q = buf + buflen;
- outlen = 0;
- while(p != q) {
- if(p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253;
- else orflags = 0;
- switch(type & BUF_TYPE_WIDTH_MASK) {
- case 4:
- c = ((unsigned long)*p++) << 24;
- c |= ((unsigned long)*p++) << 16;
- c |= ((unsigned long)*p++) << 8;
- c |= *p++;
- break;
-
- case 2:
- c = ((unsigned long)*p++) << 8;
- c |= *p++;
- break;
-
- case 1:
- c = *p++;
- break;
-
- case 0:
- i = UTF8_getc(p, buflen, &c);
- if(i < 0) return -1; /* Invalid UTF8String */
- p += i;
- break;
- default:
- return -1; /* invalid width */
- }
- if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253;
- if(type & BUF_TYPE_CONVUTF8) {
- unsigned char utfbuf[6];
- int utflen;
- utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
- for(i = 0; i < utflen; i++) {
- /* We don't need to worry about setting orflags correctly
- * because if utflen==1 its value will be correct anyway
- * otherwise each character will be > 0x7f and so the
- * character will never be escaped on first and last.
- */
- len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg);
- if(len < 0) return -1;
- outlen += len;
- }
- } else {
- len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg);
- if(len < 0) return -1;
- outlen += len;
- }
- }
- return outlen;
+ int i, outlen, len;
+ unsigned char orflags, *p, *q;
+ unsigned long c;
+ p = buf;
+ q = buf + buflen;
+ outlen = 0;
+ while (p != q) {
+ if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
+ orflags = CHARTYPE_FIRST_ESC_2253;
+ else
+ orflags = 0;
+ switch (type & BUF_TYPE_WIDTH_MASK) {
+ case 4:
+ c = ((unsigned long)*p++) << 24;
+ c |= ((unsigned long)*p++) << 16;
+ c |= ((unsigned long)*p++) << 8;
+ c |= *p++;
+ break;
+
+ case 2:
+ c = ((unsigned long)*p++) << 8;
+ c |= *p++;
+ break;
+
+ case 1:
+ c = *p++;
+ break;
+
+ case 0:
+ i = UTF8_getc(p, buflen, &c);
+ if (i < 0)
+ return -1; /* Invalid UTF8String */
+ p += i;
+ break;
+ default:
+ return -1; /* invalid width */
+ }
+ if (p == q && flags & ASN1_STRFLGS_ESC_2253)
+ orflags = CHARTYPE_LAST_ESC_2253;
+ if (type & BUF_TYPE_CONVUTF8) {
+ unsigned char utfbuf[6];
+ int utflen;
+ utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
+ for (i = 0; i < utflen; i++) {
+ /*
+ * We don't need to worry about setting orflags correctly
+ * because if utflen==1 its value will be correct anyway
+ * otherwise each character will be > 0x7f and so the
+ * character will never be escaped on first and last.
+ */
+ len =
+ do_esc_char(utfbuf[i], (unsigned char)(flags | orflags),
+ quotes, io_ch, arg);
+ if (len < 0)
+ return -1;
+ outlen += len;
+ }
+ } else {
+ len =
+ do_esc_char(c, (unsigned char)(flags | orflags), quotes,
+ io_ch, arg);
+ if (len < 0)
+ return -1;
+ outlen += len;
+ }
+ }
+ return outlen;
}
/* This function hex dumps a buffer of characters */
-static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
+static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
+ int buflen)
{
- static const char hexdig[] = "0123456789ABCDEF";
- unsigned char *p, *q;
- char hextmp[2];
- if(arg) {
- p = buf;
- q = buf + buflen;
- while(p != q) {
- hextmp[0] = hexdig[*p >> 4];
- hextmp[1] = hexdig[*p & 0xf];
- if(!io_ch(arg, hextmp, 2)) return -1;
- p++;
- }
- }
- return buflen << 1;
+ static const char hexdig[] = "0123456789ABCDEF";
+ unsigned char *p, *q;
+ char hextmp[2];
+ if (arg) {
+ p = buf;
+ q = buf + buflen;
+ while (p != q) {
+ hextmp[0] = hexdig[*p >> 4];
+ hextmp[1] = hexdig[*p & 0xf];
+ if (!io_ch(arg, hextmp, 2))
+ return -1;
+ p++;
+ }
+ }
+ return buflen << 1;
}
-/* "dump" a string. This is done when the type is unknown,
- * or the flags request it. We can either dump the content
- * octets or the entire DER encoding. This uses the RFC2253
- * #01234 format.
+/*
+ * "dump" a string. This is done when the type is unknown, or the flags
+ * request it. We can either dump the content octets or the entire DER
+ * encoding. This uses the RFC2253 #01234 format.
*/
-static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
+static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
+ ASN1_STRING *str)
{
- /* Placing the ASN1_STRING in a temp ASN1_TYPE allows
- * the DER encoding to readily obtained
- */
- ASN1_TYPE t;
- unsigned char *der_buf, *p;
- int outlen, der_len;
-
- if(!io_ch(arg, "#", 1)) return -1;
- /* If we don't dump DER encoding just dump content octets */
- if(!(lflags & ASN1_STRFLGS_DUMP_DER)) {
- outlen = do_hex_dump(io_ch, arg, str->data, str->length);
- if(outlen < 0) return -1;
- return outlen + 1;
- }
- t.type = str->type;
- t.value.ptr = (char *)str;
- der_len = i2d_ASN1_TYPE(&t, NULL);
- der_buf = OPENSSL_malloc(der_len);
- if(!der_buf) return -1;
- p = der_buf;
- i2d_ASN1_TYPE(&t, &p);
- outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
- OPENSSL_free(der_buf);
- if(outlen < 0) return -1;
- return outlen + 1;
+ /*
+ * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
+ * readily obtained
+ */
+ ASN1_TYPE t;
+ unsigned char *der_buf, *p;
+ int outlen, der_len;
+
+ if (!io_ch(arg, "#", 1))
+ return -1;
+ /* If we don't dump DER encoding just dump content octets */
+ if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
+ outlen = do_hex_dump(io_ch, arg, str->data, str->length);
+ if (outlen < 0)
+ return -1;
+ return outlen + 1;
+ }
+ t.type = str->type;
+ t.value.ptr = (char *)str;
+ der_len = i2d_ASN1_TYPE(&t, NULL);
+ der_buf = OPENSSL_malloc(der_len);
+ if (!der_buf)
+ return -1;
+ p = der_buf;
+ i2d_ASN1_TYPE(&t, &p);
+ outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
+ OPENSSL_free(der_buf);
+ if (outlen < 0)
+ return -1;
+ return outlen + 1;
}
-/* Lookup table to convert tags to character widths,
- * 0 = UTF8 encoded, -1 is used for non string types
- * otherwise it is the number of bytes per character
+/*
+ * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
+ * used for non string types otherwise it is the number of bytes per
+ * character
*/
static const signed char tag2nbyte[] = {
- -1, -1, -1, -1, -1, /* 0-4 */
- -1, -1, -1, -1, -1, /* 5-9 */
- -1, -1, 0, -1, /* 10-13 */
- -1, -1, -1, -1, /* 15-17 */
- -1, 1, 1, /* 18-20 */
- -1, 1, 1, 1, /* 21-24 */
- -1, 1, -1, /* 25-27 */
- 4, -1, 2 /* 28-30 */
+ -1, -1, -1, -1, -1, /* 0-4 */
+ -1, -1, -1, -1, -1, /* 5-9 */
+ -1, -1, 0, -1, /* 10-13 */
+ -1, -1, -1, -1, /* 15-17 */
+ -1, 1, 1, /* 18-20 */
+ -1, 1, 1, 1, /* 21-24 */
+ -1, 1, -1, /* 25-27 */
+ 4, -1, 2 /* 28-30 */
};
-/* This is the main function, print out an
- * ASN1_STRING taking note of various escape
- * and display options. Returns number of
- * characters written or -1 if an error
- * occurred.
+/*
+ * This is the main function, print out an ASN1_STRING taking note of various
+ * escape and display options. Returns number of characters written or -1 if
+ * an error occurred.
*/
-static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str)
+static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
+ ASN1_STRING *str)
{
- int outlen, len;
- int type;
- char quotes;
- unsigned char flags;
- quotes = 0;
- /* Keep a copy of escape flags */
- flags = (unsigned char)(lflags & ESC_FLAGS);
-
- type = str->type;
-
- outlen = 0;
-
-
- if(lflags & ASN1_STRFLGS_SHOW_TYPE) {
- const char *tagname;
- tagname = ASN1_tag2str(type);
- outlen += strlen(tagname);
- if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1;
- outlen++;
- }
-
- /* Decide what to do with type, either dump content or display it */
-
- /* Dump everything */
- if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1;
- /* Ignore the string type */
- else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1;
- else {
- /* Else determine width based on type */
- if((type > 0) && (type < 31)) type = tag2nbyte[type];
- else type = -1;
- if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1;
- }
-
- if(type == -1) {
- len = do_dump(lflags, io_ch, arg, str);
- if(len < 0) return -1;
- outlen += len;
- return outlen;
- }
-
- if(lflags & ASN1_STRFLGS_UTF8_CONVERT) {
- /* Note: if string is UTF8 and we want
- * to convert to UTF8 then we just interpret
- * it as 1 byte per character to avoid converting
- * twice.
- */
- if(!type) type = 1;
- else type |= BUF_TYPE_CONVUTF8;
- }
-
- len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
- if(len < 0) return -1;
- outlen += len;
- if(quotes) outlen += 2;
- if(!arg) return outlen;
- if(quotes && !io_ch(arg, "\"", 1)) return -1;
- if(do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
- return -1;
- if(quotes && !io_ch(arg, "\"", 1)) return -1;
- return outlen;
+ int outlen, len;
+ int type;
+ char quotes;
+ unsigned char flags;
+ quotes = 0;
+ /* Keep a copy of escape flags */
+ flags = (unsigned char)(lflags & ESC_FLAGS);
+
+ type = str->type;
+
+ outlen = 0;
+
+ if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
+ const char *tagname;
+ tagname = ASN1_tag2str(type);
+ outlen += strlen(tagname);
+ if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
+ return -1;
+ outlen++;
+ }
+
+ /* Decide what to do with type, either dump content or display it */
+
+ /* Dump everything */
+ if (lflags & ASN1_STRFLGS_DUMP_ALL)
+ type = -1;
+ /* Ignore the string type */
+ else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
+ type = 1;
+ else {
+ /* Else determine width based on type */
+ if ((type > 0) && (type < 31))
+ type = tag2nbyte[type];
+ else
+ type = -1;
+ if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
+ type = 1;
+ }
+
+ if (type == -1) {
+ len = do_dump(lflags, io_ch, arg, str);
+ if (len < 0)
+ return -1;
+ outlen += len;
+ return outlen;
+ }
+
+ if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
+ /*
+ * Note: if string is UTF8 and we want to convert to UTF8 then we
+ * just interpret it as 1 byte per character to avoid converting
+ * twice.
+ */
+ if (!type)
+ type = 1;
+ else
+ type |= BUF_TYPE_CONVUTF8;
+ }
+
+ len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
+ if (len < 0)
+ return -1;
+ outlen += len;
+ if (quotes)
+ outlen += 2;
+ if (!arg)
+ return outlen;
+ if (quotes && !io_ch(arg, "\"", 1))
+ return -1;
+ if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
+ return -1;
+ if (quotes && !io_ch(arg, "\"", 1))
+ return -1;
+ return outlen;
}
/* Used for line indenting: print 'indent' spaces */
static int do_indent(char_io *io_ch, void *arg, int indent)
{
- int i;
- for(i = 0; i < indent; i++)
- if(!io_ch(arg, " ", 1)) return 0;
- return 1;
+ int i;
+ for (i = 0; i < indent; i++)
+ if (!io_ch(arg, " ", 1))
+ return 0;
+ return 1;
}
-#define FN_WIDTH_LN 25
-#define FN_WIDTH_SN 10
+#define FN_WIDTH_LN 25
+#define FN_WIDTH_SN 10
static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
- int indent, unsigned long flags)
+ int indent, unsigned long flags)
{
- int i, prev = -1, orflags, cnt;
- int fn_opt, fn_nid;
- ASN1_OBJECT *fn;
- ASN1_STRING *val;
- X509_NAME_ENTRY *ent;
- char objtmp[80];
- const char *objbuf;
- int outlen, len;
- const char *sep_dn, *sep_mv, *sep_eq;
- int sep_dn_len, sep_mv_len, sep_eq_len;
- if(indent < 0) indent = 0;
- outlen = indent;
- if(!do_indent(io_ch, arg, indent)) return -1;
- switch (flags & XN_FLAG_SEP_MASK)
- {
- case XN_FLAG_SEP_MULTILINE:
- sep_dn = "\n";
- sep_dn_len = 1;
- sep_mv = " + ";
- sep_mv_len = 3;
- break;
-
- case XN_FLAG_SEP_COMMA_PLUS:
- sep_dn = ",";
- sep_dn_len = 1;
- sep_mv = "+";
- sep_mv_len = 1;
- indent = 0;
- break;
-
- case XN_FLAG_SEP_CPLUS_SPC:
- sep_dn = ", ";
- sep_dn_len = 2;
- sep_mv = " + ";
- sep_mv_len = 3;
- indent = 0;
- break;
-
- case XN_FLAG_SEP_SPLUS_SPC:
- sep_dn = "; ";
- sep_dn_len = 2;
- sep_mv = " + ";
- sep_mv_len = 3;
- indent = 0;
- break;
-
- default:
- return -1;
- }
-
- if(flags & XN_FLAG_SPC_EQ) {
- sep_eq = " = ";
- sep_eq_len = 3;
- } else {
- sep_eq = "=";
- sep_eq_len = 1;
- }
-
- fn_opt = flags & XN_FLAG_FN_MASK;
-
- cnt = X509_NAME_entry_count(n);
- for(i = 0; i < cnt; i++) {
- if(flags & XN_FLAG_DN_REV)
- ent = X509_NAME_get_entry(n, cnt - i - 1);
- else ent = X509_NAME_get_entry(n, i);
- if(prev != -1) {
- if(prev == ent->set) {
- if(!io_ch(arg, sep_mv, sep_mv_len)) return -1;
- outlen += sep_mv_len;
- } else {
- if(!io_ch(arg, sep_dn, sep_dn_len)) return -1;
- outlen += sep_dn_len;
- if(!do_indent(io_ch, arg, indent)) return -1;
- outlen += indent;
- }
- }
- prev = ent->set;
- fn = X509_NAME_ENTRY_get_object(ent);
- val = X509_NAME_ENTRY_get_data(ent);
- fn_nid = OBJ_obj2nid(fn);
- if(fn_opt != XN_FLAG_FN_NONE) {
- int objlen, fld_len;
- if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) {
- OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
- fld_len = 0; /* XXX: what should this be? */
- objbuf = objtmp;
- } else {
- if(fn_opt == XN_FLAG_FN_SN) {
- fld_len = FN_WIDTH_SN;
- objbuf = OBJ_nid2sn(fn_nid);
- } else if(fn_opt == XN_FLAG_FN_LN) {
- fld_len = FN_WIDTH_LN;
- objbuf = OBJ_nid2ln(fn_nid);
- } else {
- fld_len = 0; /* XXX: what should this be? */
- objbuf = "";
- }
- }
- objlen = strlen(objbuf);
- if(!io_ch(arg, objbuf, objlen)) return -1;
- if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
- if (!do_indent(io_ch, arg, fld_len - objlen)) return -1;
- outlen += fld_len - objlen;
- }
- if(!io_ch(arg, sep_eq, sep_eq_len)) return -1;
- outlen += objlen + sep_eq_len;
- }
- /* If the field name is unknown then fix up the DER dump
- * flag. We might want to limit this further so it will
- * DER dump on anything other than a few 'standard' fields.
- */
- if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
- orflags = ASN1_STRFLGS_DUMP_ALL;
- else orflags = 0;
-
- len = do_print_ex(io_ch, arg, flags | orflags, val);
- if(len < 0) return -1;
- outlen += len;
- }
- return outlen;
+ int i, prev = -1, orflags, cnt;
+ int fn_opt, fn_nid;
+ ASN1_OBJECT *fn;
+ ASN1_STRING *val;
+ X509_NAME_ENTRY *ent;
+ char objtmp[80];
+ const char *objbuf;
+ int outlen, len;
+ const char *sep_dn, *sep_mv, *sep_eq;
+ int sep_dn_len, sep_mv_len, sep_eq_len;
+ if (indent < 0)
+ indent = 0;
+ outlen = indent;
+ if (!do_indent(io_ch, arg, indent))
+ return -1;
+ switch (flags & XN_FLAG_SEP_MASK) {
+ case XN_FLAG_SEP_MULTILINE:
+ sep_dn = "\n";
+ sep_dn_len = 1;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ break;
+
+ case XN_FLAG_SEP_COMMA_PLUS:
+ sep_dn = ",";
+ sep_dn_len = 1;
+ sep_mv = "+";
+ sep_mv_len = 1;
+ indent = 0;
+ break;
+
+ case XN_FLAG_SEP_CPLUS_SPC:
+ sep_dn = ", ";
+ sep_dn_len = 2;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ indent = 0;
+ break;
+
+ case XN_FLAG_SEP_SPLUS_SPC:
+ sep_dn = "; ";
+ sep_dn_len = 2;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ indent = 0;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (flags & XN_FLAG_SPC_EQ) {
+ sep_eq = " = ";
+ sep_eq_len = 3;
+ } else {
+ sep_eq = "=";
+ sep_eq_len = 1;
+ }
+
+ fn_opt = flags & XN_FLAG_FN_MASK;
+
+ cnt = X509_NAME_entry_count(n);
+ for (i = 0; i < cnt; i++) {
+ if (flags & XN_FLAG_DN_REV)
+ ent = X509_NAME_get_entry(n, cnt - i - 1);
+ else
+ ent = X509_NAME_get_entry(n, i);
+ if (prev != -1) {
+ if (prev == ent->set) {
+ if (!io_ch(arg, sep_mv, sep_mv_len))
+ return -1;
+ outlen += sep_mv_len;
+ } else {
+ if (!io_ch(arg, sep_dn, sep_dn_len))
+ return -1;
+ outlen += sep_dn_len;
+ if (!do_indent(io_ch, arg, indent))
+ return -1;
+ outlen += indent;
+ }
+ }
+ prev = ent->set;
+ fn = X509_NAME_ENTRY_get_object(ent);
+ val = X509_NAME_ENTRY_get_data(ent);
+ fn_nid = OBJ_obj2nid(fn);
+ if (fn_opt != XN_FLAG_FN_NONE) {
+ int objlen, fld_len;
+ if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
+ OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+ fld_len = 0; /* XXX: what should this be? */
+ objbuf = objtmp;
+ } else {
+ if (fn_opt == XN_FLAG_FN_SN) {
+ fld_len = FN_WIDTH_SN;
+ objbuf = OBJ_nid2sn(fn_nid);
+ } else if (fn_opt == XN_FLAG_FN_LN) {
+ fld_len = FN_WIDTH_LN;
+ objbuf = OBJ_nid2ln(fn_nid);
+ } else {
+ fld_len = 0; /* XXX: what should this be? */
+ objbuf = "";
+ }
+ }
+ objlen = strlen(objbuf);
+ if (!io_ch(arg, objbuf, objlen))
+ return -1;
+ if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
+ if (!do_indent(io_ch, arg, fld_len - objlen))
+ return -1;
+ outlen += fld_len - objlen;
+ }
+ if (!io_ch(arg, sep_eq, sep_eq_len))
+ return -1;
+ outlen += objlen + sep_eq_len;
+ }
+ /*
+ * If the field name is unknown then fix up the DER dump flag. We
+ * might want to limit this further so it will DER dump on anything
+ * other than a few 'standard' fields.
+ */
+ if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
+ orflags = ASN1_STRFLGS_DUMP_ALL;
+ else
+ orflags = 0;
+
+ len = do_print_ex(io_ch, arg, flags | orflags, val);
+ if (len < 0)
+ return -1;
+ outlen += len;
+ }
+ return outlen;
}
/* Wrappers round the main functions */
-int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags)
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent,
+ unsigned long flags)
{
- if(flags == XN_FLAG_COMPAT)
- return X509_NAME_print(out, nm, indent);
- return do_name_ex(send_bio_chars, out, nm, indent, flags);
+ if (flags == XN_FLAG_COMPAT)
+ return X509_NAME_print(out, nm, indent);
+ return do_name_ex(send_bio_chars, out, nm, indent, flags);
}
#ifndef OPENSSL_NO_FP_API
-int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags)
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent,
+ unsigned long flags)
{
- if(flags == XN_FLAG_COMPAT)
- {
- BIO *btmp;
- int ret;
- btmp = BIO_new_fp(fp, BIO_NOCLOSE);
- if(!btmp) return -1;
- ret = X509_NAME_print(btmp, nm, indent);
- BIO_free(btmp);
- return ret;
- }
- return do_name_ex(send_fp_chars, fp, nm, indent, flags);
+ if (flags == XN_FLAG_COMPAT) {
+ BIO *btmp;
+ int ret;
+ btmp = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (!btmp)
+ return -1;
+ ret = X509_NAME_print(btmp, nm, indent);
+ BIO_free(btmp);
+ return ret;
+ }
+ return do_name_ex(send_fp_chars, fp, nm, indent, flags);
}
#endif
int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
{
- return do_print_ex(send_bio_chars, out, flags, str);
+ return do_print_ex(send_bio_chars, out, flags, str);
}
#ifndef OPENSSL_NO_FP_API
int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
{
- return do_print_ex(send_fp_chars, fp, flags, str);
+ return do_print_ex(send_fp_chars, fp, flags, str);
}
#endif
-/* Utility function: convert any string type to UTF8, returns number of bytes
+/*
+ * Utility function: convert any string type to UTF8, returns number of bytes
* in output string or a negative error code
*/
int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
{
- ASN1_STRING stmp, *str = &stmp;
- int mbflag, type, ret;
- if(!in) return -1;
- type = in->type;
- if((type < 0) || (type > 30)) return -1;
- mbflag = tag2nbyte[type];
- if(mbflag == -1) return -1;
- mbflag |= MBSTRING_FLAG;
- stmp.data = NULL;
- stmp.length = 0;
- stmp.flags = 0;
- ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
- if(ret < 0) return ret;
- *out = stmp.data;
- return stmp.length;
+ ASN1_STRING stmp, *str = &stmp;
+ int mbflag, type, ret;
+ if (!in)
+ return -1;
+ type = in->type;
+ if ((type < 0) || (type > 30))
+ return -1;
+ mbflag = tag2nbyte[type];
+ if (mbflag == -1)
+ return -1;
+ mbflag |= MBSTRING_FLAG;
+ stmp.data = NULL;
+ stmp.length = 0;
+ stmp.flags = 0;
+ ret =
+ ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
+ B_ASN1_UTF8STRING);
+ if (ret < 0)
+ return ret;
+ *out = stmp.data;
+ return stmp.length;
}
diff --git a/src/crypto/x509/a_verify.c b/src/crypto/x509/a_verify.c
index 572a1392..5a9adb65 100644
--- a/src/crypto/x509/a_verify.c
+++ b/src/crypto/x509/a_verify.c
@@ -68,66 +68,60 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
-#include "../evp/internal.h"
-
+#include "internal.h"
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
- ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
- {
- EVP_MD_CTX ctx;
- uint8_t *buf_in = NULL;
- int ret = 0, inl;
+ ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+{
+ EVP_MD_CTX ctx;
+ uint8_t *buf_in = NULL;
+ int ret = 0, inl;
- if (!pkey)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
+ if (!pkey) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
- if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT);
- return 0;
- }
+ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT);
+ return 0;
+ }
- EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_init(&ctx);
- if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
- {
- goto err;
- }
+ if (!x509_digest_verify_init(&ctx, a, pkey)) {
+ goto err;
+ }
- inl = ASN1_item_i2d(asn, &buf_in, it);
-
- if (buf_in == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ inl = ASN1_item_i2d(asn, &buf_in, it);
- if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
- {
- OPENSSL_cleanse(buf_in,(unsigned int)inl);
- OPENSSL_free(buf_in);
- OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
- goto err;
- }
+ if (buf_in == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- OPENSSL_cleanse(buf_in,(unsigned int)inl);
- OPENSSL_free(buf_in);
+ if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) {
+ OPENSSL_cleanse(buf_in, (unsigned int)inl);
+ OPENSSL_free(buf_in);
+ OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+ goto err;
+ }
- if (EVP_DigestVerifyFinal(&ctx,signature->data,
- (size_t)signature->length) <= 0)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
- goto err;
- }
- /* we don't need to zero the 'ctx' because we just checked
- * public information */
- /* memset(&ctx,0,sizeof(ctx)); */
- ret = 1;
-err:
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
- }
+ OPENSSL_cleanse(buf_in, (unsigned int)inl);
+ OPENSSL_free(buf_in);
+ if (EVP_DigestVerifyFinal(&ctx, signature->data,
+ (size_t)signature->length) <= 0) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+ goto err;
+ }
+ /*
+ * we don't need to zero the 'ctx' because we just checked public
+ * information
+ */
+ /* memset(&ctx,0,sizeof(ctx)); */
+ ret = 1;
+ err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return ret;
+}
diff --git a/src/crypto/evp/algorithm.c b/src/crypto/x509/algorithm.c
index 63bc77af..78ae882b 100644
--- a/src/crypto/evp/algorithm.c
+++ b/src/crypto/x509/algorithm.c
@@ -54,100 +54,84 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
-#include <openssl/evp.h>
-
-#include <assert.h>
+#include <openssl/x509.h>
#include <openssl/asn1.h>
+#include <openssl/digest.h>
#include <openssl/err.h>
+#include <openssl/evp.h>
#include <openssl/obj.h>
-#include <openssl/x509.h>
#include "internal.h"
-int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
- const EVP_MD *digest;
- EVP_PKEY *pkey;
- int sign_nid, paramtype;
-
- digest = EVP_MD_CTX_md(ctx);
- pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
- if (!digest || !pkey) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_CONTEXT_NOT_INITIALISED);
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+ const EVP_MD *digest = EVP_MD_CTX_md(ctx);
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ if (digest == NULL || pkey == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
return 0;
}
- if (pkey->ameth->digest_sign_algorithm) {
- switch (pkey->ameth->digest_sign_algorithm(ctx, algor)) {
- case EVP_DIGEST_SIGN_ALGORITHM_ERROR:
- return 0;
- case EVP_DIGEST_SIGN_ALGORITHM_SUCCESS:
- return 1;
- case EVP_DIGEST_SIGN_ALGORITHM_DEFAULT:
- /* Use default behavior. */
- break;
- default:
- assert(0);
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+ int pad_mode;
+ if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) {
+ return 0;
+ }
+ /* RSA-PSS has special signature algorithm logic. */
+ if (pad_mode == RSA_PKCS1_PSS_PADDING) {
+ return x509_rsa_ctx_to_pss(ctx, algor);
}
}
/* Default behavior: look up the OID for the algorithm/hash pair and encode
* that. */
+ int sign_nid;
if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
- pkey->ameth->pkey_id)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+ EVP_PKEY_id(pkey))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
return 0;
}
- if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) {
- paramtype = V_ASN1_NULL;
- } else {
- paramtype = V_ASN1_UNDEF;
- }
-
+ /* RSA signature algorithms include an explicit NULL parameter. Others omit
+ * it. */
+ int paramtype =
+ (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF;
X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
return 1;
}
-int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
- X509_ALGOR *algor,
- EVP_PKEY *pkey) {
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+ EVP_PKEY *pkey) {
+ /* Convert the signature OID into digest and public key OIDs. */
+ int sigalg_nid = OBJ_obj2nid(sigalg->algorithm);
int digest_nid, pkey_nid;
- const EVP_PKEY_ASN1_METHOD *ameth;
- const EVP_MD *digest;
-
- /* Convert signature OID into digest and public key OIDs */
- if (!OBJ_find_sigid_algs(OBJ_obj2nid(algor->algorithm), &digest_nid,
- &pkey_nid)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
return 0;
}
- /* Check public key OID matches public key type */
- ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
- if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_WRONG_PUBLIC_KEY_TYPE);
+ /* Check the public key OID matches the public key type. */
+ if (pkey_nid != EVP_PKEY_id(pkey)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
return 0;
}
/* NID_undef signals that there are custom parameters to set. */
if (digest_nid == NID_undef) {
- if (!pkey->ameth || !pkey->ameth->digest_verify_init_from_algorithm) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ if (sigalg_nid != NID_rsassaPss) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
return 0;
}
-
- return pkey->ameth->digest_verify_init_from_algorithm(ctx, algor, pkey);
+ return x509_rsa_pss_to_ctx(ctx, sigalg, pkey);
}
/* Otherwise, initialize with the digest from the OID. */
- digest = EVP_get_digestbynid(digest_nid);
+ const EVP_MD *digest = EVP_get_digestbynid(digest_nid);
if (digest == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
return 0;
}
return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
}
-
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
index 850a8167..03a0ab9f 100644
--- a/src/crypto/x509/asn1_gen.c
+++ b/src/crypto/x509/asn1_gen.c
@@ -66,808 +66,753 @@
#include "../internal.h"
+/*
+ * Although this file is in crypto/x509 for layering purposes, it emits
+ * errors from the ASN.1 module for OpenSSL compatibility.
+ */
-/* Although this file is in crypto/x509 for layering purposes, it emits errors
- * from the ASN.1 module for OpenSSL compatibility. */
+#define ASN1_GEN_FLAG 0x10000
+#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
+#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
+#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
+#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
+#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
+#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
+#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
+#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
-#define ASN1_GEN_FLAG 0x10000
-#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
-#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
-#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
-#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
-#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
-#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
-#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
-#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
+#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
-#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
-
-#define ASN1_FLAG_EXP_MAX 20
+#define ASN1_FLAG_EXP_MAX 20
/* Input formats */
/* ASCII: default */
-#define ASN1_GEN_FORMAT_ASCII 1
+#define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */
-#define ASN1_GEN_FORMAT_UTF8 2
+#define ASN1_GEN_FORMAT_UTF8 2
/* Hex */
-#define ASN1_GEN_FORMAT_HEX 3
+#define ASN1_GEN_FORMAT_HEX 3
/* List of bits */
-#define ASN1_GEN_FORMAT_BITLIST 4
-
-
-struct tag_name_st
- {
- const char *strnam;
- int len;
- int tag;
- };
-
-typedef struct
- {
- int exp_tag;
- int exp_class;
- int exp_constructed;
- int exp_pad;
- long exp_len;
- } tag_exp_type;
-
-typedef struct
- {
- int imp_tag;
- int imp_class;
- int utype;
- int format;
- const char *str;
- tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
- int exp_count;
- } tag_exp_arg;
+#define ASN1_GEN_FORMAT_BITLIST 4
+
+struct tag_name_st {
+ const char *strnam;
+ int len;
+ int tag;
+};
+
+typedef struct {
+ int exp_tag;
+ int exp_class;
+ int exp_constructed;
+ int exp_pad;
+ long exp_len;
+} tag_exp_type;
+
+typedef struct {
+ int imp_tag;
+ int imp_class;
+ int utype;
+ int format;
+ const char *str;
+ tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
+ int exp_count;
+} tag_exp_arg;
static int bitstr_cb(const char *elem, int len, void *bitstr);
static int asn1_cb(const char *elem, int len, void *bitstr);
-static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok);
-static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass);
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
+ int exp_constructed, int exp_pad, int imp_ok);
+static int parse_tagging(const char *vstart, int vlen, int *ptag,
+ int *pclass);
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
static int asn1_str2tag(const char *tagstr, int len);
ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
- {
- X509V3_CTX cnf;
+{
+ X509V3_CTX cnf;
- if (!nconf)
- return ASN1_generate_v3(str, NULL);
+ if (!nconf)
+ return ASN1_generate_v3(str, NULL);
- X509V3_set_nconf(&cnf, nconf);
- return ASN1_generate_v3(str, &cnf);
- }
+ X509V3_set_nconf(&cnf, nconf);
+ return ASN1_generate_v3(str, &cnf);
+}
ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
- {
- ASN1_TYPE *ret;
- tag_exp_arg asn1_tags;
- tag_exp_type *etmp;
-
- int i, len;
-
- unsigned char *orig_der = NULL, *new_der = NULL;
- const unsigned char *cpy_start;
- unsigned char *p;
- const unsigned char *cp;
- int cpy_len;
- long hdr_len;
- int hdr_constructed = 0, hdr_tag, hdr_class;
- int r;
-
- asn1_tags.imp_tag = -1;
- asn1_tags.imp_class = -1;
- asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
- asn1_tags.exp_count = 0;
- if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
- return NULL;
-
- if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET))
- {
- if (!cnf)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
- return NULL;
- }
- ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
- }
- else
- ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
-
- if (!ret)
- return NULL;
-
- /* If no tagging return base type */
- if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
- return ret;
-
- /* Generate the encoding */
- cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
- ASN1_TYPE_free(ret);
- ret = NULL;
- /* Set point to start copying for modified encoding */
- cpy_start = orig_der;
-
- /* Do we need IMPLICIT tagging? */
- if (asn1_tags.imp_tag != -1)
- {
- /* If IMPLICIT we will replace the underlying tag */
- /* Skip existing tag+len */
- r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len);
- if (r & 0x80)
- goto err;
- /* Update copy length */
- cpy_len -= cpy_start - orig_der;
- /* For IMPLICIT tagging the length should match the
- * original length and constructed flag should be
- * consistent.
- */
- if (r & 0x1)
- {
- /* Indefinite length constructed */
- hdr_constructed = 2;
- hdr_len = 0;
- }
- else
- /* Just retain constructed flag */
- hdr_constructed = r & V_ASN1_CONSTRUCTED;
- /* Work out new length with IMPLICIT tag: ignore constructed
- * because it will mess up if indefinite length
- */
- len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
- }
- else
- len = cpy_len;
-
- /* Work out length in any EXPLICIT, starting from end */
-
- for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--)
- {
- /* Content length: number of content octets + any padding */
- len += etmp->exp_pad;
- etmp->exp_len = len;
- /* Total object length: length including new header */
- len = ASN1_object_size(0, len, etmp->exp_tag);
- }
-
- /* Allocate buffer for new encoding */
-
- new_der = OPENSSL_malloc(len);
- if (!new_der)
- goto err;
-
- /* Generate tagged encoding */
-
- p = new_der;
-
- /* Output explicit tags first */
-
- for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++)
- {
- ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
- etmp->exp_tag, etmp->exp_class);
- if (etmp->exp_pad)
- *p++ = 0;
- }
-
- /* If IMPLICIT, output tag */
-
- if (asn1_tags.imp_tag != -1)
- {
- if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
- && (asn1_tags.imp_tag == V_ASN1_SEQUENCE
- || asn1_tags.imp_tag == V_ASN1_SET) )
- hdr_constructed = V_ASN1_CONSTRUCTED;
- ASN1_put_object(&p, hdr_constructed, hdr_len,
- asn1_tags.imp_tag, asn1_tags.imp_class);
- }
-
- /* Copy across original encoding */
- memcpy(p, cpy_start, cpy_len);
-
- cp = new_der;
-
- /* Obtain new ASN1_TYPE structure */
- ret = d2i_ASN1_TYPE(NULL, &cp, len);
-
- err:
- if (orig_der)
- OPENSSL_free(orig_der);
- if (new_der)
- OPENSSL_free(new_der);
-
- return ret;
-
- }
+{
+ ASN1_TYPE *ret;
+ tag_exp_arg asn1_tags;
+ tag_exp_type *etmp;
+
+ int i, len;
+
+ unsigned char *orig_der = NULL, *new_der = NULL;
+ const unsigned char *cpy_start;
+ unsigned char *p;
+ const unsigned char *cp;
+ int cpy_len;
+ long hdr_len = 0;
+ int hdr_constructed = 0, hdr_tag, hdr_class;
+ int r;
+
+ asn1_tags.imp_tag = -1;
+ asn1_tags.imp_class = -1;
+ asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
+ asn1_tags.exp_count = 0;
+ if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
+ return NULL;
+
+ if ((asn1_tags.utype == V_ASN1_SEQUENCE)
+ || (asn1_tags.utype == V_ASN1_SET)) {
+ if (!cnf) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+ return NULL;
+ }
+ ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
+ } else
+ ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
+
+ if (!ret)
+ return NULL;
+
+ /* If no tagging return base type */
+ if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
+ return ret;
+
+ /* Generate the encoding */
+ cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
+ ASN1_TYPE_free(ret);
+ ret = NULL;
+ /* Set point to start copying for modified encoding */
+ cpy_start = orig_der;
+
+ /* Do we need IMPLICIT tagging? */
+ if (asn1_tags.imp_tag != -1) {
+ /* If IMPLICIT we will replace the underlying tag */
+ /* Skip existing tag+len */
+ r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class,
+ cpy_len);
+ if (r & 0x80)
+ goto err;
+ /* Update copy length */
+ cpy_len -= cpy_start - orig_der;
+ /*
+ * For IMPLICIT tagging the length should match the original length
+ * and constructed flag should be consistent.
+ */
+ if (r & 0x1) {
+ /* Indefinite length constructed */
+ hdr_constructed = 2;
+ hdr_len = 0;
+ } else
+ /* Just retain constructed flag */
+ hdr_constructed = r & V_ASN1_CONSTRUCTED;
+ /*
+ * Work out new length with IMPLICIT tag: ignore constructed because
+ * it will mess up if indefinite length
+ */
+ len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
+ } else
+ len = cpy_len;
+
+ /* Work out length in any EXPLICIT, starting from end */
+
+ for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
+ i < asn1_tags.exp_count; i++, etmp--) {
+ /* Content length: number of content octets + any padding */
+ len += etmp->exp_pad;
+ etmp->exp_len = len;
+ /* Total object length: length including new header */
+ len = ASN1_object_size(0, len, etmp->exp_tag);
+ }
+
+ /* Allocate buffer for new encoding */
+
+ new_der = OPENSSL_malloc(len);
+ if (!new_der)
+ goto err;
+
+ /* Generate tagged encoding */
+
+ p = new_der;
+
+ /* Output explicit tags first */
+
+ for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
+ i++, etmp++) {
+ ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
+ etmp->exp_tag, etmp->exp_class);
+ if (etmp->exp_pad)
+ *p++ = 0;
+ }
+
+ /* If IMPLICIT, output tag */
+
+ if (asn1_tags.imp_tag != -1) {
+ if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
+ && (asn1_tags.imp_tag == V_ASN1_SEQUENCE
+ || asn1_tags.imp_tag == V_ASN1_SET))
+ hdr_constructed = V_ASN1_CONSTRUCTED;
+ ASN1_put_object(&p, hdr_constructed, hdr_len,
+ asn1_tags.imp_tag, asn1_tags.imp_class);
+ }
+
+ /* Copy across original encoding */
+ memcpy(p, cpy_start, cpy_len);
+
+ cp = new_der;
+
+ /* Obtain new ASN1_TYPE structure */
+ ret = d2i_ASN1_TYPE(NULL, &cp, len);
+
+ err:
+ if (orig_der)
+ OPENSSL_free(orig_der);
+ if (new_der)
+ OPENSSL_free(new_der);
+
+ return ret;
+
+}
static int asn1_cb(const char *elem, int len, void *bitstr)
- {
- tag_exp_arg *arg = bitstr;
- int i;
- int utype;
- int vlen = 0;
- const char *p, *vstart = NULL;
-
- int tmp_tag, tmp_class;
-
- if (elem == NULL)
- return 0;
-
- for(i = 0, p = elem; i < len; p++, i++)
- {
- /* Look for the ':' in name value pairs */
- if (*p == ':')
- {
- vstart = p + 1;
- vlen = len - (vstart - elem);
- len = p - elem;
- break;
- }
- }
-
- utype = asn1_str2tag(elem, len);
-
- if (utype == -1)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG);
- ERR_add_error_data(2, "tag=", elem);
- return -1;
- }
-
- /* If this is not a modifier mark end of string and exit */
- if (!(utype & ASN1_GEN_FLAG))
- {
- arg->utype = utype;
- arg->str = vstart;
- /* If no value and not end of string, error */
- if (!vstart && elem[len])
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
- return -1;
- }
- return 0;
- }
-
- switch(utype)
- {
-
- case ASN1_GEN_FLAG_IMP:
- /* Check for illegal multiple IMPLICIT tagging */
- if (arg->imp_tag != -1)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
- return -1;
- }
- if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_EXP:
-
- if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
- return -1;
- if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_SEQWRAP:
- if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_SETWRAP:
- if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_BITWRAP:
- if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_OCTWRAP:
- if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
- return -1;
- break;
-
- case ASN1_GEN_FLAG_FORMAT:
- if (!vstart)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
- return -1;
- }
- if (!strncmp(vstart, "ASCII", 5))
- arg->format = ASN1_GEN_FORMAT_ASCII;
- else if (!strncmp(vstart, "UTF8", 4))
- arg->format = ASN1_GEN_FORMAT_UTF8;
- else if (!strncmp(vstart, "HEX", 3))
- arg->format = ASN1_GEN_FORMAT_HEX;
- else if (!strncmp(vstart, "BITLIST", 7))
- arg->format = ASN1_GEN_FORMAT_BITLIST;
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
- return -1;
- }
- break;
-
- }
-
- return 1;
-
- }
+{
+ tag_exp_arg *arg = bitstr;
+ int i;
+ int utype;
+ int vlen = 0;
+ const char *p, *vstart = NULL;
+
+ int tmp_tag, tmp_class;
+
+ if (elem == NULL)
+ return 0;
+
+ for (i = 0, p = elem; i < len; p++, i++) {
+ /* Look for the ':' in name value pairs */
+ if (*p == ':') {
+ vstart = p + 1;
+ vlen = len - (vstart - elem);
+ len = p - elem;
+ break;
+ }
+ }
+
+ utype = asn1_str2tag(elem, len);
+
+ if (utype == -1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG);
+ ERR_add_error_data(2, "tag=", elem);
+ return -1;
+ }
+
+ /* If this is not a modifier mark end of string and exit */
+ if (!(utype & ASN1_GEN_FLAG)) {
+ arg->utype = utype;
+ arg->str = vstart;
+ /* If no value and not end of string, error */
+ if (!vstart && elem[len]) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
+ return -1;
+ }
+ return 0;
+ }
+
+ switch (utype) {
+
+ case ASN1_GEN_FLAG_IMP:
+ /* Check for illegal multiple IMPLICIT tagging */
+ if (arg->imp_tag != -1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
+ return -1;
+ }
+ if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_EXP:
+
+ if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
+ return -1;
+ if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_SEQWRAP:
+ if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_SETWRAP:
+ if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_BITWRAP:
+ if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_OCTWRAP:
+ if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_FORMAT:
+ if (!vstart) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+ if (!strncmp(vstart, "ASCII", 5))
+ arg->format = ASN1_GEN_FORMAT_ASCII;
+ else if (!strncmp(vstart, "UTF8", 4))
+ arg->format = ASN1_GEN_FORMAT_UTF8;
+ else if (!strncmp(vstart, "HEX", 3))
+ arg->format = ASN1_GEN_FORMAT_HEX;
+ else if (!strncmp(vstart, "BITLIST", 7))
+ arg->format = ASN1_GEN_FORMAT_BITLIST;
+ else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+ break;
+
+ }
+
+ return 1;
+
+}
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
- {
- char erch[2];
- long tag_num;
- char *eptr;
- if (!vstart)
- return 0;
- tag_num = strtoul(vstart, &eptr, 10);
- /* Check we haven't gone past max length: should be impossible */
- if (eptr && *eptr && (eptr > vstart + vlen))
- return 0;
- if (tag_num < 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
- return 0;
- }
- *ptag = tag_num;
- /* If we have non numeric characters, parse them */
- if (eptr)
- vlen -= eptr - vstart;
- else
- vlen = 0;
- if (vlen)
- {
- switch (*eptr)
- {
-
- case 'U':
- *pclass = V_ASN1_UNIVERSAL;
- break;
-
- case 'A':
- *pclass = V_ASN1_APPLICATION;
- break;
-
- case 'P':
- *pclass = V_ASN1_PRIVATE;
- break;
-
- case 'C':
- *pclass = V_ASN1_CONTEXT_SPECIFIC;
- break;
-
- default:
- erch[0] = *eptr;
- erch[1] = 0;
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER);
- ERR_add_error_data(2, "Char=", erch);
- return 0;
- break;
-
- }
- }
- else
- *pclass = V_ASN1_CONTEXT_SPECIFIC;
-
- return 1;
-
- }
+{
+ char erch[2];
+ long tag_num;
+ char *eptr;
+ if (!vstart)
+ return 0;
+ tag_num = strtoul(vstart, &eptr, 10);
+ /* Check we haven't gone past max length: should be impossible */
+ if (eptr && *eptr && (eptr > vstart + vlen))
+ return 0;
+ if (tag_num < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
+ return 0;
+ }
+ *ptag = tag_num;
+ /* If we have non numeric characters, parse them */
+ if (eptr)
+ vlen -= eptr - vstart;
+ else
+ vlen = 0;
+ if (vlen) {
+ switch (*eptr) {
+
+ case 'U':
+ *pclass = V_ASN1_UNIVERSAL;
+ break;
+
+ case 'A':
+ *pclass = V_ASN1_APPLICATION;
+ break;
+
+ case 'P':
+ *pclass = V_ASN1_PRIVATE;
+ break;
+
+ case 'C':
+ *pclass = V_ASN1_CONTEXT_SPECIFIC;
+ break;
+
+ default:
+ erch[0] = *eptr;
+ erch[1] = 0;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER);
+ ERR_add_error_data(2, "Char=", erch);
+ return 0;
+ break;
+
+ }
+ } else
+ *pclass = V_ASN1_CONTEXT_SPECIFIC;
+
+ return 1;
+
+}
/* Handle multiple types: SET and SEQUENCE */
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
- {
- ASN1_TYPE *ret = NULL;
- STACK_OF(ASN1_TYPE) *sk = NULL;
- STACK_OF(CONF_VALUE) *sect = NULL;
- unsigned char *der = NULL;
- int derlen;
- size_t i;
- sk = sk_ASN1_TYPE_new_null();
- if (!sk)
- goto bad;
- if (section)
- {
- if (!cnf)
- goto bad;
- sect = X509V3_get_section(cnf, (char *)section);
- if (!sect)
- goto bad;
- for (i = 0; i < sk_CONF_VALUE_num(sect); i++)
- {
- ASN1_TYPE *typ = ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
- if (!typ)
- goto bad;
- if (!sk_ASN1_TYPE_push(sk, typ))
- goto bad;
- }
- }
-
- /* Now we has a STACK of the components, convert to the correct form */
-
- if (utype == V_ASN1_SET)
- derlen = i2d_ASN1_SET_ANY(sk, &der);
- else
- derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
-
- if (derlen < 0)
- goto bad;
-
- if (!(ret = ASN1_TYPE_new()))
- goto bad;
-
- if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
- goto bad;
-
- ret->type = utype;
-
- ret->value.asn1_string->data = der;
- ret->value.asn1_string->length = derlen;
-
- der = NULL;
-
- bad:
-
- if (der)
- OPENSSL_free(der);
-
- if (sk)
- sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
- if (sect)
- X509V3_section_free(cnf, sect);
-
- return ret;
- }
-
-static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok)
- {
- tag_exp_type *exp_tmp;
- /* Can only have IMPLICIT if permitted */
- if ((arg->imp_tag != -1) && !imp_ok)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
- return 0;
- }
-
- if (arg->exp_count == ASN1_FLAG_EXP_MAX)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED);
- return 0;
- }
-
- exp_tmp = &arg->exp_list[arg->exp_count++];
-
- /* If IMPLICIT set tag to implicit value then
- * reset implicit tag since it has been used.
- */
- if (arg->imp_tag != -1)
- {
- exp_tmp->exp_tag = arg->imp_tag;
- exp_tmp->exp_class = arg->imp_class;
- arg->imp_tag = -1;
- arg->imp_class = -1;
- }
- else
- {
- exp_tmp->exp_tag = exp_tag;
- exp_tmp->exp_class = exp_class;
- }
- exp_tmp->exp_constructed = exp_constructed;
- exp_tmp->exp_pad = exp_pad;
-
- return 1;
- }
-
+{
+ ASN1_TYPE *ret = NULL;
+ STACK_OF(ASN1_TYPE) *sk = NULL;
+ STACK_OF(CONF_VALUE) *sect = NULL;
+ unsigned char *der = NULL;
+ int derlen;
+ size_t i;
+ sk = sk_ASN1_TYPE_new_null();
+ if (!sk)
+ goto bad;
+ if (section) {
+ if (!cnf)
+ goto bad;
+ sect = X509V3_get_section(cnf, (char *)section);
+ if (!sect)
+ goto bad;
+ for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
+ ASN1_TYPE *typ =
+ ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
+ if (!typ)
+ goto bad;
+ if (!sk_ASN1_TYPE_push(sk, typ))
+ goto bad;
+ }
+ }
+
+ /*
+ * Now we has a STACK of the components, convert to the correct form
+ */
+
+ if (utype == V_ASN1_SET)
+ derlen = i2d_ASN1_SET_ANY(sk, &der);
+ else
+ derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
+
+ if (derlen < 0)
+ goto bad;
+
+ if (!(ret = ASN1_TYPE_new()))
+ goto bad;
+
+ if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
+ goto bad;
+
+ ret->type = utype;
+
+ ret->value.asn1_string->data = der;
+ ret->value.asn1_string->length = derlen;
+
+ der = NULL;
+
+ bad:
+
+ if (der)
+ OPENSSL_free(der);
+
+ if (sk)
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ if (sect)
+ X509V3_section_free(cnf, sect);
+
+ return ret;
+}
+
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
+ int exp_constructed, int exp_pad, int imp_ok)
+{
+ tag_exp_type *exp_tmp;
+ /* Can only have IMPLICIT if permitted */
+ if ((arg->imp_tag != -1) && !imp_ok) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+ return 0;
+ }
+
+ if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED);
+ return 0;
+ }
+
+ exp_tmp = &arg->exp_list[arg->exp_count++];
+
+ /*
+ * If IMPLICIT set tag to implicit value then reset implicit tag since it
+ * has been used.
+ */
+ if (arg->imp_tag != -1) {
+ exp_tmp->exp_tag = arg->imp_tag;
+ exp_tmp->exp_class = arg->imp_class;
+ arg->imp_tag = -1;
+ arg->imp_class = -1;
+ } else {
+ exp_tmp->exp_tag = exp_tag;
+ exp_tmp->exp_class = exp_class;
+ }
+ exp_tmp->exp_constructed = exp_constructed;
+ exp_tmp->exp_pad = exp_pad;
+
+ return 1;
+}
static int asn1_str2tag(const char *tagstr, int len)
- {
- unsigned int i;
- static const struct tag_name_st *tntmp, tnst [] = {
- ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
- ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
- ASN1_GEN_STR("NULL", V_ASN1_NULL),
- ASN1_GEN_STR("INT", V_ASN1_INTEGER),
- ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
- ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
- ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
- ASN1_GEN_STR("OID", V_ASN1_OBJECT),
- ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
- ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
- ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
- ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
- ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
- ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
- ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
- ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
- ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
- ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
- ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
- ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
- ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
- ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
- ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
- ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
- ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
- ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
- ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
- ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
- ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
- ASN1_GEN_STR("T61", V_ASN1_T61STRING),
- ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
- ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
- ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
- ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
- ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
- ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
-
- /* Special cases */
- ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
- ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
- ASN1_GEN_STR("SET", V_ASN1_SET),
- /* type modifiers */
- /* Explicit tag */
- ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
- ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
- /* Implicit tag */
- ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
- ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
- /* OCTET STRING wrapper */
- ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
- /* SEQUENCE wrapper */
- ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
- /* SET wrapper */
- ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
- /* BIT STRING wrapper */
- ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
- ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
- ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
- };
-
- if (len == -1)
- len = strlen(tagstr);
-
- tntmp = tnst;
- for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++)
- {
- if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
- return tntmp->tag;
- }
-
- return -1;
- }
+{
+ unsigned int i;
+ static const struct tag_name_st *tntmp, tnst[] = {
+ ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
+ ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
+ ASN1_GEN_STR("NULL", V_ASN1_NULL),
+ ASN1_GEN_STR("INT", V_ASN1_INTEGER),
+ ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
+ ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
+ ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
+ ASN1_GEN_STR("OID", V_ASN1_OBJECT),
+ ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
+ ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
+ ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
+ ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
+ ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
+ ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
+ ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
+ ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
+ ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
+ ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
+ ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
+ ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
+ ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
+ ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
+ ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
+ ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
+ ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
+ ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
+ ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
+ ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
+ ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
+ ASN1_GEN_STR("T61", V_ASN1_T61STRING),
+ ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
+ ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
+ ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
+ ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
+ ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
+ ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
+
+ /* Special cases */
+ ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
+ ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
+ ASN1_GEN_STR("SET", V_ASN1_SET),
+ /* type modifiers */
+ /* Explicit tag */
+ ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
+ ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
+ /* Implicit tag */
+ ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
+ ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
+ /* OCTET STRING wrapper */
+ ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
+ /* SEQUENCE wrapper */
+ ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
+ /* SET wrapper */
+ ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
+ /* BIT STRING wrapper */
+ ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
+ ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
+ ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
+ };
+
+ if (len == -1)
+ len = strlen(tagstr);
+
+ tntmp = tnst;
+ for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) {
+ if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
+ return tntmp->tag;
+ }
+
+ return -1;
+}
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
- {
- ASN1_TYPE *atmp = NULL;
-
- CONF_VALUE vtmp;
-
- unsigned char *rdata;
- long rdlen;
-
- int no_unused = 1;
-
- if (!(atmp = ASN1_TYPE_new()))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (!str)
- str = "";
-
- switch(utype)
- {
-
- case V_ASN1_NULL:
- if (str && *str)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
- goto bad_form;
- }
- break;
-
- case V_ASN1_BOOLEAN:
- if (format != ASN1_GEN_FORMAT_ASCII)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT);
- goto bad_form;
- }
- vtmp.name = NULL;
- vtmp.section = NULL;
- vtmp.value = (char *)str;
- if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN);
- goto bad_str;
- }
- break;
-
- case V_ASN1_INTEGER:
- case V_ASN1_ENUMERATED:
- if (format != ASN1_GEN_FORMAT_ASCII)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
- goto bad_form;
- }
- if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER);
- goto bad_str;
- }
- break;
-
- case V_ASN1_OBJECT:
- if (format != ASN1_GEN_FORMAT_ASCII)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
- goto bad_form;
- }
- if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
- goto bad_str;
- }
- break;
-
- case V_ASN1_UTCTIME:
- case V_ASN1_GENERALIZEDTIME:
- if (format != ASN1_GEN_FORMAT_ASCII)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
- goto bad_form;
- }
- if (!(atmp->value.asn1_string = ASN1_STRING_new()))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto bad_str;
- }
- if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto bad_str;
- }
- atmp->value.asn1_string->type = utype;
- if (!ASN1_TIME_check(atmp->value.asn1_string))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
- goto bad_str;
- }
-
- break;
-
- case V_ASN1_BMPSTRING:
- case V_ASN1_PRINTABLESTRING:
- case V_ASN1_IA5STRING:
- case V_ASN1_T61STRING:
- case V_ASN1_UTF8STRING:
- case V_ASN1_VISIBLESTRING:
- case V_ASN1_UNIVERSALSTRING:
- case V_ASN1_GENERALSTRING:
- case V_ASN1_NUMERICSTRING:
-
- if (format == ASN1_GEN_FORMAT_ASCII)
- format = MBSTRING_ASC;
- else if (format == ASN1_GEN_FORMAT_UTF8)
- format = MBSTRING_UTF8;
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT);
- goto bad_form;
- }
-
-
- if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
- -1, format, ASN1_tag2bit(utype)) <= 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto bad_str;
- }
-
-
- break;
-
- case V_ASN1_BIT_STRING:
-
- case V_ASN1_OCTET_STRING:
-
- if (!(atmp->value.asn1_string = ASN1_STRING_new()))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto bad_form;
- }
-
- if (format == ASN1_GEN_FORMAT_HEX)
- {
-
- if (!(rdata = string_to_hex((char *)str, &rdlen)))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
- goto bad_str;
- }
-
- atmp->value.asn1_string->data = rdata;
- atmp->value.asn1_string->length = rdlen;
- atmp->value.asn1_string->type = utype;
-
- }
- else if (format == ASN1_GEN_FORMAT_ASCII)
- ASN1_STRING_set(atmp->value.asn1_string, str, -1);
- else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING))
- {
- if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR);
- goto bad_str;
- }
- no_unused = 0;
-
- }
- else
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
- goto bad_form;
- }
-
- if ((utype == V_ASN1_BIT_STRING) && no_unused)
- {
- atmp->value.asn1_string->flags
- &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
- atmp->value.asn1_string->flags
- |= ASN1_STRING_FLAG_BITS_LEFT;
- }
-
-
- break;
-
- default:
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE);
- goto bad_str;
- break;
- }
-
-
- atmp->type = utype;
- return atmp;
-
-
- bad_str:
- ERR_add_error_data(2, "string=", str);
- bad_form:
-
- ASN1_TYPE_free(atmp);
- return NULL;
-
- }
+{
+ ASN1_TYPE *atmp = NULL;
+
+ CONF_VALUE vtmp;
+
+ unsigned char *rdata;
+ long rdlen;
+
+ int no_unused = 1;
+
+ if (!(atmp = ASN1_TYPE_new())) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!str)
+ str = "";
+
+ switch (utype) {
+
+ case V_ASN1_NULL:
+ if (str && *str) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
+ goto bad_form;
+ }
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (format != ASN1_GEN_FORMAT_ASCII) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ vtmp.name = NULL;
+ vtmp.section = NULL;
+ vtmp.value = (char *)str;
+ if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_ENUMERATED:
+ if (format != ASN1_GEN_FORMAT_ASCII) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_OBJECT:
+ if (format != ASN1_GEN_FORMAT_ASCII) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ if (format != ASN1_GEN_FORMAT_ASCII) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ atmp->value.asn1_string->type = utype;
+ if (!ASN1_TIME_check(atmp->value.asn1_string)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
+ goto bad_str;
+ }
+
+ break;
+
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_NUMERICSTRING:
+
+ if (format == ASN1_GEN_FORMAT_ASCII)
+ format = MBSTRING_ASC;
+ else if (format == ASN1_GEN_FORMAT_UTF8)
+ format = MBSTRING_UTF8;
+ else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT);
+ goto bad_form;
+ }
+
+ if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
+ -1, format, ASN1_tag2bit(utype)) <= 0) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+
+ break;
+
+ case V_ASN1_BIT_STRING:
+
+ case V_ASN1_OCTET_STRING:
+
+ if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto bad_form;
+ }
+
+ if (format == ASN1_GEN_FORMAT_HEX) {
+
+ if (!(rdata = string_to_hex((char *)str, &rdlen))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
+ goto bad_str;
+ }
+
+ atmp->value.asn1_string->data = rdata;
+ atmp->value.asn1_string->length = rdlen;
+ atmp->value.asn1_string->type = utype;
+
+ } else if (format == ASN1_GEN_FORMAT_ASCII)
+ ASN1_STRING_set(atmp->value.asn1_string, str, -1);
+ else if ((format == ASN1_GEN_FORMAT_BITLIST)
+ && (utype == V_ASN1_BIT_STRING)) {
+ if (!CONF_parse_list
+ (str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR);
+ goto bad_str;
+ }
+ no_unused = 0;
+
+ } else {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+ goto bad_form;
+ }
+
+ if ((utype == V_ASN1_BIT_STRING) && no_unused) {
+ atmp->value.asn1_string->flags
+ &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ }
+
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE);
+ goto bad_str;
+ break;
+ }
+
+ atmp->type = utype;
+ return atmp;
+
+ bad_str:
+ ERR_add_error_data(2, "string=", str);
+ bad_form:
+
+ ASN1_TYPE_free(atmp);
+ return NULL;
+
+}
static int bitstr_cb(const char *elem, int len, void *bitstr)
- {
- long bitnum;
- char *eptr;
- if (!elem)
- return 0;
- bitnum = strtoul(elem, &eptr, 10);
- if (eptr && *eptr && (eptr != elem + len))
- return 0;
- if (bitnum < 0)
- {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
- return 0;
- }
- if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
- {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
- }
-
+{
+ long bitnum;
+ char *eptr;
+ if (!elem)
+ return 0;
+ bitnum = strtoul(elem, &eptr, 10);
+ if (eptr && *eptr && (eptr != elem + len))
+ return 0;
+ if (bitnum < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
+ return 0;
+ }
+ if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
index ae50ae1e..4f0a49e2 100644
--- a/src/crypto/x509/by_dir.c
+++ b/src/crypto/x509/by_dir.c
@@ -68,424 +68,386 @@
#include "../internal.h"
-
-typedef struct lookup_dir_hashes_st
- {
- unsigned long hash;
- int suffix;
- } BY_DIR_HASH;
-
-typedef struct lookup_dir_entry_st
- {
- char *dir;
- int dir_type;
- STACK_OF(BY_DIR_HASH) *hashes;
- } BY_DIR_ENTRY;
-
-typedef struct lookup_dir_st
- {
- BUF_MEM *buffer;
- STACK_OF(BY_DIR_ENTRY) *dirs;
- } BY_DIR;
+typedef struct lookup_dir_hashes_st {
+ unsigned long hash;
+ int suffix;
+} BY_DIR_HASH;
+
+typedef struct lookup_dir_entry_st {
+ char *dir;
+ int dir_type;
+ STACK_OF(BY_DIR_HASH) *hashes;
+} BY_DIR_ENTRY;
+
+typedef struct lookup_dir_st {
+ BUF_MEM *buffer;
+ STACK_OF(BY_DIR_ENTRY) *dirs;
+} BY_DIR;
DECLARE_STACK_OF(BY_DIR_HASH)
DECLARE_STACK_OF(BY_DIR_ENTRY)
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
- char **ret);
+ char **ret);
static int new_dir(X509_LOOKUP *lu);
static void free_dir(X509_LOOKUP *lu);
-static int add_cert_dir(BY_DIR *ctx,const char *dir,int type);
-static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name,
- X509_OBJECT *ret);
-static X509_LOOKUP_METHOD x509_dir_lookup=
- {
- "Load certs from files in a directory",
- new_dir, /* new */
- free_dir, /* free */
- NULL, /* init */
- NULL, /* shutdown */
- dir_ctrl, /* ctrl */
- get_cert_by_subject, /* get_by_subject */
- NULL, /* get_by_issuer_serial */
- NULL, /* get_by_fingerprint */
- NULL, /* get_by_alias */
- };
+static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
+static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
+ X509_OBJECT *ret);
+static X509_LOOKUP_METHOD x509_dir_lookup = {
+ "Load certs from files in a directory",
+ new_dir, /* new */
+ free_dir, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ dir_ctrl, /* ctrl */
+ get_cert_by_subject, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+};
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
- {
- return(&x509_dir_lookup);
- }
+{
+ return (&x509_dir_lookup);
+}
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
- char **retp)
- {
- int ret=0;
- BY_DIR *ld;
- char *dir = NULL;
-
- ld=(BY_DIR *)ctx->method_data;
-
- switch (cmd)
- {
- case X509_L_ADD_DIR:
- if (argl == X509_FILETYPE_DEFAULT)
- {
- dir=(char *)getenv(X509_get_default_cert_dir_env());
- if (dir)
- ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
- else
- ret=add_cert_dir(ld,X509_get_default_cert_dir(),
- X509_FILETYPE_PEM);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR);
- }
- }
- else
- ret=add_cert_dir(ld,argp,(int)argl);
- break;
- }
- return(ret);
- }
+ char **retp)
+{
+ int ret = 0;
+ BY_DIR *ld;
+ char *dir = NULL;
+
+ ld = (BY_DIR *)ctx->method_data;
+
+ switch (cmd) {
+ case X509_L_ADD_DIR:
+ if (argl == X509_FILETYPE_DEFAULT) {
+ dir = (char *)getenv(X509_get_default_cert_dir_env());
+ if (dir)
+ ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
+ else
+ ret = add_cert_dir(ld, X509_get_default_cert_dir(),
+ X509_FILETYPE_PEM);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR);
+ }
+ } else
+ ret = add_cert_dir(ld, argp, (int)argl);
+ break;
+ }
+ return (ret);
+}
static int new_dir(X509_LOOKUP *lu)
- {
- BY_DIR *a;
-
- if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
- return(0);
- if ((a->buffer=BUF_MEM_new()) == NULL)
- {
- OPENSSL_free(a);
- return(0);
- }
- a->dirs=NULL;
- lu->method_data=(char *)a;
- return(1);
- }
+{
+ BY_DIR *a;
+
+ if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
+ return (0);
+ if ((a->buffer = BUF_MEM_new()) == NULL) {
+ OPENSSL_free(a);
+ return (0);
+ }
+ a->dirs = NULL;
+ lu->method_data = (char *)a;
+ return (1);
+}
static void by_dir_hash_free(BY_DIR_HASH *hash)
- {
- OPENSSL_free(hash);
- }
-
-static int by_dir_hash_cmp(const BY_DIR_HASH **a,
- const BY_DIR_HASH **b)
- {
- if ((*a)->hash > (*b)->hash)
- return 1;
- if ((*a)->hash < (*b)->hash)
- return -1;
- return 0;
- }
+{
+ OPENSSL_free(hash);
+}
+
+static int by_dir_hash_cmp(const BY_DIR_HASH **a, const BY_DIR_HASH **b)
+{
+ if ((*a)->hash > (*b)->hash)
+ return 1;
+ if ((*a)->hash < (*b)->hash)
+ return -1;
+ return 0;
+}
static void by_dir_entry_free(BY_DIR_ENTRY *ent)
- {
- if (ent->dir)
- OPENSSL_free(ent->dir);
- if (ent->hashes)
- sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
- OPENSSL_free(ent);
- }
+{
+ if (ent->dir)
+ OPENSSL_free(ent->dir);
+ if (ent->hashes)
+ sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
+ OPENSSL_free(ent);
+}
static void free_dir(X509_LOOKUP *lu)
- {
- BY_DIR *a;
+{
+ BY_DIR *a;
- a=(BY_DIR *)lu->method_data;
- if (a->dirs != NULL)
- sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
- if (a->buffer != NULL)
- BUF_MEM_free(a->buffer);
- OPENSSL_free(a);
- }
+ a = (BY_DIR *)lu->method_data;
+ if (a->dirs != NULL)
+ sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
+ if (a->buffer != NULL)
+ BUF_MEM_free(a->buffer);
+ OPENSSL_free(a);
+}
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
- {
- size_t j,len;
- const char *s,*ss,*p;
-
- if (dir == NULL || !*dir)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY);
- return 0;
- }
-
- s=dir;
- p=s;
- do
- {
- if ((*p == ':') || (*p == '\0'))
- {
- BY_DIR_ENTRY *ent;
- ss=s;
- s=p+1;
- len=p-ss;
- if (len == 0) continue;
- for (j=0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++)
- {
- ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
- if (strlen(ent->dir) == len &&
- strncmp(ent->dir,ss,len) == 0)
- break;
- }
- if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
- continue;
- if (ctx->dirs == NULL)
- {
- ctx->dirs = sk_BY_DIR_ENTRY_new_null();
- if (!ctx->dirs)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- }
- ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
- if (!ent)
- return 0;
- ent->dir_type = type;
- ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
- ent->dir = OPENSSL_malloc(len+1);
- if (!ent->dir || !ent->hashes)
- {
- by_dir_entry_free(ent);
- return 0;
- }
- strncpy(ent->dir,ss,len);
- ent->dir[len] = '\0';
- if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
- {
- by_dir_entry_free(ent);
- return 0;
- }
- }
- } while (*p++ != '\0');
- return 1;
- }
-
-/* g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
- * objects. */
-static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = CRYPTO_STATIC_MUTEX_INIT;
+{
+ size_t j, len;
+ const char *s, *ss, *p;
+
+ if (dir == NULL || !*dir) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY);
+ return 0;
+ }
+
+ s = dir;
+ p = s;
+ do {
+ if ((*p == ':') || (*p == '\0')) {
+ BY_DIR_ENTRY *ent;
+ ss = s;
+ s = p + 1;
+ len = p - ss;
+ if (len == 0)
+ continue;
+ for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) {
+ ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
+ if (strlen(ent->dir) == len &&
+ strncmp(ent->dir, ss, len) == 0)
+ break;
+ }
+ if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
+ continue;
+ if (ctx->dirs == NULL) {
+ ctx->dirs = sk_BY_DIR_ENTRY_new_null();
+ if (!ctx->dirs) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
+ if (!ent)
+ return 0;
+ ent->dir_type = type;
+ ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
+ ent->dir = OPENSSL_malloc(len + 1);
+ if (!ent->dir || !ent->hashes) {
+ by_dir_entry_free(ent);
+ return 0;
+ }
+ strncpy(ent->dir, ss, len);
+ ent->dir[len] = '\0';
+ if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
+ by_dir_entry_free(ent);
+ return 0;
+ }
+ }
+ } while (*p++ != '\0');
+ return 1;
+}
+
+/*
+ * g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
+ * objects.
+ */
+static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock =
+ CRYPTO_STATIC_MUTEX_INIT;
static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
- X509_OBJECT *ret)
- {
- BY_DIR *ctx;
- union {
- struct {
- X509 st_x509;
- X509_CINF st_x509_cinf;
- } x509;
- struct {
- X509_CRL st_crl;
- X509_CRL_INFO st_crl_info;
- } crl;
- } data;
- int ok=0;
- size_t i;
- int j,k;
- unsigned long h;
- unsigned long hash_array[2];
- int hash_index;
- BUF_MEM *b=NULL;
- X509_OBJECT stmp,*tmp;
- const char *postfix="";
-
- if (name == NULL) return(0);
-
- stmp.type=type;
- if (type == X509_LU_X509)
- {
- data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
- data.x509.st_x509_cinf.subject=name;
- stmp.data.x509= &data.x509.st_x509;
- postfix="";
- }
- else if (type == X509_LU_CRL)
- {
- data.crl.st_crl.crl= &data.crl.st_crl_info;
- data.crl.st_crl_info.issuer=name;
- stmp.data.crl= &data.crl.st_crl;
- postfix="r";
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE);
- goto finish;
- }
-
- if ((b=BUF_MEM_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- goto finish;
- }
-
- ctx=(BY_DIR *)xl->method_data;
-
- hash_array[0]=X509_NAME_hash(name);
- hash_array[1]=X509_NAME_hash_old(name);
- for (hash_index=0; hash_index < 2; ++hash_index)
- {
- h=hash_array[hash_index];
- for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
- {
- BY_DIR_ENTRY *ent;
- size_t idx;
- BY_DIR_HASH htmp, *hent;
- ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
- j=strlen(ent->dir)+1+8+6+1+1;
- if (!BUF_MEM_grow(b,j))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto finish;
- }
- if (type == X509_LU_CRL && ent->hashes)
- {
- htmp.hash = h;
- CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock);
- if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
- {
- hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
- k = hent->suffix;
- }
- else
- {
- hent = NULL;
- k=0;
- }
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
- }
- else
- {
- k = 0;
- hent = NULL;
- }
- for (;;)
- {
- char c = '/';
+ X509_OBJECT *ret)
+{
+ BY_DIR *ctx;
+ union {
+ struct {
+ X509 st_x509;
+ X509_CINF st_x509_cinf;
+ } x509;
+ struct {
+ X509_CRL st_crl;
+ X509_CRL_INFO st_crl_info;
+ } crl;
+ } data;
+ int ok = 0;
+ size_t i;
+ int j, k;
+ unsigned long h;
+ unsigned long hash_array[2];
+ int hash_index;
+ BUF_MEM *b = NULL;
+ X509_OBJECT stmp, *tmp;
+ const char *postfix = "";
+
+ if (name == NULL)
+ return (0);
+
+ stmp.type = type;
+ if (type == X509_LU_X509) {
+ data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;
+ data.x509.st_x509_cinf.subject = name;
+ stmp.data.x509 = &data.x509.st_x509;
+ postfix = "";
+ } else if (type == X509_LU_CRL) {
+ data.crl.st_crl.crl = &data.crl.st_crl_info;
+ data.crl.st_crl_info.issuer = name;
+ stmp.data.crl = &data.crl.st_crl;
+ postfix = "r";
+ } else {
+ OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE);
+ goto finish;
+ }
+
+ if ((b = BUF_MEM_new()) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+ goto finish;
+ }
+
+ ctx = (BY_DIR *)xl->method_data;
+
+ hash_array[0] = X509_NAME_hash(name);
+ hash_array[1] = X509_NAME_hash_old(name);
+ for (hash_index = 0; hash_index < 2; ++hash_index) {
+ h = hash_array[hash_index];
+ for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
+ BY_DIR_ENTRY *ent;
+ size_t idx;
+ BY_DIR_HASH htmp, *hent;
+ ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
+ j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
+ if (!BUF_MEM_grow(b, j)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto finish;
+ }
+ if (type == X509_LU_CRL && ent->hashes) {
+ htmp.hash = h;
+ CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock);
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) {
+ hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+ k = hent->suffix;
+ } else {
+ hent = NULL;
+ k = 0;
+ }
+ CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ } else {
+ k = 0;
+ hent = NULL;
+ }
+ for (;;) {
+ char c = '/';
#ifdef OPENSSL_SYS_VMS
- c = ent->dir[strlen(ent->dir)-1];
- if (c != ':' && c != '>' && c != ']')
- {
- /* If no separator is present, we assume the
- directory specifier is a logical name, and
- add a colon. We really should use better
- VMS routines for merging things like this,
- but this will do for now...
- -- Richard Levitte */
- c = ':';
- }
- else
- {
- c = '\0';
- }
+ c = ent->dir[strlen(ent->dir) - 1];
+ if (c != ':' && c != '>' && c != ']') {
+ /*
+ * If no separator is present, we assume the directory
+ * specifier is a logical name, and add a colon. We
+ * really should use better VMS routines for merging
+ * things like this, but this will do for now... --
+ * Richard Levitte
+ */
+ c = ':';
+ } else {
+ c = '\0';
+ }
#endif
- if (c == '\0')
- {
- /* This is special. When c == '\0', no
- directory separator should be added. */
- BIO_snprintf(b->data,b->max,
- "%s%08lx.%s%d",ent->dir,h,
- postfix,k);
- }
- else
- {
- BIO_snprintf(b->data,b->max,
- "%s%c%08lx.%s%d",ent->dir,c,h,
- postfix,k);
- }
+ if (c == '\0') {
+ /*
+ * This is special. When c == '\0', no directory
+ * separator should be added.
+ */
+ BIO_snprintf(b->data, b->max,
+ "%s%08lx.%s%d", ent->dir, h, postfix, k);
+ } else {
+ BIO_snprintf(b->data, b->max,
+ "%s%c%08lx.%s%d", ent->dir, c, h,
+ postfix, k);
+ }
#ifndef OPENSSL_NO_POSIX_IO
-#ifdef _WIN32
-#define stat _stat
-#endif
- {
- struct stat st;
- if (stat(b->data,&st) < 0)
- break;
- }
+# ifdef _WIN32
+# define stat _stat
+# endif
+ {
+ struct stat st;
+ if (stat(b->data, &st) < 0)
+ break;
+ }
#endif
- /* found one. */
- if (type == X509_LU_X509)
- {
- if ((X509_load_cert_file(xl,b->data,
- ent->dir_type)) == 0)
- break;
- }
- else if (type == X509_LU_CRL)
- {
- if ((X509_load_crl_file(xl,b->data,
- ent->dir_type)) == 0)
- break;
- }
- /* else case will caught higher up */
- k++;
- }
-
- /* we have added it to the cache so now pull
- * it out again */
- CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock);
- tmp = NULL;
- if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
- tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx);
- }
- CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);
-
-
- /* If a CRL, update the last file suffix added for this */
-
- if (type == X509_LU_CRL)
- {
- CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
- /* Look for entry again in case another thread added
- * an entry first.
- */
- if (!hent)
- {
- htmp.hash = h;
- if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
- hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
- }
- if (!hent)
- {
- hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
- if (hent == NULL)
- {
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
- ok = 0;
- goto finish;
- }
- hent->hash = h;
- hent->suffix = k;
- if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
- {
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
- OPENSSL_free(hent);
- ok = 0;
- goto finish;
- }
- }
- else if (hent->suffix < k)
- hent->suffix = k;
-
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
- }
-
- if (tmp != NULL)
- {
- ok=1;
- ret->type=tmp->type;
- memcpy(&ret->data,&tmp->data,sizeof(ret->data));
- /* If we were going to up the reference count,
- * we would need to do it on a perl 'type'
- * basis */
- /* CRYPTO_add(&tmp->data.x509->references,1,
- CRYPTO_LOCK_X509);*/
- goto finish;
- }
- }
- }
-finish:
- if (b != NULL) BUF_MEM_free(b);
- return(ok);
- }
+ /* found one. */
+ if (type == X509_LU_X509) {
+ if ((X509_load_cert_file(xl, b->data,
+ ent->dir_type)) == 0)
+ break;
+ } else if (type == X509_LU_CRL) {
+ if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
+ break;
+ }
+ /* else case will caught higher up */
+ k++;
+ }
+
+ /*
+ * we have added it to the cache so now pull it out again
+ */
+ CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock);
+ tmp = NULL;
+ if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
+ tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx);
+ }
+ CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);
+
+ /*
+ * If a CRL, update the last file suffix added for this
+ */
+
+ if (type == X509_LU_CRL) {
+ CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
+ /*
+ * Look for entry again in case another thread added an entry
+ * first.
+ */
+ if (!hent) {
+ htmp.hash = h;
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+ hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+ }
+ if (!hent) {
+ hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+ if (hent == NULL) {
+ CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ ok = 0;
+ goto finish;
+ }
+ hent->hash = h;
+ hent->suffix = k;
+ if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
+ CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ OPENSSL_free(hent);
+ ok = 0;
+ goto finish;
+ }
+ } else if (hent->suffix < k)
+ hent->suffix = k;
+
+ CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ }
+
+ if (tmp != NULL) {
+ ok = 1;
+ ret->type = tmp->type;
+ memcpy(&ret->data, &tmp->data, sizeof(ret->data));
+ /*
+ * If we were going to up the reference count, we would need
+ * to do it on a perl 'type' basis
+ */
+ /*
+ * CRYPTO_add(&tmp->data.x509->references,1,
+ * CRYPTO_LOCK_X509);
+ */
+ goto finish;
+ }
+ }
+ }
+ finish:
+ if (b != NULL)
+ BUF_MEM_free(b);
+ return (ok);
+}
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 3460b570..ebeb72e5 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -63,233 +63,213 @@
#include <openssl/pem.h>
#include <openssl/thread.h>
-
#ifndef OPENSSL_NO_STDIO
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
- long argl, char **ret);
-static X509_LOOKUP_METHOD x509_file_lookup=
- {
- "Load file into cache",
- NULL, /* new */
- NULL, /* free */
- NULL, /* init */
- NULL, /* shutdown */
- by_file_ctrl, /* ctrl */
- NULL, /* get_by_subject */
- NULL, /* get_by_issuer_serial */
- NULL, /* get_by_fingerprint */
- NULL, /* get_by_alias */
- };
+ long argl, char **ret);
+static X509_LOOKUP_METHOD x509_file_lookup = {
+ "Load file into cache",
+ NULL, /* new */
+ NULL, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ by_file_ctrl, /* ctrl */
+ NULL, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+};
X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
- {
- return(&x509_file_lookup);
- }
+{
+ return (&x509_file_lookup);
+}
-static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
- char **ret)
- {
- int ok=0;
- char *file;
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
+ long argl, char **ret)
+{
+ int ok = 0;
+ char *file;
- switch (cmd)
- {
- case X509_L_FILE_LOAD:
- if (argl == X509_FILETYPE_DEFAULT)
- {
- file = (char *)getenv(X509_get_default_cert_file_env());
- if (file)
- ok = (X509_load_cert_crl_file(ctx,file,
- X509_FILETYPE_PEM) != 0);
+ switch (cmd) {
+ case X509_L_FILE_LOAD:
+ if (argl == X509_FILETYPE_DEFAULT) {
+ file = (char *)getenv(X509_get_default_cert_file_env());
+ if (file)
+ ok = (X509_load_cert_crl_file(ctx, file,
+ X509_FILETYPE_PEM) != 0);
- else
- ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
- X509_FILETYPE_PEM) != 0);
+ else
+ ok = (X509_load_cert_crl_file
+ (ctx, X509_get_default_cert_file(),
+ X509_FILETYPE_PEM) != 0);
- if (!ok)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS);
- }
- }
- else
- {
- if(argl == X509_FILETYPE_PEM)
- ok = (X509_load_cert_crl_file(ctx,argp,
- X509_FILETYPE_PEM) != 0);
- else
- ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0);
- }
- break;
- }
- return(ok);
- }
+ if (!ok) {
+ OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS);
+ }
+ } else {
+ if (argl == X509_FILETYPE_PEM)
+ ok = (X509_load_cert_crl_file(ctx, argp,
+ X509_FILETYPE_PEM) != 0);
+ else
+ ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
+ }
+ break;
+ }
+ return (ok);
+}
int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
- {
- int ret=0;
- BIO *in=NULL;
- int i,count=0;
- X509 *x=NULL;
+{
+ int ret = 0;
+ BIO *in = NULL;
+ int i, count = 0;
+ X509 *x = NULL;
- if (file == NULL) return(1);
- in=BIO_new(BIO_s_file());
+ if (file == NULL)
+ return (1);
+ in = BIO_new(BIO_s_file());
- if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
- goto err;
- }
+ if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+ goto err;
+ }
- if (type == X509_FILETYPE_PEM)
- {
- for (;;)
- {
- x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL);
- if (x == NULL)
- {
- if ((ERR_GET_REASON(ERR_peek_last_error()) ==
- PEM_R_NO_START_LINE) && (count > 0))
- {
- ERR_clear_error();
- break;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
- goto err;
- }
- }
- i=X509_STORE_add_cert(ctx->store_ctx,x);
- if (!i) goto err;
- count++;
- X509_free(x);
- x=NULL;
- }
- ret=count;
- }
- else if (type == X509_FILETYPE_ASN1)
- {
- x=d2i_X509_bio(in,NULL);
- if (x == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
- goto err;
- }
- i=X509_STORE_add_cert(ctx->store_ctx,x);
- if (!i) goto err;
- ret=i;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
- goto err;
- }
-err:
- if (x != NULL) X509_free(x);
- if (in != NULL) BIO_free(in);
- return(ret);
- }
+ if (type == X509_FILETYPE_PEM) {
+ for (;;) {
+ x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
+ if (x == NULL) {
+ if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+ PEM_R_NO_START_LINE) && (count > 0)) {
+ ERR_clear_error();
+ break;
+ } else {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+ goto err;
+ }
+ }
+ i = X509_STORE_add_cert(ctx->store_ctx, x);
+ if (!i)
+ goto err;
+ count++;
+ X509_free(x);
+ x = NULL;
+ }
+ ret = count;
+ } else if (type == X509_FILETYPE_ASN1) {
+ x = d2i_X509_bio(in, NULL);
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i = X509_STORE_add_cert(ctx->store_ctx, x);
+ if (!i)
+ goto err;
+ ret = i;
+ } else {
+ OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+ err:
+ if (x != NULL)
+ X509_free(x);
+ if (in != NULL)
+ BIO_free(in);
+ return (ret);
+}
int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
- {
- int ret=0;
- BIO *in=NULL;
- int i,count=0;
- X509_CRL *x=NULL;
+{
+ int ret = 0;
+ BIO *in = NULL;
+ int i, count = 0;
+ X509_CRL *x = NULL;
- if (file == NULL) return(1);
- in=BIO_new(BIO_s_file());
+ if (file == NULL)
+ return (1);
+ in = BIO_new(BIO_s_file());
- if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
- goto err;
- }
+ if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+ goto err;
+ }
- if (type == X509_FILETYPE_PEM)
- {
- for (;;)
- {
- x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
- if (x == NULL)
- {
- if ((ERR_GET_REASON(ERR_peek_last_error()) ==
- PEM_R_NO_START_LINE) && (count > 0))
- {
- ERR_clear_error();
- break;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
- goto err;
- }
- }
- i=X509_STORE_add_crl(ctx->store_ctx,x);
- if (!i) goto err;
- count++;
- X509_CRL_free(x);
- x=NULL;
- }
- ret=count;
- }
- else if (type == X509_FILETYPE_ASN1)
- {
- x=d2i_X509_CRL_bio(in,NULL);
- if (x == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
- goto err;
- }
- i=X509_STORE_add_crl(ctx->store_ctx,x);
- if (!i) goto err;
- ret=i;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
- goto err;
- }
-err:
- if (x != NULL) X509_CRL_free(x);
- if (in != NULL) BIO_free(in);
- return(ret);
- }
+ if (type == X509_FILETYPE_PEM) {
+ for (;;) {
+ x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+ if (x == NULL) {
+ if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+ PEM_R_NO_START_LINE) && (count > 0)) {
+ ERR_clear_error();
+ break;
+ } else {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+ goto err;
+ }
+ }
+ i = X509_STORE_add_crl(ctx->store_ctx, x);
+ if (!i)
+ goto err;
+ count++;
+ X509_CRL_free(x);
+ x = NULL;
+ }
+ ret = count;
+ } else if (type == X509_FILETYPE_ASN1) {
+ x = d2i_X509_CRL_bio(in, NULL);
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i = X509_STORE_add_crl(ctx->store_ctx, x);
+ if (!i)
+ goto err;
+ ret = i;
+ } else {
+ OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+ err:
+ if (x != NULL)
+ X509_CRL_free(x);
+ if (in != NULL)
+ BIO_free(in);
+ return (ret);
+}
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
- STACK_OF(X509_INFO) *inf;
- X509_INFO *itmp;
- BIO *in;
- size_t i;
- int count = 0;
- if(type != X509_FILETYPE_PEM)
- return X509_load_cert_file(ctx, file, type);
- in = BIO_new_file(file, "r");
- if(!in) {
- OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
- return 0;
- }
- inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
- BIO_free(in);
- if(!inf) {
- OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
- return 0;
- }
- for(i = 0; i < sk_X509_INFO_num(inf); i++) {
- itmp = sk_X509_INFO_value(inf, i);
- if(itmp->x509) {
- X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
- count++;
- }
- if(itmp->crl) {
- X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
- count++;
- }
- }
- sk_X509_INFO_pop_free(inf, X509_INFO_free);
- return count;
+ STACK_OF(X509_INFO) *inf;
+ X509_INFO *itmp;
+ BIO *in;
+ size_t i;
+ int count = 0;
+ if (type != X509_FILETYPE_PEM)
+ return X509_load_cert_file(ctx, file, type);
+ in = BIO_new_file(file, "r");
+ if (!in) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+ return 0;
+ }
+ inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+ BIO_free(in);
+ if (!inf) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+ return 0;
+ }
+ for (i = 0; i < sk_X509_INFO_num(inf); i++) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if (itmp->x509) {
+ X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
+ count++;
+ }
+ if (itmp->crl) {
+ X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
+ count++;
+ }
+ }
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ return count;
}
-#endif /* OPENSSL_NO_STDIO */
+#endif /* OPENSSL_NO_STDIO */
diff --git a/src/crypto/x509/charmap.h b/src/crypto/x509/charmap.h
index b55e6387..3305ad14 100644
--- a/src/crypto/x509/charmap.h
+++ b/src/crypto/x509/charmap.h
@@ -1,15 +1,15 @@
-/* Auto generated with chartype.pl script.
- * Mask of various character properties
+/*
+ * Auto generated with chartype.pl script. Mask of various character
+ * properties
*/
static const unsigned char char_type[] = {
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-120, 0, 1,40, 0, 0, 0,16,16,16, 0,25,25,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 9, 9,16, 9,16,
- 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 0, 1, 0, 0, 0,
- 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 0, 0, 0, 0, 2
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16,
+ 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0,
+ 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2
};
-
diff --git a/src/crypto/x509/i2d_pr.c b/src/crypto/x509/i2d_pr.c
index e7f4269d..c3fb8a8a 100644
--- a/src/crypto/x509/i2d_pr.c
+++ b/src/crypto/x509/i2d_pr.c
@@ -55,30 +55,29 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
-#include <openssl/x509.h>
-
#include <openssl/asn1.h>
+#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
-#include "../evp/internal.h"
-
-
-int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
- {
- if (a->ameth && a->ameth->old_priv_encode)
- {
- return a->ameth->old_priv_encode(a, pp);
- }
- if (a->ameth && a->ameth->priv_encode) {
- PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8((EVP_PKEY*)a);
- int ret = i2d_PKCS8_PRIV_KEY_INFO(p8,pp);
- PKCS8_PRIV_KEY_INFO_free(p8);
- return ret;
- }
- /* Although this file is in crypto/x509 for layering reasons, it emits
- * an error code from ASN1 for OpenSSL compatibility. */
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return -1;
- }
+int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp)
+{
+ switch (EVP_PKEY_id(a)) {
+ case EVP_PKEY_RSA:
+ return i2d_RSAPrivateKey(a->pkey.rsa, pp);
+ case EVP_PKEY_EC:
+ return i2d_ECPrivateKey(a->pkey.ec, pp);
+ case EVP_PKEY_DSA:
+ return i2d_DSAPrivateKey(a->pkey.dsa, pp);
+ default:
+ /*
+ * Although this file is in crypto/x509 for layering reasons, it emits
+ * an error code from ASN1 for OpenSSL compatibility.
+ */
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+ }
+}
diff --git a/src/crypto/x509/internal.h b/src/crypto/x509/internal.h
new file mode 100644
index 00000000..4957c1e1
--- /dev/null
+++ b/src/crypto/x509/internal.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_X509_INTERNAL_H
+#define OPENSSL_HEADER_X509_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* RSA-PSS functions. */
+
+/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on
+ * signature algorithm parameters in |sigalg| (which must have type
+ * |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on
+ * error. */
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey);
+
+/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for
+ * |ctx|, which must have been configured for an RSA-PSS signing operation. It
+ * returns one on success and zero on error. */
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS
+ * parameters in |sigalg| to |bp|. It returns one on success and zero on
+ * error. */
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+ ASN1_PCTX *pctx);
+
+
+/* Signature algorithm functions. */
+
+/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an
+ * AlgorithmIdentifer and saves the result in |algor|. It returns one on
+ * success, or zero on error. */
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_digest_verify_init sets up |ctx| for a signature verification operation
+ * with public key |pkey| and parameters from |algor|. The |ctx| argument must
+ * have been initialised with |EVP_MD_CTX_init|. It returns one on success, or
+ * zero on error. */
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+ EVP_PKEY *pkey);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_X509_INTERNAL_H */
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
index 38beb3e8..2dfeb5ed 100644
--- a/src/crypto/x509/pkcs7_test.c
+++ b/src/crypto/x509/pkcs7_test.c
@@ -22,6 +22,8 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
+#include "../test/test_util.h"
+
/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
* using the Chrome UI. */
@@ -504,7 +506,7 @@ static int test_cert_reparse(const uint8_t *der_bytes, size_t der_len) {
X509 *b = sk_X509_value(certs2, i);
if (X509_cmp(a, b) != 0) {
- fprintf(stderr, "Certificate %u differs.\n", (unsigned) i);
+ fprintf(stderr, "Certificate %" OPENSSL_PR_SIZE_T " differs.\n", i);
return 0;
}
}
@@ -568,7 +570,7 @@ static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) {
X509_CRL *b = sk_X509_CRL_value(crls2, i);
if (X509_CRL_cmp(a, b) != 0) {
- fprintf(stderr, "CRL %u differs.\n", (unsigned) i);
+ fprintf(stderr, "CRL %" OPENSSL_PR_SIZE_T " differs.\n", i);
return 0;
}
}
@@ -596,7 +598,7 @@ static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) {
}
static int test_pem_certs(const char *pem) {
- BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+ BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
STACK_OF(X509) *certs = sk_X509_new_null();
if (!PKCS7_get_PEM_certificates(certs, bio)) {
@@ -606,8 +608,9 @@ static int test_pem_certs(const char *pem) {
if (sk_X509_num(certs) != 1) {
fprintf(stderr,
- "Bad number of certificates from PKCS7_get_PEM_certificates: %u\n",
- (unsigned)sk_X509_num(certs));
+ "Bad number of certificates from PKCS7_get_PEM_certificates: "
+ "%" OPENSSL_PR_SIZE_T "\n",
+ sk_X509_num(certs));
return 0;
}
@@ -618,7 +621,7 @@ static int test_pem_certs(const char *pem) {
}
static int test_pem_crls(const char *pem) {
- BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+ BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null();
if (!PKCS7_get_PEM_CRLs(crls, bio)) {
@@ -628,8 +631,9 @@ static int test_pem_crls(const char *pem) {
if (sk_X509_CRL_num(crls) != 1) {
fprintf(stderr,
- "Bad number of CRLs from PKCS7_get_PEM_CRLs: %u\n",
- (unsigned)sk_X509_CRL_num(crls));
+ "Bad number of CRLs from PKCS7_get_PEM_CRLs: %" OPENSSL_PR_SIZE_T
+ "\n",
+ sk_X509_CRL_num(crls));
return 0;
}
@@ -653,4 +657,3 @@ int main(void) {
printf("PASS\n");
return 0;
}
-
diff --git a/src/crypto/x509/rsa_pss.c b/src/crypto/x509/rsa_pss.c
new file mode 100644
index 00000000..1ae01a3d
--- /dev/null
+++ b/src/crypto/x509/rsa_pss.c
@@ -0,0 +1,385 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/x509.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
+} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
+
+
+/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
+static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
+ if (alg == NULL || alg->parameter == NULL ||
+ OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+ alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+
+ const uint8_t *p = alg->parameter->value.sequence->data;
+ int plen = alg->parameter->value.sequence->length;
+ return d2i_X509_ALGOR(NULL, &p, plen);
+}
+
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+ X509_ALGOR **pmaskHash) {
+ *pmaskHash = NULL;
+
+ if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+
+ const uint8_t *p = alg->parameter->value.sequence->data;
+ int plen = alg->parameter->value.sequence->length;
+ RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+ if (pss == NULL) {
+ return NULL;
+ }
+
+ *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+ return pss;
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
+ if (EVP_MD_type(md) == NID_sha1) {
+ return 1;
+ }
+ *palg = X509_ALGOR_new();
+ if (*palg == NULL) {
+ return 0;
+ }
+ X509_ALGOR_set_md(*palg, md);
+ return 1;
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
+ X509_ALGOR *algtmp = NULL;
+ ASN1_STRING *stmp = NULL;
+ *palg = NULL;
+
+ if (EVP_MD_type(mgf1md) == NID_sha1) {
+ return 1;
+ }
+ /* need to embed algorithm ID inside another */
+ if (!rsa_md_to_algor(&algtmp, mgf1md) ||
+ !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
+ goto err;
+ }
+ *palg = X509_ALGOR_new();
+ if (!*palg) {
+ goto err;
+ }
+ X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+ stmp = NULL;
+
+err:
+ ASN1_STRING_free(stmp);
+ X509_ALGOR_free(algtmp);
+ if (*palg) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ md = EVP_get_digestbyobj(alg->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ }
+ return md;
+}
+
+/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ /* Check mask and lookup mask hash algorithm */
+ if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+ maskHash == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ return NULL;
+ }
+ md = EVP_get_digestbyobj(maskHash->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ return NULL;
+ }
+ return md;
+}
+
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+ const EVP_MD *sigmd, *mgf1md;
+ int saltlen;
+ if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) ||
+ !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) ||
+ !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) {
+ return 0;
+ }
+
+ EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ if (saltlen == -1) {
+ saltlen = EVP_MD_size(sigmd);
+ } else if (saltlen == -2) {
+ saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+ if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
+ saltlen--;
+ }
+ } else {
+ return 0;
+ }
+
+ int ret = 0;
+ ASN1_STRING *os = NULL;
+ RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
+ if (!pss) {
+ goto err;
+ }
+
+ if (saltlen != 20) {
+ pss->saltLength = ASN1_INTEGER_new();
+ if (!pss->saltLength ||
+ !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
+ goto err;
+ }
+ }
+
+ if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
+ !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
+ goto err;
+ }
+
+ /* Finally create string with pss parameter encoding. */
+ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
+ goto err;
+ }
+
+ X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
+ os = NULL;
+ ret = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ ASN1_STRING_free(os);
+ return ret;
+}
+
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
+ assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+ /* Decode PSS parameters */
+ int ret = 0;
+ X509_ALGOR *maskHash;
+ RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+ if (pss == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+
+ const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
+ const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm);
+ if (mgf1md == NULL || md == NULL) {
+ goto err;
+ }
+
+ int saltlen = 20;
+ if (pss->saltLength != NULL) {
+ saltlen = ASN1_INTEGER_get(pss->saltLength);
+
+ /* Could perform more salt length sanity checks but the main
+ * RSA routines will trap other invalid values anyway. */
+ if (saltlen < 0) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+ }
+
+ /* low-level routines support only trailer field 0xbc (value 1)
+ * and PKCS#1 says we should reject any other value anyway. */
+ if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+
+ EVP_PKEY_CTX *pkctx;
+ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ X509_ALGOR_free(maskHash);
+ return ret;
+}
+
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+ ASN1_PCTX *pctx) {
+ assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+ int rv = 0;
+ X509_ALGOR *maskHash;
+ RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+ if (!pss) {
+ if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
+ goto err;
+ }
+ rv = 1;
+ goto err;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Hash Algorithm: ") <= 0) {
+ goto err;
+ }
+
+ if (pss->hashAlgorithm) {
+ if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
+ goto err;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Mask Algorithm: ") <= 0) {
+ goto err;
+ }
+
+ if (pss->maskGenAlgorithm) {
+ if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
+ BIO_puts(bp, " with ") <= 0) {
+ goto err;
+ }
+
+ if (maskHash) {
+ if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "INVALID") <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Salt Length: 0x") <= 0) {
+ goto err;
+ }
+
+ if (pss->saltLength) {
+ if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "14 (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Trailer Field: 0x") <= 0) {
+ goto err;
+ }
+
+ if (pss->trailerField) {
+ if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "BC (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ rv = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ X509_ALGOR_free(maskHash);
+ return rv;
+}
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
index a2d8bc74..6c347cb8 100644
--- a/src/crypto/x509/t_crl.c
+++ b/src/crypto/x509/t_crl.c
@@ -61,69 +61,68 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
#ifndef OPENSSL_NO_FP_API
int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
- {
- BIO *b;
- int ret;
+{
+ BIO *b;
+ int ret;
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=X509_CRL_print(b, x);
- BIO_free(b);
- return(ret);
- }
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = X509_CRL_print(b, x);
+ BIO_free(b);
+ return (ret);
+}
#endif
int X509_CRL_print(BIO *out, X509_CRL *x)
{
- STACK_OF(X509_REVOKED) *rev;
- X509_REVOKED *r;
- long l;
- size_t i;
- char *p;
+ STACK_OF(X509_REVOKED) *rev;
+ X509_REVOKED *r;
+ long l;
+ size_t i;
+ char *p;
- BIO_printf(out, "Certificate Revocation List (CRL):\n");
- l = X509_CRL_get_version(x);
- BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
- X509_signature_print(out, x->sig_alg, NULL);
- p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
- BIO_printf(out,"%8sIssuer: %s\n","",p);
- OPENSSL_free(p);
- BIO_printf(out,"%8sLast Update: ","");
- ASN1_TIME_print(out,X509_CRL_get_lastUpdate(x));
- BIO_printf(out,"\n%8sNext Update: ","");
- if (X509_CRL_get_nextUpdate(x))
- ASN1_TIME_print(out,X509_CRL_get_nextUpdate(x));
- else BIO_printf(out,"NONE");
- BIO_printf(out,"\n");
+ BIO_printf(out, "Certificate Revocation List (CRL):\n");
+ l = X509_CRL_get_version(x);
+ BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l);
+ X509_signature_print(out, x->sig_alg, NULL);
+ p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0);
+ BIO_printf(out, "%8sIssuer: %s\n", "", p);
+ OPENSSL_free(p);
+ BIO_printf(out, "%8sLast Update: ", "");
+ ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x));
+ BIO_printf(out, "\n%8sNext Update: ", "");
+ if (X509_CRL_get_nextUpdate(x))
+ ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x));
+ else
+ BIO_printf(out, "NONE");
+ BIO_printf(out, "\n");
- X509V3_extensions_print(out, "CRL extensions",
- x->crl->extensions, 0, 8);
+ X509V3_extensions_print(out, "CRL extensions", x->crl->extensions, 0, 8);
- rev = X509_CRL_get_REVOKED(x);
+ rev = X509_CRL_get_REVOKED(x);
- if(sk_X509_REVOKED_num(rev) > 0)
- BIO_printf(out, "Revoked Certificates:\n");
- else BIO_printf(out, "No Revoked Certificates.\n");
+ if (sk_X509_REVOKED_num(rev) > 0)
+ BIO_printf(out, "Revoked Certificates:\n");
+ else
+ BIO_printf(out, "No Revoked Certificates.\n");
- for(i = 0; i < sk_X509_REVOKED_num(rev); i++) {
- r = sk_X509_REVOKED_value(rev, i);
- BIO_printf(out," Serial Number: ");
- i2a_ASN1_INTEGER(out,r->serialNumber);
- BIO_printf(out,"\n Revocation Date: ");
- ASN1_TIME_print(out,r->revocationDate);
- BIO_printf(out,"\n");
- X509V3_extensions_print(out, "CRL entry extensions",
- r->extensions, 0, 8);
- }
- X509_signature_print(out, x->sig_alg, x->signature);
+ for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
+ r = sk_X509_REVOKED_value(rev, i);
+ BIO_printf(out, " Serial Number: ");
+ i2a_ASN1_INTEGER(out, r->serialNumber);
+ BIO_printf(out, "\n Revocation Date: ");
+ ASN1_TIME_print(out, r->revocationDate);
+ BIO_printf(out, "\n");
+ X509V3_extensions_print(out, "CRL entry extensions",
+ r->extensions, 0, 8);
+ }
+ X509_signature_print(out, x->sig_alg, x->signature);
- return 1;
+ return 1;
}
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index 7785ebff..1fba9b43 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -64,437 +64,443 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-#include "../evp/internal.h"
+#include "internal.h"
+
#ifndef OPENSSL_NO_FP_API
-int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
- {
- BIO *b;
- int ret;
-
- if ((b=BIO_new(BIO_s_file())) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- return(0);
- }
- BIO_set_fp(b,fp,BIO_NOCLOSE);
- ret=X509_print_ex(b, x, nmflag, cflag);
- BIO_free(b);
- return(ret);
- }
+int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
+ unsigned long cflag)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = X509_print_ex(b, x, nmflag, cflag);
+ BIO_free(b);
+ return (ret);
+}
int X509_print_fp(FILE *fp, X509 *x)
- {
- return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
- }
+{
+ return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
#endif
int X509_print(BIO *bp, X509 *x)
{
- return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+ return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
-int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
- {
- long l;
- int ret=0,i;
- char *m=NULL,mlch = ' ';
- int nmindent = 0;
- X509_CINF *ci;
- ASN1_INTEGER *bs;
- EVP_PKEY *pkey=NULL;
- const char *neg;
-
- if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
- mlch = '\n';
- nmindent = 12;
- }
-
- if(nmflags == X509_FLAG_COMPAT)
- nmindent = 16;
-
- ci=x->cert_info;
- if(!(cflag & X509_FLAG_NO_HEADER))
- {
- if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
- if (BIO_write(bp," Data:\n",10) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_VERSION))
- {
- l=X509_get_version(x);
- if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_SERIAL))
- {
-
- if (BIO_write(bp," Serial Number:",22) <= 0) goto err;
-
- bs=X509_get_serialNumber(x);
- if (bs->length <= (int)sizeof(long))
- {
- l=ASN1_INTEGER_get(bs);
- if (bs->type == V_ASN1_NEG_INTEGER)
- {
- l= -l;
- neg="-";
- }
- else
- neg="";
- if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
- goto err;
- }
- else
- {
- neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
- if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
-
- for (i=0; i<bs->length; i++)
- {
- if (BIO_printf(bp,"%02x%c",bs->data[i],
- ((i+1 == bs->length)?'\n':':')) <= 0)
- goto err;
- }
- }
-
- }
-
- if(!(cflag & X509_FLAG_NO_SIGNAME))
- {
- if (X509_signature_print(bp, ci->signature, NULL) <= 0)
- goto err;
- }
-
- if(!(cflag & X509_FLAG_NO_ISSUER))
- {
- if (BIO_printf(bp," Issuer:%c",mlch) <= 0) goto err;
- if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
- if (BIO_write(bp,"\n",1) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_VALIDITY))
- {
- if (BIO_write(bp," Validity\n",17) <= 0) goto err;
- if (BIO_write(bp," Not Before: ",24) <= 0) goto err;
- if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
- if (BIO_write(bp,"\n Not After : ",25) <= 0) goto err;
- if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
- if (BIO_write(bp,"\n",1) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_SUBJECT))
- {
- if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err;
- if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
- if (BIO_write(bp,"\n",1) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_PUBKEY))
- {
- if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0)
- goto err;
- if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
- goto err;
- if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
- goto err;
- if (BIO_puts(bp, "\n") <= 0)
- goto err;
-
- pkey=X509_get_pubkey(x);
- if (pkey == NULL)
- {
- BIO_printf(bp,"%12sUnable to load Public Key\n","");
- BIO_print_errors(bp);
- }
- else
- {
- EVP_PKEY_print_public(bp, pkey, 16, NULL);
- EVP_PKEY_free(pkey);
- }
- }
-
- if(!(cflag & X509_FLAG_NO_IDS))
- {
- if (ci->issuerUID)
- {
- if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0)
- goto err;
- if (!X509_signature_dump(bp, ci->issuerUID, 12))
- goto err;
- }
- if (ci->subjectUID)
- {
- if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0)
- goto err;
- if (!X509_signature_dump(bp, ci->subjectUID, 12))
- goto err;
- }
- }
-
- if (!(cflag & X509_FLAG_NO_EXTENSIONS))
- X509V3_extensions_print(bp, "X509v3 extensions",
- ci->extensions, cflag, 8);
-
- if(!(cflag & X509_FLAG_NO_SIGDUMP))
- {
- if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
- }
- if(!(cflag & X509_FLAG_NO_AUX))
- {
- if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
- }
- ret=1;
-err:
- if (m != NULL) OPENSSL_free(m);
- return(ret);
- }
-
-int X509_ocspid_print (BIO *bp, X509 *x)
- {
- unsigned char *der=NULL ;
- unsigned char *dertmp;
- int derlen;
- int i;
- unsigned char SHA1md[SHA_DIGEST_LENGTH];
-
- /* display the hash of the subject as it would appear
- in OCSP requests */
- if (BIO_printf(bp," Subject OCSP hash: ") <= 0)
- goto err;
- derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
- if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
- goto err;
- i2d_X509_NAME(x->cert_info->subject, &dertmp);
-
- if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
- goto err;
- for (i=0; i < SHA_DIGEST_LENGTH; i++)
- {
- if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
- }
- OPENSSL_free (der);
- der=NULL;
-
- /* display the hash of the public key as it would appear
- in OCSP requests */
- if (BIO_printf(bp,"\n Public key OCSP hash: ") <= 0)
- goto err;
-
- if (!EVP_Digest(x->cert_info->key->public_key->data,
- x->cert_info->key->public_key->length,
- SHA1md, NULL, EVP_sha1(), NULL))
- goto err;
- for (i=0; i < SHA_DIGEST_LENGTH; i++)
- {
- if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
- goto err;
- }
- BIO_printf(bp,"\n");
-
- return (1);
-err:
- if (der != NULL) OPENSSL_free(der);
- return(0);
- }
+int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
+ unsigned long cflag)
+{
+ long l;
+ int ret = 0, i;
+ char *m = NULL, mlch = ' ';
+ int nmindent = 0;
+ X509_CINF *ci;
+ ASN1_INTEGER *bs;
+ EVP_PKEY *pkey = NULL;
+ const char *neg;
+
+ if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+ mlch = '\n';
+ nmindent = 12;
+ }
+
+ if (nmflags == X509_FLAG_COMPAT)
+ nmindent = 16;
+
+ ci = x->cert_info;
+ if (!(cflag & X509_FLAG_NO_HEADER)) {
+ if (BIO_write(bp, "Certificate:\n", 13) <= 0)
+ goto err;
+ if (BIO_write(bp, " Data:\n", 10) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_VERSION)) {
+ l = X509_get_version(x);
+ if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_SERIAL)) {
+
+ if (BIO_write(bp, " Serial Number:", 22) <= 0)
+ goto err;
+
+ bs = X509_get_serialNumber(x);
+ if (bs->length < (int)sizeof(long)
+ || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) {
+ l = ASN1_INTEGER_get(bs);
+ if (bs->type == V_ASN1_NEG_INTEGER) {
+ l = -l;
+ neg = "-";
+ } else
+ neg = "";
+ if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0)
+ goto err;
+ } else {
+ neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
+ if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
+ goto err;
+
+ for (i = 0; i < bs->length; i++) {
+ if (BIO_printf(bp, "%02x%c", bs->data[i],
+ ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
+ goto err;
+ }
+ }
+
+ }
+
+ if (!(cflag & X509_FLAG_NO_SIGNAME)) {
+ if (X509_signature_print(bp, ci->signature, NULL) <= 0)
+ goto err;
+ }
+
+ if (!(cflag & X509_FLAG_NO_ISSUER)) {
+ if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
+ goto err;
+ if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
+ < 0)
+ goto err;
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_VALIDITY)) {
+ if (BIO_write(bp, " Validity\n", 17) <= 0)
+ goto err;
+ if (BIO_write(bp, " Not Before: ", 24) <= 0)
+ goto err;
+ if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
+ goto err;
+ if (BIO_write(bp, "\n Not After : ", 25) <= 0)
+ goto err;
+ if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
+ goto err;
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_SUBJECT)) {
+ if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
+ goto err;
+ if (X509_NAME_print_ex
+ (bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
+ goto err;
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_PUBKEY)) {
+ if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
+ goto err;
+ if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
+ goto err;
+ if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
+ goto err;
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ pkey = X509_get_pubkey(x);
+ if (pkey == NULL) {
+ BIO_printf(bp, "%12sUnable to load Public Key\n", "");
+ BIO_print_errors(bp);
+ } else {
+ EVP_PKEY_print_public(bp, pkey, 16, NULL);
+ EVP_PKEY_free(pkey);
+ }
+ }
+
+ if (!(cflag & X509_FLAG_NO_IDS)) {
+ if (ci->issuerUID) {
+ if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->issuerUID, 12))
+ goto err;
+ }
+ if (ci->subjectUID) {
+ if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->subjectUID, 12))
+ goto err;
+ }
+ }
+
+ if (!(cflag & X509_FLAG_NO_EXTENSIONS))
+ X509V3_extensions_print(bp, "X509v3 extensions",
+ ci->extensions, cflag, 8);
+
+ if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
+ if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
+ goto err;
+ }
+ if (!(cflag & X509_FLAG_NO_AUX)) {
+ if (!X509_CERT_AUX_print(bp, x->aux, 0))
+ goto err;
+ }
+ ret = 1;
+ err:
+ if (m != NULL)
+ OPENSSL_free(m);
+ return (ret);
+}
+
+int X509_ocspid_print(BIO *bp, X509 *x)
+{
+ unsigned char *der = NULL;
+ unsigned char *dertmp;
+ int derlen;
+ int i;
+ unsigned char SHA1md[SHA_DIGEST_LENGTH];
+
+ /*
+ * display the hash of the subject as it would appear in OCSP requests
+ */
+ if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
+ goto err;
+ derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
+ if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL)
+ goto err;
+ i2d_X509_NAME(x->cert_info->subject, &dertmp);
+
+ if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+ goto err;
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+ if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
+ goto err;
+ }
+ OPENSSL_free(der);
+ der = NULL;
+
+ /*
+ * display the hash of the public key as it would appear in OCSP requests
+ */
+ if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0)
+ goto err;
+
+ if (!EVP_Digest(x->cert_info->key->public_key->data,
+ x->cert_info->key->public_key->length,
+ SHA1md, NULL, EVP_sha1(), NULL))
+ goto err;
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+ if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
+ goto err;
+ }
+ BIO_printf(bp, "\n");
+
+ return (1);
+ err:
+ if (der != NULL)
+ OPENSSL_free(der);
+ return (0);
+}
int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
{
- int sig_nid;
- if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0;
- if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
-
- sig_nid = OBJ_obj2nid(sigalg->algorithm);
- if (sig_nid != NID_undef)
- {
- int pkey_nid, dig_nid;
- const EVP_PKEY_ASN1_METHOD *ameth;
- if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid))
- {
- ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
- if (ameth && ameth->sig_print)
- return ameth->sig_print(bp, sigalg, sig, 9, 0);
- }
- }
- if (sig)
- return X509_signature_dump(bp, sig, 9);
- else if (BIO_puts(bp, "\n") <= 0)
- return 0;
- return 1;
+ if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
+ return 0;
+ if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
+ return 0;
+
+ /* RSA-PSS signatures have parameters to print. */
+ int sig_nid = OBJ_obj2nid(sigalg->algorithm);
+ if (sig_nid == NID_rsassaPss &&
+ !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) {
+ return 0;
+ }
+
+ if (sig)
+ return X509_signature_dump(bp, sig, 9);
+ else if (BIO_puts(bp, "\n") <= 0)
+ return 0;
+ return 1;
}
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
- {
- int i,n;
- char buf[80];
- const char *p;
-
- if (v == NULL) return(0);
- n=0;
- p=(const char *)v->data;
- for (i=0; i<v->length; i++)
- {
- if ((p[i] > '~') || ((p[i] < ' ') &&
- (p[i] != '\n') && (p[i] != '\r')))
- buf[n]='.';
- else
- buf[n]=p[i];
- n++;
- if (n >= 80)
- {
- if (BIO_write(bp,buf,n) <= 0)
- return(0);
- n=0;
- }
- }
- if (n > 0)
- if (BIO_write(bp,buf,n) <= 0)
- return(0);
- return(1);
- }
+{
+ int i, n;
+ char buf[80];
+ const char *p;
+
+ if (v == NULL)
+ return (0);
+ n = 0;
+ p = (const char *)v->data;
+ for (i = 0; i < v->length; i++) {
+ if ((p[i] > '~') || ((p[i] < ' ') &&
+ (p[i] != '\n') && (p[i] != '\r')))
+ buf[n] = '.';
+ else
+ buf[n] = p[i];
+ n++;
+ if (n >= 80) {
+ if (BIO_write(bp, buf, n) <= 0)
+ return (0);
+ n = 0;
+ }
+ }
+ if (n > 0)
+ if (BIO_write(bp, buf, n) <= 0)
+ return (0);
+ return (1);
+}
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
- if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
- if(tm->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_print(bp, tm);
- BIO_write(bp,"Bad time value",14);
- return(0);
+ if (tm->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_print(bp, tm);
+ if (tm->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_print(bp, tm);
+ BIO_write(bp, "Bad time value", 14);
+ return (0);
}
-static const char *const mon[12]=
- {
- "Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"
- };
+static const char *const mon[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
- {
- char *v;
- int gmt=0;
- int i;
- int y=0,M=0,d=0,h=0,m=0,s=0;
- char *f = NULL;
- int f_len = 0;
-
- i=tm->length;
- v=(char *)tm->data;
-
- if (i < 12) goto err;
- if (v[i-1] == 'Z') gmt=1;
- for (i=0; i<12; i++)
- if ((v[i] > '9') || (v[i] < '0')) goto err;
- y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
- M= (v[4]-'0')*10+(v[5]-'0');
- if ((M > 12) || (M < 1)) goto err;
- 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 (tm->length >= 14 &&
- (v[12] >= '0') && (v[12] <= '9') &&
- (v[13] >= '0') && (v[13] <= '9'))
- {
- s= (v[12]-'0')*10+(v[13]-'0');
- /* Check for fractions of seconds. */
- if (tm->length >= 15 && v[14] == '.')
- {
- int l = tm->length;
- f = &v[14]; /* The decimal point. */
- f_len = 1;
- while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
- ++f_len;
- }
- }
-
- if (BIO_printf(bp,"%s %2d %02d:%02d:%02d%.*s %d%s",
- mon[M-1],d,h,m,s,f_len,f,y,(gmt)?" GMT":"") <= 0)
- return(0);
- else
- return(1);
-err:
- BIO_write(bp,"Bad time value",14);
- return(0);
- }
+{
+ char *v;
+ int gmt = 0;
+ int i;
+ int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+ char *f = NULL;
+ int f_len = 0;
+
+ i = tm->length;
+ v = (char *)tm->data;
+
+ if (i < 12)
+ goto err;
+ if (v[i - 1] == 'Z')
+ gmt = 1;
+ for (i = 0; i < 12; i++)
+ if ((v[i] > '9') || (v[i] < '0'))
+ goto err;
+ y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] -
+ '0');
+ M = (v[4] - '0') * 10 + (v[5] - '0');
+ if ((M > 12) || (M < 1))
+ goto err;
+ 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 (tm->length >= 14 &&
+ (v[12] >= '0') && (v[12] <= '9') &&
+ (v[13] >= '0') && (v[13] <= '9')) {
+ s = (v[12] - '0') * 10 + (v[13] - '0');
+ /* Check for fractions of seconds. */
+ if (tm->length >= 15 && v[14] == '.') {
+ int l = tm->length;
+ f = &v[14]; /* The decimal point. */
+ f_len = 1;
+ while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
+ ++f_len;
+ }
+ }
+
+ if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+ mon[M - 1], d, h, m, s, f_len, f, y,
+ (gmt) ? " GMT" : "") <= 0)
+ return (0);
+ else
+ return (1);
+ err:
+ BIO_write(bp, "Bad time value", 14);
+ return (0);
+}
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
- {
- const char *v;
- int gmt=0;
- int i;
- int y=0,M=0,d=0,h=0,m=0,s=0;
-
- i=tm->length;
- v=(const char *)tm->data;
-
- if (i < 10) goto err;
- if (v[i-1] == 'Z') gmt=1;
- for (i=0; i<10; i++)
- if ((v[i] > '9') || (v[i] < '0')) goto err;
- y= (v[0]-'0')*10+(v[1]-'0');
- if (y < 50) y+=100;
- M= (v[2]-'0')*10+(v[3]-'0');
- if ((M > 12) || (M < 1)) goto err;
- 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 (tm->length >=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",
- mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
- return(0);
- else
- return(1);
-err:
- BIO_write(bp,"Bad time value",14);
- return(0);
- }
+{
+ const char *v;
+ int gmt = 0;
+ int i;
+ int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+
+ i = tm->length;
+ v = (const char *)tm->data;
+
+ if (i < 10)
+ goto err;
+ if (v[i - 1] == 'Z')
+ gmt = 1;
+ for (i = 0; i < 10; i++)
+ if ((v[i] > '9') || (v[i] < '0'))
+ goto err;
+ y = (v[0] - '0') * 10 + (v[1] - '0');
+ if (y < 50)
+ y += 100;
+ M = (v[2] - '0') * 10 + (v[3] - '0');
+ if ((M > 12) || (M < 1))
+ goto err;
+ 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 (tm->length >= 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",
+ mon[M - 1], d, h, m, s, y + 1900,
+ (gmt) ? " GMT" : "") <= 0)
+ return (0);
+ else
+ return (1);
+ err:
+ BIO_write(bp, "Bad time value", 14);
+ return (0);
+}
int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
- {
- char *s,*c,*b;
- int ret=0,l,i;
-
- l=80-2-obase;
-
- b=X509_NAME_oneline(name,NULL,0);
- if (!b)
- return 0;
- if (!*b)
- {
- OPENSSL_free(b);
- return 1;
- }
- s=b+1; /* skip the first slash */
-
- c=s;
- for (;;)
- {
- if ( ((*s == '/') &&
- ((s[1] >= 'A') && (s[1] <= 'Z') && (
- (s[2] == '=') ||
- ((s[2] >= 'A') && (s[2] <= 'Z') &&
- (s[3] == '='))
- ))) ||
- (*s == '\0'))
- {
- i=s-c;
- if (BIO_write(bp,c,i) != i) goto err;
- c=s+1; /* skip following slash */
- if (*s != '\0')
- {
- if (BIO_write(bp,", ",2) != 2) goto err;
- }
- l--;
- }
- if (*s == '\0') break;
- s++;
- l--;
- }
-
- ret=1;
- if (0)
- {
-err:
- OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- }
- OPENSSL_free(b);
- return(ret);
- }
+{
+ char *s, *c, *b;
+ int ret = 0, l, i;
+
+ l = 80 - 2 - obase;
+
+ b = X509_NAME_oneline(name, NULL, 0);
+ if (!b)
+ return 0;
+ if (!*b) {
+ OPENSSL_free(b);
+ return 1;
+ }
+ s = b + 1; /* skip the first slash */
+
+ c = s;
+ for (;;) {
+ if (((*s == '/') &&
+ ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
+ ((s[2] >= 'A')
+ && (s[2] <= 'Z')
+ && (s[3] == '='))
+ ))) || (*s == '\0')) {
+ i = s - c;
+ if (BIO_write(bp, c, i) != i)
+ goto err;
+ c = s + 1; /* skip following slash */
+ if (*s != '\0') {
+ if (BIO_write(bp, ", ", 2) != 2)
+ goto err;
+ }
+ l--;
+ }
+ if (*s == '\0')
+ break;
+ s++;
+ l--;
+ }
+
+ ret = 1;
+ if (0) {
+ err:
+ OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+ }
+ OPENSSL_free(b);
+ return (ret);
+}
diff --git a/src/crypto/x509/t_x509a.c b/src/crypto/x509/t_x509a.c
index 76672688..54368286 100644
--- a/src/crypto/x509/t_x509a.c
+++ b/src/crypto/x509/t_x509a.c
@@ -60,50 +60,52 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
/* X509_CERT_AUX and string set routines */
int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
{
- char oidstr[80], first;
- size_t i;
- int j;
- if(!aux) return 1;
- if(aux->trust) {
- first = 1;
- BIO_printf(out, "%*sTrusted Uses:\n%*s",
- indent, "", indent + 2, "");
- for(i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
- if(!first) BIO_puts(out, ", ");
- else first = 0;
- OBJ_obj2txt(oidstr, sizeof oidstr,
- sk_ASN1_OBJECT_value(aux->trust, i), 0);
- BIO_puts(out, oidstr);
- }
- BIO_puts(out, "\n");
- } else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
- if(aux->reject) {
- first = 1;
- BIO_printf(out, "%*sRejected Uses:\n%*s",
- indent, "", indent + 2, "");
- for(i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
- if(!first) BIO_puts(out, ", ");
- else first = 0;
- OBJ_obj2txt(oidstr, sizeof oidstr,
- sk_ASN1_OBJECT_value(aux->reject, i), 0);
- BIO_puts(out, oidstr);
- }
- BIO_puts(out, "\n");
- } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
- if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "",
- aux->alias->data);
- if(aux->keyid) {
- BIO_printf(out, "%*sKey Id: ", indent, "");
- for(j = 0; j < aux->keyid->length; j++)
- BIO_printf(out, "%s%02X",
- j ? ":" : "",
- aux->keyid->data[j]);
- BIO_write(out,"\n",1);
- }
- return 1;
+ char oidstr[80], first;
+ size_t i;
+ int j;
+ if (!aux)
+ return 1;
+ if (aux->trust) {
+ first = 1;
+ BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, "");
+ for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
+ if (!first)
+ BIO_puts(out, ", ");
+ else
+ first = 0;
+ OBJ_obj2txt(oidstr, sizeof oidstr,
+ sk_ASN1_OBJECT_value(aux->trust, i), 0);
+ BIO_puts(out, oidstr);
+ }
+ BIO_puts(out, "\n");
+ } else
+ BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
+ if (aux->reject) {
+ first = 1;
+ BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, "");
+ for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
+ if (!first)
+ BIO_puts(out, ", ");
+ else
+ first = 0;
+ OBJ_obj2txt(oidstr, sizeof oidstr,
+ sk_ASN1_OBJECT_value(aux->reject, i), 0);
+ BIO_puts(out, oidstr);
+ }
+ BIO_puts(out, "\n");
+ } else
+ BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
+ if (aux->alias)
+ BIO_printf(out, "%*sAlias: %s\n", indent, "", aux->alias->data);
+ if (aux->keyid) {
+ BIO_printf(out, "%*sKey Id: ", indent, "");
+ for (j = 0; j < aux->keyid->length; j++)
+ BIO_printf(out, "%s%02X", j ? ":" : "", aux->keyid->data[j]);
+ BIO_write(out, "\n", 1);
+ }
+ return 1;
}
diff --git a/src/crypto/x509/vpm_int.h b/src/crypto/x509/vpm_int.h
index 9edbd5ad..9c55defc 100644
--- a/src/crypto/x509/vpm_int.h
+++ b/src/crypto/x509/vpm_int.h
@@ -1,6 +1,7 @@
/* vpm_int.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2013.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2013.
*/
/* ====================================================================
* Copyright (c) 2013 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -58,13 +59,12 @@
/* internal only structure to hold additional X509_VERIFY_PARAM data */
-struct X509_VERIFY_PARAM_ID_st
- {
- STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
- unsigned int hostflags; /* Flags to control matching features */
- char *peername; /* Matching hostname in peer certificate */
- char *email; /* If not NULL email address to match */
- size_t emaillen;
- unsigned char *ip; /* If not NULL IP address to match */
- size_t iplen; /* Length of IP address */
- };
+struct X509_VERIFY_PARAM_ID_st {
+ STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
+ unsigned int hostflags; /* Flags to control matching features */
+ char *peername; /* Matching hostname in peer certificate */
+ char *email; /* If not NULL email address to match */
+ size_t emaillen;
+ unsigned char *ip; /* If not NULL IP address to match */
+ size_t iplen; /* Length of IP address */
+};
diff --git a/src/crypto/x509/x509.c b/src/crypto/x509/x509.c
index 31f9e1eb..188fd496 100644
--- a/src/crypto/x509/x509.c
+++ b/src/crypto/x509/x509.c
@@ -57,9 +57,14 @@
#include <openssl/x509.h>
#include <openssl/bio.h>
+#include <openssl/err.h>
#include <openssl/mem.h>
+/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define
+ * it to avoid downstream churn. */
+OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM)
+
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
int ptype, void *pval, uint8_t *penc, int penclen) {
uint8_t **ppenc = NULL;
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
index 14914849..b83d32f9 100644
--- a/src/crypto/x509/x509_att.c
+++ b/src/crypto/x509/x509_att.c
@@ -62,292 +62,314 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
-
int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
{
- return sk_X509_ATTRIBUTE_num(x);
+ return sk_X509_ATTRIBUTE_num(x);
}
int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
- int lastpos)
+ int lastpos)
{
- const ASN1_OBJECT *obj;
+ const ASN1_OBJECT *obj;
- obj=OBJ_nid2obj(nid);
- if (obj == NULL) return(-2);
- return(X509at_get_attr_by_OBJ(x,obj,lastpos));
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ return (-2);
+ return (X509at_get_attr_by_OBJ(x, obj, lastpos));
}
-int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj,
- int lastpos)
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
+ const ASN1_OBJECT *obj, int lastpos)
{
- int n;
- X509_ATTRIBUTE *ex;
-
- if (sk == NULL) return(-1);
- lastpos++;
- if (lastpos < 0)
- lastpos=0;
- n=sk_X509_ATTRIBUTE_num(sk);
- for ( ; lastpos < n; lastpos++)
- {
- ex=sk_X509_ATTRIBUTE_value(sk,lastpos);
- if (OBJ_cmp(ex->object,obj) == 0)
- return(lastpos);
- }
- return(-1);
+ int n;
+ X509_ATTRIBUTE *ex;
+
+ if (sk == NULL)
+ return (-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos = 0;
+ n = sk_X509_ATTRIBUTE_num(sk);
+ for (; lastpos < n; lastpos++) {
+ ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
+ if (OBJ_cmp(ex->object, obj) == 0)
+ return (lastpos);
+ }
+ return (-1);
}
X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
{
- if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
- return NULL;
- else
- return sk_X509_ATTRIBUTE_value(x,loc);
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc)
+ return NULL;
+ else
+ return sk_X509_ATTRIBUTE_value(x, loc);
}
X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
{
- X509_ATTRIBUTE *ret;
+ X509_ATTRIBUTE *ret;
- if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
- return(NULL);
- ret=sk_X509_ATTRIBUTE_delete(x,loc);
- return(ret);
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc)
+ return (NULL);
+ ret = sk_X509_ATTRIBUTE_delete(x, loc);
+ return (ret);
}
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
- X509_ATTRIBUTE *attr)
+ X509_ATTRIBUTE *attr)
{
- X509_ATTRIBUTE *new_attr=NULL;
- STACK_OF(X509_ATTRIBUTE) *sk=NULL;
-
- if (x == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
- goto err2;
- }
-
- if (*x == NULL)
- {
- if ((sk=sk_X509_ATTRIBUTE_new_null()) == NULL)
- goto err;
- }
- else
- sk= *x;
-
- if ((new_attr=X509_ATTRIBUTE_dup(attr)) == NULL)
- goto err2;
- if (!sk_X509_ATTRIBUTE_push(sk,new_attr))
- goto err;
- if (*x == NULL)
- *x=sk;
- return(sk);
-err:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-err2:
- if (new_attr != NULL) X509_ATTRIBUTE_free(new_attr);
- if (sk != NULL) sk_X509_ATTRIBUTE_free(sk);
- return(NULL);
+ X509_ATTRIBUTE *new_attr = NULL;
+ STACK_OF(X509_ATTRIBUTE) *sk = NULL;
+
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+ goto err2;
+ }
+
+ if (*x == NULL) {
+ if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
+ goto err;
+ } else
+ sk = *x;
+
+ if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
+ goto err2;
+ if (!sk_X509_ATTRIBUTE_push(sk, new_attr))
+ goto err;
+ if (*x == NULL)
+ *x = sk;
+ return (sk);
+ err:
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ err2:
+ if (new_attr != NULL)
+ X509_ATTRIBUTE_free(new_attr);
+ if (sk != NULL)
+ sk_X509_ATTRIBUTE_free(sk);
+ return (NULL);
}
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
- const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
+ **x, const ASN1_OBJECT *obj,
+ int type,
+ const unsigned char *bytes,
+ int len)
{
- X509_ATTRIBUTE *attr;
- STACK_OF(X509_ATTRIBUTE) *ret;
- attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
- if(!attr) return 0;
- ret = X509at_add1_attr(x, attr);
- X509_ATTRIBUTE_free(attr);
- return ret;
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
+ if (!attr)
+ return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
}
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
- int nid, int type,
- const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
+ **x, int nid, int type,
+ const unsigned char *bytes,
+ int len)
{
- X509_ATTRIBUTE *attr;
- STACK_OF(X509_ATTRIBUTE) *ret;
- attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
- if(!attr) return 0;
- ret = X509at_add1_attr(x, attr);
- X509_ATTRIBUTE_free(attr);
- return ret;
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
+ if (!attr)
+ return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
}
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
- const char *attrname, int type,
- const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
+ **x, const char *attrname,
+ int type,
+ const unsigned char *bytes,
+ int len)
{
- X509_ATTRIBUTE *attr;
- STACK_OF(X509_ATTRIBUTE) *ret;
- attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
- if(!attr) return 0;
- ret = X509at_add1_attr(x, attr);
- X509_ATTRIBUTE_free(attr);
- return ret;
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
+ if (!attr)
+ return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
}
void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
- ASN1_OBJECT *obj, int lastpos, int type)
+ ASN1_OBJECT *obj, int lastpos, int type)
{
- int i;
- X509_ATTRIBUTE *at;
- i = X509at_get_attr_by_OBJ(x, obj, lastpos);
- if (i == -1)
- return NULL;
- if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
- return NULL;
- at = X509at_get_attr(x, i);
- if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
- return NULL;
- return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
+ int i;
+ X509_ATTRIBUTE *at;
+ i = X509at_get_attr_by_OBJ(x, obj, lastpos);
+ if (i == -1)
+ return NULL;
+ if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
+ return NULL;
+ at = X509at_get_attr(x, i);
+ if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
+ return NULL;
+ return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
- int atrtype, const void *data, int len)
+ int atrtype, const void *data,
+ int len)
{
- const ASN1_OBJECT *obj;
-
- obj=OBJ_nid2obj(nid);
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
- return(NULL);
- }
- return X509_ATTRIBUTE_create_by_OBJ(attr,obj,atrtype,data,len);
+ const ASN1_OBJECT *obj;
+
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+ return (NULL);
+ }
+ return X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
- const ASN1_OBJECT *obj, int atrtype, const void *data, int len)
+ const ASN1_OBJECT *obj,
+ int atrtype, const void *data,
+ int len)
{
- X509_ATTRIBUTE *ret;
-
- if ((attr == NULL) || (*attr == NULL))
- {
- if ((ret=X509_ATTRIBUTE_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
- }
- else
- ret= *attr;
-
- if (!X509_ATTRIBUTE_set1_object(ret,obj))
- goto err;
- if (!X509_ATTRIBUTE_set1_data(ret,atrtype,data,len))
- goto err;
-
- if ((attr != NULL) && (*attr == NULL)) *attr=ret;
- return(ret);
-err:
- if ((attr == NULL) || (ret != *attr))
- X509_ATTRIBUTE_free(ret);
- return(NULL);
+ X509_ATTRIBUTE *ret;
+
+ if ((attr == NULL) || (*attr == NULL)) {
+ if ((ret = X509_ATTRIBUTE_new()) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ } else
+ ret = *attr;
+
+ if (!X509_ATTRIBUTE_set1_object(ret, obj))
+ goto err;
+ if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len))
+ goto err;
+
+ if ((attr != NULL) && (*attr == NULL))
+ *attr = ret;
+ return (ret);
+ err:
+ if ((attr == NULL) || (ret != *attr))
+ X509_ATTRIBUTE_free(ret);
+ return (NULL);
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
- const char *atrname, int type, const unsigned char *bytes, int len)
- {
- ASN1_OBJECT *obj;
- X509_ATTRIBUTE *nattr;
-
- obj=OBJ_txt2obj(atrname, 0);
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
- ERR_add_error_data(2, "name=", atrname);
- return(NULL);
- }
- nattr = X509_ATTRIBUTE_create_by_OBJ(attr,obj,type,bytes,len);
- ASN1_OBJECT_free(obj);
- return nattr;
- }
+ const char *atrname, int type,
+ const unsigned char *bytes,
+ int len)
+{
+ ASN1_OBJECT *obj;
+ X509_ATTRIBUTE *nattr;
+
+ obj = OBJ_txt2obj(atrname, 0);
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", atrname);
+ return (NULL);
+ }
+ nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
+ ASN1_OBJECT_free(obj);
+ return nattr;
+}
int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
{
- if ((attr == NULL) || (obj == NULL))
- return(0);
- ASN1_OBJECT_free(attr->object);
- attr->object=OBJ_dup(obj);
- return attr->object != NULL;
+ if ((attr == NULL) || (obj == NULL))
+ return (0);
+ ASN1_OBJECT_free(attr->object);
+ attr->object = OBJ_dup(obj);
+ return attr->object != NULL;
}
-int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
+ const void *data, int len)
{
- ASN1_TYPE *ttmp;
- ASN1_STRING *stmp = NULL;
- int atype = 0;
- if (!attr) return 0;
- if(attrtype & MBSTRING_FLAG) {
- stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
- OBJ_obj2nid(attr->object));
- if(!stmp) {
- OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
- return 0;
- }
- atype = stmp->type;
- } else if (len != -1){
- if(!(stmp = ASN1_STRING_type_new(attrtype))) goto err;
- if(!ASN1_STRING_set(stmp, data, len)) goto err;
- atype = attrtype;
- }
- if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
- attr->single = 0;
- /* This is a bit naughty because the attribute should really have
- * at least one value but some types use and zero length SET and
- * require this.
- */
- if (attrtype == 0)
- return 1;
- if(!(ttmp = ASN1_TYPE_new())) goto err;
- if ((len == -1) && !(attrtype & MBSTRING_FLAG))
- {
- if (!ASN1_TYPE_set1(ttmp, attrtype, data))
- goto err;
- }
- else
- ASN1_TYPE_set(ttmp, atype, stmp);
- if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err;
- return 1;
- err:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
+ ASN1_TYPE *ttmp;
+ ASN1_STRING *stmp = NULL;
+ int atype = 0;
+ if (!attr)
+ return 0;
+ if (attrtype & MBSTRING_FLAG) {
+ stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
+ OBJ_obj2nid(attr->object));
+ if (!stmp) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+ return 0;
+ }
+ atype = stmp->type;
+ } else if (len != -1) {
+ if (!(stmp = ASN1_STRING_type_new(attrtype)))
+ goto err;
+ if (!ASN1_STRING_set(stmp, data, len))
+ goto err;
+ atype = attrtype;
+ }
+ if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
+ goto err;
+ attr->single = 0;
+ /*
+ * This is a bit naughty because the attribute should really have at
+ * least one value but some types use and zero length SET and require
+ * this.
+ */
+ if (attrtype == 0)
+ return 1;
+ if (!(ttmp = ASN1_TYPE_new()))
+ goto err;
+ if ((len == -1) && !(attrtype & MBSTRING_FLAG)) {
+ if (!ASN1_TYPE_set1(ttmp, attrtype, data))
+ goto err;
+ } else
+ ASN1_TYPE_set(ttmp, atype, stmp);
+ if (!sk_ASN1_TYPE_push(attr->value.set, ttmp))
+ goto err;
+ return 1;
+ err:
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
}
int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
{
- if(!attr->single) return sk_ASN1_TYPE_num(attr->value.set);
- if(attr->value.single) return 1;
- return 0;
+ if (!attr->single)
+ return sk_ASN1_TYPE_num(attr->value.set);
+ if (attr->value.single)
+ return 1;
+ return 0;
}
ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
{
- if (attr == NULL) return(NULL);
- return(attr->object);
+ if (attr == NULL)
+ return (NULL);
+ return (attr->object);
}
void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
- int atrtype, void *data)
+ int atrtype, void *data)
{
- ASN1_TYPE *ttmp;
- ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
- if(!ttmp) return NULL;
- if(atrtype != ASN1_TYPE_get(ttmp)){
- OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE);
- return NULL;
- }
- return ttmp->value.ptr;
+ ASN1_TYPE *ttmp;
+ ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
+ if (!ttmp)
+ return NULL;
+ if (atrtype != ASN1_TYPE_get(ttmp)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE);
+ return NULL;
+ }
+ return ttmp->value.ptr;
}
ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
{
- if (attr == NULL) return(NULL);
- if(idx >= X509_ATTRIBUTE_count(attr)) return NULL;
- if(!attr->single) return sk_ASN1_TYPE_value(attr->value.set, idx);
- else return attr->value.single;
+ if (attr == NULL)
+ return (NULL);
+ if (idx >= X509_ATTRIBUTE_count(attr))
+ return NULL;
+ if (!attr->single)
+ return sk_ASN1_TYPE_value(attr->value.set, idx);
+ else
+ return attr->value.single;
}
diff --git a/src/crypto/x509/x509_cmp.c b/src/crypto/x509/x509_cmp.c
index 0e35f3ea..32862ebc 100644
--- a/src/crypto/x509/x509_cmp.c
+++ b/src/crypto/x509/x509_cmp.c
@@ -67,424 +67,408 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
- {
- int i;
- X509_CINF *ai,*bi;
-
- ai=a->cert_info;
- bi=b->cert_info;
- i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
- if (i) return(i);
- return(X509_NAME_cmp(ai->issuer,bi->issuer));
- }
+{
+ int i;
+ X509_CINF *ai, *bi;
+
+ ai = a->cert_info;
+ bi = b->cert_info;
+ i = M_ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber);
+ if (i)
+ return (i);
+ return (X509_NAME_cmp(ai->issuer, bi->issuer));
+}
unsigned long X509_issuer_and_serial_hash(X509 *a)
- {
- unsigned long ret=0;
- EVP_MD_CTX ctx;
- unsigned char md[16];
- char *f;
-
- EVP_MD_CTX_init(&ctx);
- f=X509_NAME_oneline(a->cert_info->issuer,NULL,0);
- if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
- goto err;
- if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,strlen(f)))
- goto err;
- OPENSSL_free(f);
- if(!EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data,
- (unsigned long)a->cert_info->serialNumber->length))
- goto err;
- if (!EVP_DigestFinal_ex(&ctx,&(md[0]),NULL))
- goto err;
- ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
- ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
- )&0xffffffffL;
- err:
- EVP_MD_CTX_cleanup(&ctx);
- return(ret);
- }
-
+{
+ unsigned long ret = 0;
+ EVP_MD_CTX ctx;
+ unsigned char md[16];
+ char *f;
+
+ EVP_MD_CTX_init(&ctx);
+ f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0);
+ if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f)))
+ goto err;
+ OPENSSL_free(f);
+ if (!EVP_DigestUpdate
+ (&ctx, (unsigned char *)a->cert_info->serialNumber->data,
+ (unsigned long)a->cert_info->serialNumber->length))
+ goto err;
+ if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL))
+ goto err;
+ ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+ ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+ ) & 0xffffffffL;
+ err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return (ret);
+}
+
int X509_issuer_name_cmp(const X509 *a, const X509 *b)
- {
- return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer));
- }
+{
+ return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer));
+}
int X509_subject_name_cmp(const X509 *a, const X509 *b)
- {
- return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
- }
+{
+ return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject));
+}
int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
- {
- return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
- }
+{
+ return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer));
+}
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
- {
- return memcmp(a->sha1_hash, b->sha1_hash, 20);
- }
+{
+ return memcmp(a->sha1_hash, b->sha1_hash, 20);
+}
X509_NAME *X509_get_issuer_name(X509 *a)
- {
- return(a->cert_info->issuer);
- }
+{
+ return (a->cert_info->issuer);
+}
unsigned long X509_issuer_name_hash(X509 *x)
- {
- return(X509_NAME_hash(x->cert_info->issuer));
- }
+{
+ return (X509_NAME_hash(x->cert_info->issuer));
+}
unsigned long X509_issuer_name_hash_old(X509 *x)
- {
- return(X509_NAME_hash_old(x->cert_info->issuer));
- }
+{
+ return (X509_NAME_hash_old(x->cert_info->issuer));
+}
X509_NAME *X509_get_subject_name(X509 *a)
- {
- return(a->cert_info->subject);
- }
+{
+ return (a->cert_info->subject);
+}
ASN1_INTEGER *X509_get_serialNumber(X509 *a)
- {
- return(a->cert_info->serialNumber);
- }
+{
+ return (a->cert_info->serialNumber);
+}
unsigned long X509_subject_name_hash(X509 *x)
- {
- return(X509_NAME_hash(x->cert_info->subject));
- }
+{
+ return (X509_NAME_hash(x->cert_info->subject));
+}
unsigned long X509_subject_name_hash_old(X509 *x)
- {
- return(X509_NAME_hash_old(x->cert_info->subject));
- }
-
-/* Compare two certificates: they must be identical for
- * this to work. NB: Although "cmp" operations are generally
- * prototyped to take "const" arguments (eg. for use in
- * STACKs), the way X509 handling is - these operations may
- * involve ensuring the hashes are up-to-date and ensuring
- * certain cert information is cached. So this is the point
- * where the "depth-first" constification tree has to halt
- * with an evil cast.
+{
+ return (X509_NAME_hash_old(x->cert_info->subject));
+}
+
+/*
+ * Compare two certificates: they must be identical for this to work. NB:
+ * Although "cmp" operations are generally prototyped to take "const"
+ * arguments (eg. for use in STACKs), the way X509 handling is - these
+ * operations may involve ensuring the hashes are up-to-date and ensuring
+ * certain cert information is cached. So this is the point where the
+ * "depth-first" constification tree has to halt with an evil cast.
*/
int X509_cmp(const X509 *a, const X509 *b)
{
- int rv;
- /* ensure hash is valid */
- X509_check_purpose((X509 *)a, -1, 0);
- X509_check_purpose((X509 *)b, -1, 0);
-
- rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
- if (rv)
- return rv;
- /* Check for match against stored encoding too */
- if (!a->cert_info->enc.modified && !b->cert_info->enc.modified)
- {
- rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
- if (rv)
- return rv;
- return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
- a->cert_info->enc.len);
- }
- return rv;
+ int rv;
+ /* ensure hash is valid */
+ X509_check_purpose((X509 *)a, -1, 0);
+ X509_check_purpose((X509 *)b, -1, 0);
+
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ if (rv)
+ return rv;
+ /* Check for match against stored encoding too */
+ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) {
+ rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
+ if (rv)
+ return rv;
+ return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
+ a->cert_info->enc.len);
+ }
+ return rv;
}
-
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
- {
- int ret;
+{
+ int ret;
- /* Ensure canonical encoding is present and up to date */
+ /* Ensure canonical encoding is present and up to date */
- if (!a->canon_enc || a->modified)
- {
- ret = i2d_X509_NAME((X509_NAME *)a, NULL);
- if (ret < 0)
- return -2;
- }
+ if (!a->canon_enc || a->modified) {
+ ret = i2d_X509_NAME((X509_NAME *)a, NULL);
+ if (ret < 0)
+ return -2;
+ }
- if (!b->canon_enc || b->modified)
- {
- ret = i2d_X509_NAME((X509_NAME *)b, NULL);
- if (ret < 0)
- return -2;
- }
+ if (!b->canon_enc || b->modified) {
+ ret = i2d_X509_NAME((X509_NAME *)b, NULL);
+ if (ret < 0)
+ return -2;
+ }
- ret = a->canon_enclen - b->canon_enclen;
+ ret = a->canon_enclen - b->canon_enclen;
- if (ret)
- return ret;
+ if (ret)
+ return ret;
- return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+ return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
- }
+}
unsigned long X509_NAME_hash(X509_NAME *x)
- {
- unsigned long ret=0;
- unsigned char md[SHA_DIGEST_LENGTH];
-
- /* Make sure X509_NAME structure contains valid cached encoding */
- i2d_X509_NAME(x,NULL);
- if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
- NULL))
- return 0;
-
- ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
- ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
- )&0xffffffffL;
- return(ret);
- }
-
+{
+ unsigned long ret = 0;
+ unsigned char md[SHA_DIGEST_LENGTH];
+
+ /* Make sure X509_NAME structure contains valid cached encoding */
+ i2d_X509_NAME(x, NULL);
+ if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
+ NULL))
+ return 0;
+
+ ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+ ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+ ) & 0xffffffffL;
+ return (ret);
+}
-/* I now DER encode the name and hash it. Since I cache the DER encoding,
- * this is reasonably efficient. */
+/*
+ * I now DER encode the name and hash it. Since I cache the DER encoding,
+ * this is reasonably efficient.
+ */
unsigned long X509_NAME_hash_old(X509_NAME *x)
- {
- EVP_MD_CTX md_ctx;
- unsigned long ret=0;
- unsigned char md[16];
-
- /* Make sure X509_NAME structure contains valid cached encoding */
- i2d_X509_NAME(x,NULL);
- EVP_MD_CTX_init(&md_ctx);
- /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
- if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
- && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
- && EVP_DigestFinal_ex(&md_ctx,md,NULL))
- ret=(((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
- ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
- )&0xffffffffL;
- EVP_MD_CTX_cleanup(&md_ctx);
-
- return(ret);
- }
+{
+ EVP_MD_CTX md_ctx;
+ unsigned long ret = 0;
+ unsigned char md[16];
+
+ /* Make sure X509_NAME structure contains valid cached encoding */
+ i2d_X509_NAME(x, NULL);
+ EVP_MD_CTX_init(&md_ctx);
+ /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
+ if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
+ && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
+ && EVP_DigestFinal_ex(&md_ctx, md, NULL))
+ ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+ ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+ ) & 0xffffffffL;
+ EVP_MD_CTX_cleanup(&md_ctx);
+
+ return (ret);
+}
/* Search a stack of X509 for a match */
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
- ASN1_INTEGER *serial)
- {
- size_t i;
- X509_CINF cinf;
- X509 x,*x509=NULL;
-
- if(!sk) return NULL;
-
- x.cert_info= &cinf;
- cinf.serialNumber=serial;
- cinf.issuer=name;
-
- for (i=0; i<sk_X509_num(sk); i++)
- {
- x509=sk_X509_value(sk,i);
- if (X509_issuer_and_serial_cmp(x509,&x) == 0)
- return(x509);
- }
- return(NULL);
- }
+ ASN1_INTEGER *serial)
+{
+ size_t i;
+ X509_CINF cinf;
+ X509 x, *x509 = NULL;
+
+ if (!sk)
+ return NULL;
+
+ x.cert_info = &cinf;
+ cinf.serialNumber = serial;
+ cinf.issuer = name;
+
+ for (i = 0; i < sk_X509_num(sk); i++) {
+ x509 = sk_X509_value(sk, i);
+ if (X509_issuer_and_serial_cmp(x509, &x) == 0)
+ return (x509);
+ }
+ return (NULL);
+}
X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
- {
- X509 *x509;
- size_t i;
-
- for (i=0; i<sk_X509_num(sk); i++)
- {
- x509=sk_X509_value(sk,i);
- if (X509_NAME_cmp(X509_get_subject_name(x509),name) == 0)
- return(x509);
- }
- return(NULL);
- }
+{
+ X509 *x509;
+ size_t i;
+
+ for (i = 0; i < sk_X509_num(sk); i++) {
+ x509 = sk_X509_value(sk, i);
+ if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
+ return (x509);
+ }
+ return (NULL);
+}
EVP_PKEY *X509_get_pubkey(X509 *x)
- {
- if ((x == NULL) || (x->cert_info == NULL))
- return(NULL);
- return(X509_PUBKEY_get(x->cert_info->key));
- }
+{
+ if ((x == NULL) || (x->cert_info == NULL))
+ return (NULL);
+ return (X509_PUBKEY_get(x->cert_info->key));
+}
ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
- {
- if(!x) return NULL;
- return x->cert_info->key->public_key;
- }
-
+{
+ if (!x)
+ return NULL;
+ return x->cert_info->key->public_key;
+}
int X509_check_private_key(X509 *x, EVP_PKEY *k)
- {
- EVP_PKEY *xk;
- int ret;
-
- xk=X509_get_pubkey(x);
-
- if (xk)
- ret = EVP_PKEY_cmp(xk, k);
- else
- ret = -2;
-
- switch (ret)
- {
- case 1:
- break;
- case 0:
- OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
- break;
- case -1:
- OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
- break;
- case -2:
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
- }
- if (xk)
- EVP_PKEY_free(xk);
- if (ret > 0)
- return 1;
- return 0;
- }
-
-/* Check a suite B algorithm is permitted: pass in a public key and
- * the NID of its signature (or 0 if no signature). The pflags is
- * a pointer to a flags field which must contain the suite B verification
- * flags.
- */
+{
+ EVP_PKEY *xk;
+ int ret;
+
+ xk = X509_get_pubkey(x);
+
+ if (xk)
+ ret = EVP_PKEY_cmp(xk, k);
+ else
+ ret = -2;
+
+ switch (ret) {
+ case 1:
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+ }
+ if (xk)
+ EVP_PKEY_free(xk);
+ if (ret > 0)
+ return 1;
+ return 0;
+}
+/*
+ * Check a suite B algorithm is permitted: pass in a public key and the NID
+ * of its signature (or 0 if no signature). The pflags is a pointer to a
+ * flags field which must contain the suite B verification flags.
+ */
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
- {
- const EC_GROUP *grp = NULL;
- int curve_nid;
- if (pkey && pkey->type == EVP_PKEY_EC)
- grp = EC_KEY_get0_group(pkey->pkey.ec);
- if (!grp)
- return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
- curve_nid = EC_GROUP_get_curve_name(grp);
- /* Check curve is consistent with LOS */
- if (curve_nid == NID_secp384r1) /* P-384 */
- {
- /* Check signature algorithm is consistent with
- * curve.
- */
- if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
- return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
- if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
- return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
- /* If we encounter P-384 we cannot use P-256 later */
- *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
- }
- else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */
- {
- if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
- return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
- if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
- return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
- }
- else
- return X509_V_ERR_SUITE_B_INVALID_CURVE;
-
- return X509_V_OK;
- }
+{
+ const EC_GROUP *grp = NULL;
+ int curve_nid;
+ if (pkey && pkey->type == EVP_PKEY_EC)
+ grp = EC_KEY_get0_group(pkey->pkey.ec);
+ if (!grp)
+ return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
+ curve_nid = EC_GROUP_get_curve_name(grp);
+ /* Check curve is consistent with LOS */
+ if (curve_nid == NID_secp384r1) { /* P-384 */
+ /*
+ * Check signature algorithm is consistent with curve.
+ */
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ /* If we encounter P-384 we cannot use P-256 later */
+ *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
+ } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ } else
+ return X509_V_ERR_SUITE_B_INVALID_CURVE;
+
+ return X509_V_OK;
+}
int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
- unsigned long flags)
- {
- int rv, sign_nid;
- size_t i;
- EVP_PKEY *pk = NULL;
- unsigned long tflags;
- if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
- return X509_V_OK;
- tflags = flags;
- /* If no EE certificate passed in must be first in chain */
- if (x == NULL)
- {
- x = sk_X509_value(chain, 0);
- i = 1;
- }
- else
- i = 0;
-
- if (X509_get_version(x) != 2)
- {
- rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
- /* Correct error depth */
- i = 0;
- goto end;
- }
-
- pk = X509_get_pubkey(x);
- /* Check EE key only */
- rv = check_suite_b(pk, -1, &tflags);
- if (rv != X509_V_OK)
- {
- /* Correct error depth */
- i = 0;
- goto end;
- }
- for(; i < sk_X509_num(chain); i++)
- {
- sign_nid = X509_get_signature_nid(x);
- x = sk_X509_value(chain, i);
- if (X509_get_version(x) != 2)
- {
- rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
- goto end;
- }
- EVP_PKEY_free(pk);
- pk = X509_get_pubkey(x);
- rv = check_suite_b(pk, sign_nid, &tflags);
- if (rv != X509_V_OK)
- goto end;
- }
-
- /* Final check: root CA signature */
- rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
- end:
- if (pk)
- EVP_PKEY_free(pk);
- if (rv != X509_V_OK)
- {
- /* Invalid signature or LOS errors are for previous cert */
- if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
- || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
- i--;
- /* If we have LOS error and flags changed then we are signing
- * P-384 with P-256. Use more meaninggul error.
- */
- if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
- rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
- if (perror_depth)
- *perror_depth = i;
- }
- return rv;
- }
+ unsigned long flags)
+{
+ int rv, sign_nid;
+ size_t i;
+ EVP_PKEY *pk = NULL;
+ unsigned long tflags;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ tflags = flags;
+ /* If no EE certificate passed in must be first in chain */
+ if (x == NULL) {
+ x = sk_X509_value(chain, 0);
+ i = 1;
+ } else
+ i = 0;
+
+ if (X509_get_version(x) != 2) {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+
+ pk = X509_get_pubkey(x);
+ /* Check EE key only */
+ rv = check_suite_b(pk, -1, &tflags);
+ if (rv != X509_V_OK) {
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+ for (; i < sk_X509_num(chain); i++) {
+ sign_nid = X509_get_signature_nid(x);
+ x = sk_X509_value(chain, i);
+ if (X509_get_version(x) != 2) {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ goto end;
+ }
+ EVP_PKEY_free(pk);
+ pk = X509_get_pubkey(x);
+ rv = check_suite_b(pk, sign_nid, &tflags);
+ if (rv != X509_V_OK)
+ goto end;
+ }
+
+ /* Final check: root CA signature */
+ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
+ end:
+ if (pk)
+ EVP_PKEY_free(pk);
+ if (rv != X509_V_OK) {
+ /* Invalid signature or LOS errors are for previous cert */
+ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
+ || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
+ i--;
+ /*
+ * If we have LOS error and flags changed then we are signing P-384
+ * with P-256. Use more meaninggul error.
+ */
+ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
+ rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
+ if (perror_depth)
+ *perror_depth = i;
+ }
+ return rv;
+}
int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
- {
- int sign_nid;
- if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
- return X509_V_OK;
- sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
- return check_suite_b(pk, sign_nid, &flags);
- }
-
-/* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
- * count but it has the same effect by duping the STACK and upping the ref
- * of each X509 structure.
+{
+ int sign_nid;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
+ return check_suite_b(pk, sign_nid, &flags);
+}
+
+/*
+ * Not strictly speaking an "up_ref" as a STACK doesn't have a reference
+ * count but it has the same effect by duping the STACK and upping the ref of
+ * each X509 structure.
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
- {
- STACK_OF(X509) *ret;
- size_t i;
- ret = sk_X509_dup(chain);
- for (i = 0; i < sk_X509_num(ret); i++)
- {
- X509_up_ref(sk_X509_value(ret, i));
- }
- return ret;
- }
+{
+ STACK_OF(X509) *ret;
+ size_t i;
+ ret = sk_X509_dup(chain);
+ for (i = 0; i < sk_X509_num(ret); i++) {
+ X509_up_ref(sk_X509_value(ret, i));
+ }
+ return ret;
+}
diff --git a/src/crypto/x509/x509_d2.c b/src/crypto/x509/x509_d2.c
index 2161d851..69ae54ed 100644
--- a/src/crypto/x509/x509_d2.c
+++ b/src/crypto/x509/x509_d2.c
@@ -58,48 +58,49 @@
#include <openssl/err.h>
#include <openssl/x509.h>
-
#ifndef OPENSSL_NO_STDIO
int X509_STORE_set_default_paths(X509_STORE *ctx)
- {
- X509_LOOKUP *lookup;
+{
+ X509_LOOKUP *lookup;
+
+ lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
+ if (lookup == NULL)
+ return (0);
+ X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
- lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
- if (lookup == NULL) return(0);
- X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
+ lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ return (0);
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
- lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
- if (lookup == NULL) return(0);
- X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
-
- /* clear any errors */
- ERR_clear_error();
+ /* clear any errors */
+ ERR_clear_error();
- return(1);
- }
+ return (1);
+}
int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
- const char *path)
- {
- X509_LOOKUP *lookup;
+ const char *path)
+{
+ X509_LOOKUP *lookup;
- if (file != NULL)
- {
- lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
- if (lookup == NULL) return(0);
- if (X509_LOOKUP_load_file(lookup,file,X509_FILETYPE_PEM) != 1)
- return(0);
- }
- if (path != NULL)
- {
- lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
- if (lookup == NULL) return(0);
- if (X509_LOOKUP_add_dir(lookup,path,X509_FILETYPE_PEM) != 1)
- return(0);
- }
- if ((path == NULL) && (file == NULL))
- return(0);
- return(1);
- }
+ if (file != NULL) {
+ lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
+ if (lookup == NULL)
+ return (0);
+ if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1)
+ return (0);
+ }
+ if (path != NULL) {
+ lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ return (0);
+ if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
+ return (0);
+ }
+ if ((path == NULL) && (file == NULL))
+ return (0);
+ return (1);
+}
#endif
diff --git a/src/crypto/x509/x509_def.c b/src/crypto/x509/x509_def.c
index dbae289f..2bf2240c 100644
--- a/src/crypto/x509/x509_def.c
+++ b/src/crypto/x509/x509_def.c
@@ -57,32 +57,42 @@
#include <openssl/x509.h>
-
/* TODO(fork): cleanup */
#define OPENSSLDIR "/etc/ssl"
-#define X509_CERT_AREA OPENSSLDIR
-#define X509_CERT_DIR OPENSSLDIR "/certs"
-#define X509_CERT_FILE OPENSSLDIR "/cert.pem"
-#define X509_PRIVATE_DIR OPENSSLDIR "/private"
+#define X509_CERT_AREA OPENSSLDIR
+#define X509_CERT_DIR OPENSSLDIR "/certs"
+#define X509_CERT_FILE OPENSSLDIR "/cert.pem"
+#define X509_PRIVATE_DIR OPENSSLDIR "/private"
#define X509_CERT_DIR_EVP "SSL_CERT_DIR"
#define X509_CERT_FILE_EVP "SSL_CERT_FILE"
const char *X509_get_default_private_dir(void)
- { return(X509_PRIVATE_DIR); }
-
+{
+ return (X509_PRIVATE_DIR);
+}
+
const char *X509_get_default_cert_area(void)
- { return(X509_CERT_AREA); }
+{
+ return (X509_CERT_AREA);
+}
const char *X509_get_default_cert_dir(void)
- { return(X509_CERT_DIR); }
+{
+ return (X509_CERT_DIR);
+}
const char *X509_get_default_cert_file(void)
- { return(X509_CERT_FILE); }
+{
+ return (X509_CERT_FILE);
+}
const char *X509_get_default_cert_dir_env(void)
- { return(X509_CERT_DIR_EVP); }
+{
+ return (X509_CERT_DIR_EVP);
+}
const char *X509_get_default_cert_file_env(void)
- { return(X509_CERT_FILE_EVP); }
-
+{
+ return (X509_CERT_FILE_EVP);
+}
diff --git a/src/crypto/x509/x509_ext.c b/src/crypto/x509/x509_ext.c
index 2f1e0c5a..a329f6fa 100644
--- a/src/crypto/x509/x509_ext.c
+++ b/src/crypto/x509/x509_ext.c
@@ -62,145 +62,145 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
int X509_CRL_get_ext_count(X509_CRL *x)
- {
- return(X509v3_get_ext_count(x->crl->extensions));
- }
+{
+ return (X509v3_get_ext_count(x->crl->extensions));
+}
int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos)
- {
- return(X509v3_get_ext_by_NID(x->crl->extensions,nid,lastpos));
- }
+{
+ return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos));
+}
int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos)
- {
- return(X509v3_get_ext_by_OBJ(x->crl->extensions,obj,lastpos));
- }
+{
+ return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos));
+}
int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos)
- {
- return(X509v3_get_ext_by_critical(x->crl->extensions,crit,lastpos));
- }
+{
+ return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos));
+}
X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc)
- {
- return(X509v3_get_ext(x->crl->extensions,loc));
- }
+{
+ return (X509v3_get_ext(x->crl->extensions, loc));
+}
X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc)
- {
- return(X509v3_delete_ext(x->crl->extensions,loc));
- }
+{
+ return (X509v3_delete_ext(x->crl->extensions, loc));
+}
void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx)
{
- return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
+ return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
}
int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
- unsigned long flags)
+ unsigned long flags)
{
- return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags);
+ return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags);
}
int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc)
- {
- return(X509v3_add_ext(&(x->crl->extensions),ex,loc) != NULL);
- }
+{
+ return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL);
+}
int X509_get_ext_count(X509 *x)
- {
- return(X509v3_get_ext_count(x->cert_info->extensions));
- }
+{
+ return (X509v3_get_ext_count(x->cert_info->extensions));
+}
int X509_get_ext_by_NID(X509 *x, int nid, int lastpos)
- {
- return(X509v3_get_ext_by_NID(x->cert_info->extensions,nid,lastpos));
- }
+{
+ return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos));
+}
int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos)
- {
- return(X509v3_get_ext_by_OBJ(x->cert_info->extensions,obj,lastpos));
- }
+{
+ return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos));
+}
int X509_get_ext_by_critical(X509 *x, int crit, int lastpos)
- {
- return(X509v3_get_ext_by_critical(x->cert_info->extensions,crit,lastpos));
- }
+{
+ return (X509v3_get_ext_by_critical
+ (x->cert_info->extensions, crit, lastpos));
+}
X509_EXTENSION *X509_get_ext(X509 *x, int loc)
- {
- return(X509v3_get_ext(x->cert_info->extensions,loc));
- }
+{
+ return (X509v3_get_ext(x->cert_info->extensions, loc));
+}
X509_EXTENSION *X509_delete_ext(X509 *x, int loc)
- {
- return(X509v3_delete_ext(x->cert_info->extensions,loc));
- }
+{
+ return (X509v3_delete_ext(x->cert_info->extensions, loc));
+}
int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc)
- {
- return(X509v3_add_ext(&(x->cert_info->extensions),ex,loc) != NULL);
- }
+{
+ return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL);
+}
void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)
{
- return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
+ return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
}
int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
- unsigned long flags)
+ unsigned long flags)
{
- return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit,
- flags);
+ return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit,
+ flags);
}
int X509_REVOKED_get_ext_count(X509_REVOKED *x)
- {
- return(X509v3_get_ext_count(x->extensions));
- }
+{
+ return (X509v3_get_ext_count(x->extensions));
+}
int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos)
- {
- return(X509v3_get_ext_by_NID(x->extensions,nid,lastpos));
- }
+{
+ return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos));
+}
int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj,
- int lastpos)
- {
- return(X509v3_get_ext_by_OBJ(x->extensions,obj,lastpos));
- }
+ int lastpos)
+{
+ return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos));
+}
int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos)
- {
- return(X509v3_get_ext_by_critical(x->extensions,crit,lastpos));
- }
+{
+ return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos));
+}
X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc)
- {
- return(X509v3_get_ext(x->extensions,loc));
- }
+{
+ return (X509v3_get_ext(x->extensions, loc));
+}
X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc)
- {
- return(X509v3_delete_ext(x->extensions,loc));
- }
+{
+ return (X509v3_delete_ext(x->extensions, loc));
+}
int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc)
- {
- return(X509v3_add_ext(&(x->extensions),ex,loc) != NULL);
- }
+{
+ return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL);
+}
void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx)
{
- return X509V3_get_d2i(x->extensions, nid, crit, idx);
+ return X509V3_get_d2i(x->extensions, nid, crit, idx);
}
int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
- unsigned long flags)
+ unsigned long flags)
{
- return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
+ return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
}
IMPLEMENT_ASN1_SET_OF(X509_EXTENSION)
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index 5751f758..ec3f300b 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -66,673 +66,640 @@
#include "../internal.h"
-
X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
- {
- X509_LOOKUP *ret;
-
- ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
- if (ret == NULL) return NULL;
-
- ret->init=0;
- ret->skip=0;
- ret->method=method;
- ret->method_data=NULL;
- ret->store_ctx=NULL;
- if ((method->new_item != NULL) && !method->new_item(ret))
- {
- OPENSSL_free(ret);
- return NULL;
- }
- return ret;
- }
+{
+ X509_LOOKUP *ret;
+
+ ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
+ if (ret == NULL)
+ return NULL;
+
+ ret->init = 0;
+ ret->skip = 0;
+ ret->method = method;
+ ret->method_data = NULL;
+ ret->store_ctx = NULL;
+ if ((method->new_item != NULL) && !method->new_item(ret)) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+}
void X509_LOOKUP_free(X509_LOOKUP *ctx)
- {
- if (ctx == NULL) return;
- if ( (ctx->method != NULL) &&
- (ctx->method->free != NULL))
- (*ctx->method->free)(ctx);
- OPENSSL_free(ctx);
- }
+{
+ if (ctx == NULL)
+ return;
+ if ((ctx->method != NULL) && (ctx->method->free != NULL))
+ (*ctx->method->free) (ctx);
+ OPENSSL_free(ctx);
+}
int X509_LOOKUP_init(X509_LOOKUP *ctx)
- {
- if (ctx->method == NULL) return 0;
- if (ctx->method->init != NULL)
- return ctx->method->init(ctx);
- else
- return 1;
- }
+{
+ if (ctx->method == NULL)
+ return 0;
+ if (ctx->method->init != NULL)
+ return ctx->method->init(ctx);
+ else
+ return 1;
+}
int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
- {
- if (ctx->method == NULL) return 0;
- if (ctx->method->shutdown != NULL)
- return ctx->method->shutdown(ctx);
- else
- return 1;
- }
+{
+ if (ctx->method == NULL)
+ return 0;
+ if (ctx->method->shutdown != NULL)
+ return ctx->method->shutdown(ctx);
+ else
+ return 1;
+}
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
- char **ret)
- {
- if (ctx->method == NULL) return -1;
- if (ctx->method->ctrl != NULL)
- return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
- else
- return 1;
- }
+ char **ret)
+{
+ if (ctx->method == NULL)
+ return -1;
+ if (ctx->method->ctrl != NULL)
+ return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
+ else
+ return 1;
+}
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
- X509_OBJECT *ret)
- {
- if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
- return X509_LU_FAIL;
- if (ctx->skip) return 0;
- return ctx->method->get_by_subject(ctx,type,name,ret);
- }
+ X509_OBJECT *ret)
+{
+ if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
+ return X509_LU_FAIL;
+ if (ctx->skip)
+ return 0;
+ return ctx->method->get_by_subject(ctx, type, name, ret);
+}
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
- ASN1_INTEGER *serial, X509_OBJECT *ret)
- {
- if ((ctx->method == NULL) ||
- (ctx->method->get_by_issuer_serial == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
- }
+ ASN1_INTEGER *serial, X509_OBJECT *ret)
+{
+ if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
+}
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
- unsigned char *bytes, int len, X509_OBJECT *ret)
- {
- if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
- }
+ unsigned char *bytes, int len,
+ X509_OBJECT *ret)
+{
+ if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
+}
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
- X509_OBJECT *ret)
- {
- if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_alias(ctx,type,str,len,ret);
- }
-
-
+ X509_OBJECT *ret)
+{
+ if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_alias(ctx, type, str, len, ret);
+}
+
static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
- {
- int ret;
-
- ret=((*a)->type - (*b)->type);
- if (ret) return ret;
- switch ((*a)->type)
- {
- case X509_LU_X509:
- ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
- break;
- case X509_LU_CRL:
- ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
- break;
- default:
- /* abort(); */
- return 0;
- }
- return ret;
- }
+{
+ int ret;
+
+ ret = ((*a)->type - (*b)->type);
+ if (ret)
+ return ret;
+ switch ((*a)->type) {
+ case X509_LU_X509:
+ ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
+ break;
+ case X509_LU_CRL:
+ ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ return ret;
+}
X509_STORE *X509_STORE_new(void)
- {
- X509_STORE *ret;
-
- if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
- return NULL;
- memset(ret, 0, sizeof(*ret));
- CRYPTO_MUTEX_init(&ret->objs_lock);
- ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
- if (ret->objs == NULL)
- goto err;
- ret->cache = 1;
- ret->get_cert_methods = sk_X509_LOOKUP_new_null();
- if (ret->get_cert_methods == NULL)
- goto err;
- ret->param = X509_VERIFY_PARAM_new();
- if (ret->param == NULL)
- goto err;
-
- ret->references = 1;
- return ret;
-err:
- if (ret)
- {
- CRYPTO_MUTEX_cleanup(&ret->objs_lock);
- if (ret->param)
- X509_VERIFY_PARAM_free(ret->param);
- if (ret->get_cert_methods)
- sk_X509_LOOKUP_free(ret->get_cert_methods);
- if (ret->objs)
- sk_X509_OBJECT_free(ret->objs);
- OPENSSL_free(ret);
- }
- return NULL;
- }
+{
+ X509_STORE *ret;
+
+ if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
+ return NULL;
+ memset(ret, 0, sizeof(*ret));
+ CRYPTO_MUTEX_init(&ret->objs_lock);
+ ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
+ if (ret->objs == NULL)
+ goto err;
+ ret->cache = 1;
+ ret->get_cert_methods = sk_X509_LOOKUP_new_null();
+ if (ret->get_cert_methods == NULL)
+ goto err;
+ ret->param = X509_VERIFY_PARAM_new();
+ if (ret->param == NULL)
+ goto err;
+
+ ret->references = 1;
+ return ret;
+ err:
+ if (ret) {
+ CRYPTO_MUTEX_cleanup(&ret->objs_lock);
+ if (ret->param)
+ X509_VERIFY_PARAM_free(ret->param);
+ if (ret->get_cert_methods)
+ sk_X509_LOOKUP_free(ret->get_cert_methods);
+ if (ret->objs)
+ sk_X509_OBJECT_free(ret->objs);
+ OPENSSL_free(ret);
+ }
+ return NULL;
+}
+
+void X509_STORE_up_ref(X509_STORE *store)
+{
+ CRYPTO_refcount_inc(&store->references);
+}
static void cleanup(X509_OBJECT *a)
- {
- if (a->type == X509_LU_X509)
- {
- X509_free(a->data.x509);
- }
- else if (a->type == X509_LU_CRL)
- {
- X509_CRL_free(a->data.crl);
- }
- else
- {
- /* abort(); */
- }
-
- OPENSSL_free(a);
- }
+{
+ if (a == NULL) {
+ return;
+ }
+ if (a->type == X509_LU_X509) {
+ X509_free(a->data.x509);
+ } else if (a->type == X509_LU_CRL) {
+ X509_CRL_free(a->data.crl);
+ } else {
+ /* abort(); */
+ }
+
+ OPENSSL_free(a);
+}
void X509_STORE_free(X509_STORE *vfy)
- {
- size_t j;
- STACK_OF(X509_LOOKUP) *sk;
- X509_LOOKUP *lu;
-
- if (vfy == NULL)
- return;
-
- if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
- return;
- }
-
- CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
-
- sk=vfy->get_cert_methods;
- for (j=0; j<sk_X509_LOOKUP_num(sk); j++)
- {
- lu=sk_X509_LOOKUP_value(sk,j);
- X509_LOOKUP_shutdown(lu);
- X509_LOOKUP_free(lu);
- }
- sk_X509_LOOKUP_free(sk);
- sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
-
- if (vfy->param)
- X509_VERIFY_PARAM_free(vfy->param);
- OPENSSL_free(vfy);
- }
+{
+ size_t j;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ if (vfy == NULL)
+ return;
+
+ if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
+ return;
+ }
+
+ CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
+
+ sk = vfy->get_cert_methods;
+ for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) {
+ lu = sk_X509_LOOKUP_value(sk, j);
+ X509_LOOKUP_shutdown(lu);
+ X509_LOOKUP_free(lu);
+ }
+ sk_X509_LOOKUP_free(sk);
+ sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
+
+ if (vfy->param)
+ X509_VERIFY_PARAM_free(vfy->param);
+ OPENSSL_free(vfy);
+}
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
- {
- size_t i;
- STACK_OF(X509_LOOKUP) *sk;
- X509_LOOKUP *lu;
-
- sk=v->get_cert_methods;
- for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
- {
- lu=sk_X509_LOOKUP_value(sk,i);
- if (m == lu->method)
- {
- return lu;
- }
- }
- /* a new one */
- lu=X509_LOOKUP_new(m);
- if (lu == NULL)
- return NULL;
- else
- {
- lu->store_ctx=v;
- if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
- return lu;
- else
- {
- X509_LOOKUP_free(lu);
- return NULL;
- }
- }
- }
+{
+ size_t i;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ sk = v->get_cert_methods;
+ for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
+ lu = sk_X509_LOOKUP_value(sk, i);
+ if (m == lu->method) {
+ return lu;
+ }
+ }
+ /* a new one */
+ lu = X509_LOOKUP_new(m);
+ if (lu == NULL)
+ return NULL;
+ else {
+ lu->store_ctx = v;
+ if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
+ return lu;
+ else {
+ X509_LOOKUP_free(lu);
+ return NULL;
+ }
+ }
+}
int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
- X509_OBJECT *ret)
- {
- X509_STORE *ctx=vs->ctx;
- X509_LOOKUP *lu;
- X509_OBJECT stmp,*tmp;
- int i,j;
-
- CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
- tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
-
- if (tmp == NULL || type == X509_LU_CRL)
- {
- for (i=vs->current_method; i<(int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
- {
- lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
- j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
- if (j < 0)
- {
- vs->current_method=j;
- return j;
- }
- else if (j)
- {
- tmp= &stmp;
- break;
- }
- }
- vs->current_method=0;
- if (tmp == NULL)
- return 0;
- }
-
-/* if (ret->data.ptr != NULL)
- X509_OBJECT_free_contents(ret); */
-
- ret->type=tmp->type;
- ret->data.ptr=tmp->data.ptr;
-
- X509_OBJECT_up_ref_count(ret);
-
- return 1;
- }
+ X509_OBJECT *ret)
+{
+ X509_STORE *ctx = vs->ctx;
+ X509_LOOKUP *lu;
+ X509_OBJECT stmp, *tmp;
+ int i, j;
+
+ CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+ tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
+ CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+
+ if (tmp == NULL || type == X509_LU_CRL) {
+ for (i = vs->current_method;
+ i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
+ lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
+ j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
+ if (j < 0) {
+ vs->current_method = j;
+ return j;
+ } else if (j) {
+ tmp = &stmp;
+ break;
+ }
+ }
+ vs->current_method = 0;
+ if (tmp == NULL)
+ return 0;
+ }
+
+ /*
+ * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret);
+ */
+
+ ret->type = tmp->type;
+ ret->data.ptr = tmp->data.ptr;
+
+ X509_OBJECT_up_ref_count(ret);
+
+ return 1;
+}
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
- {
- X509_OBJECT *obj;
- int ret=1;
-
- if (x == NULL) return 0;
- obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- obj->type=X509_LU_X509;
- obj->data.x509=x;
-
- CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
-
- X509_OBJECT_up_ref_count(obj);
-
- if (X509_OBJECT_retrieve_match(ctx->objs, obj))
- {
- X509_OBJECT_free_contents(obj);
- OPENSSL_free(obj);
- OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
- ret=0;
- }
- else sk_X509_OBJECT_push(ctx->objs, obj);
-
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
-
- return ret;
- }
+{
+ X509_OBJECT *obj;
+ int ret = 1;
+
+ if (x == NULL)
+ return 0;
+ obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type = X509_LU_X509;
+ obj->data.x509 = x;
+
+ CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret = 0;
+ } else
+ sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+
+ return ret;
+}
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
- {
- X509_OBJECT *obj;
- int ret=1;
-
- if (x == NULL) return 0;
- obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- obj->type=X509_LU_CRL;
- obj->data.crl=x;
-
- CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
-
- X509_OBJECT_up_ref_count(obj);
-
- if (X509_OBJECT_retrieve_match(ctx->objs, obj))
- {
- X509_OBJECT_free_contents(obj);
- OPENSSL_free(obj);
- OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
- ret=0;
- }
- else sk_X509_OBJECT_push(ctx->objs, obj);
-
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
-
- return ret;
- }
+{
+ X509_OBJECT *obj;
+ int ret = 1;
+
+ if (x == NULL)
+ return 0;
+ obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type = X509_LU_CRL;
+ obj->data.crl = x;
+
+ CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret = 0;
+ } else
+ sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+
+ return ret;
+}
void X509_OBJECT_up_ref_count(X509_OBJECT *a)
- {
- switch (a->type)
- {
- case X509_LU_X509:
- X509_up_ref(a->data.x509);
- break;
- case X509_LU_CRL:
- X509_CRL_up_ref(a->data.crl);
- break;
- }
- }
+{
+ switch (a->type) {
+ case X509_LU_X509:
+ X509_up_ref(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ X509_CRL_up_ref(a->data.crl);
+ break;
+ }
+}
void X509_OBJECT_free_contents(X509_OBJECT *a)
- {
- switch (a->type)
- {
- case X509_LU_X509:
- X509_free(a->data.x509);
- break;
- case X509_LU_CRL:
- X509_CRL_free(a->data.crl);
- break;
- }
- }
+{
+ switch (a->type) {
+ case X509_LU_X509:
+ X509_free(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ X509_CRL_free(a->data.crl);
+ break;
+ }
+}
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
- X509_NAME *name, int *pnmatch)
- {
- X509_OBJECT stmp;
- X509 x509_s;
- X509_CINF cinf_s;
- X509_CRL crl_s;
- X509_CRL_INFO crl_info_s;
-
- stmp.type=type;
- switch (type)
- {
- case X509_LU_X509:
- stmp.data.x509= &x509_s;
- x509_s.cert_info= &cinf_s;
- cinf_s.subject=name;
- break;
- case X509_LU_CRL:
- stmp.data.crl= &crl_s;
- crl_s.crl= &crl_info_s;
- crl_info_s.issuer=name;
- break;
- default:
- /* abort(); */
- return -1;
- }
-
- size_t idx;
- if (!sk_X509_OBJECT_find(h, &idx, &stmp))
- return -1;
-
- if (pnmatch != NULL)
- {
- int tidx;
- const X509_OBJECT *tobj, *pstmp;
- *pnmatch = 1;
- pstmp = &stmp;
- for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++)
- {
- tobj = sk_X509_OBJECT_value(h, tidx);
- if (x509_object_cmp(&tobj, &pstmp))
- break;
- (*pnmatch)++;
- }
- }
-
- return idx;
- }
-
+ X509_NAME *name, int *pnmatch)
+{
+ X509_OBJECT stmp;
+ X509 x509_s;
+ X509_CINF cinf_s;
+ X509_CRL crl_s;
+ X509_CRL_INFO crl_info_s;
+
+ stmp.type = type;
+ switch (type) {
+ case X509_LU_X509:
+ stmp.data.x509 = &x509_s;
+ x509_s.cert_info = &cinf_s;
+ cinf_s.subject = name;
+ break;
+ case X509_LU_CRL:
+ stmp.data.crl = &crl_s;
+ crl_s.crl = &crl_info_s;
+ crl_info_s.issuer = name;
+ break;
+ default:
+ /* abort(); */
+ return -1;
+ }
+
+ size_t idx;
+ if (!sk_X509_OBJECT_find(h, &idx, &stmp))
+ return -1;
+
+ if (pnmatch != NULL) {
+ int tidx;
+ const X509_OBJECT *tobj, *pstmp;
+ *pnmatch = 1;
+ pstmp = &stmp;
+ for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) {
+ tobj = sk_X509_OBJECT_value(h, tidx);
+ if (x509_object_cmp(&tobj, &pstmp))
+ break;
+ (*pnmatch)++;
+ }
+ }
+
+ return idx;
+}
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
- X509_NAME *name)
- {
- return x509_object_idx_cnt(h, type, name, NULL);
- }
-
-X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
- X509_NAME *name)
- {
- int idx;
- idx = X509_OBJECT_idx_by_subject(h, type, name);
- if (idx==-1) return NULL;
- return sk_X509_OBJECT_value(h, idx);
- }
-
-STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
- {
- int i, idx, cnt;
- STACK_OF(X509) *sk;
- X509 *x;
- X509_OBJECT *obj;
- sk = sk_X509_new_null();
- if (sk == NULL)
- return NULL;
- CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
- idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
- if (idx < 0)
- {
- /* Nothing found in cache: do lookup to possibly add new
- * objects to cache
- */
- X509_OBJECT xobj;
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj))
- {
- sk_X509_free(sk);
- return NULL;
- }
- X509_OBJECT_free_contents(&xobj);
- CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
- idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_X509,nm, &cnt);
- if (idx < 0)
- {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- sk_X509_free(sk);
- return NULL;
- }
- }
- for (i = 0; i < cnt; i++, idx++)
- {
- obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
- x = obj->data.x509;
- if (!sk_X509_push(sk, X509_up_ref(x)))
- {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return NULL;
- }
- }
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- return sk;
-
- }
-
-STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
- {
- int i, idx, cnt;
- STACK_OF(X509_CRL) *sk;
- X509_CRL *x;
- X509_OBJECT *obj, xobj;
- sk = sk_X509_CRL_new_null();
- if (sk == NULL)
- return NULL;
-
- /* Always do lookup to possibly add new CRLs to cache. */
- if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj))
- {
- sk_X509_CRL_free(sk);
- return NULL;
- }
- X509_OBJECT_free_contents(&xobj);
- CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
- idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_CRL, nm, &cnt);
- if (idx < 0)
- {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- sk_X509_CRL_free(sk);
- return NULL;
- }
-
- for (i = 0; i < cnt; i++, idx++)
- {
- obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
- x = obj->data.crl;
- X509_CRL_up_ref(x);
- if (!sk_X509_CRL_push(sk, x))
- {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- X509_CRL_free(x);
- sk_X509_CRL_pop_free(sk, X509_CRL_free);
- return NULL;
- }
- }
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- return sk;
- }
-
-X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
- {
- size_t idx, i;
- X509_OBJECT *obj;
-
- if (!sk_X509_OBJECT_find(h, &idx, x)) {
- return NULL;
- }
- if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
- return sk_X509_OBJECT_value(h, idx);
- for (i = idx; i < sk_X509_OBJECT_num(h); i++)
- {
- obj = sk_X509_OBJECT_value(h, i);
- if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
- return NULL;
- if (x->type == X509_LU_X509)
- {
- if (!X509_cmp(obj->data.x509, x->data.x509))
- return obj;
- }
- else if (x->type == X509_LU_CRL)
- {
- if (!X509_CRL_match(obj->data.crl, x->data.crl))
- return obj;
- }
- else
- return obj;
- }
- return NULL;
- }
-
-
-/* Try to get issuer certificate from store. Due to limitations
- * of the API this can only retrieve a single certificate matching
- * a given subject name. However it will fill the cache with all
- * matching certificates, so we can examine the cache for all
- * matches.
- *
- * Return values are:
- * 1 lookup successful.
- * 0 certificate not found.
- * -1 some other error.
+ X509_NAME *name)
+{
+ return x509_object_idx_cnt(h, type, name, NULL);
+}
+
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
+ int type, X509_NAME *name)
+{
+ int idx;
+ idx = X509_OBJECT_idx_by_subject(h, type, name);
+ if (idx == -1)
+ return NULL;
+ return sk_X509_OBJECT_value(h, idx);
+}
+
+STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+ int i, idx, cnt;
+ STACK_OF(X509) *sk;
+ X509 *x;
+ X509_OBJECT *obj;
+ sk = sk_X509_new_null();
+ if (sk == NULL)
+ return NULL;
+ CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+ if (idx < 0) {
+ /*
+ * Nothing found in cache: do lookup to possibly add new objects to
+ * cache
+ */
+ X509_OBJECT xobj;
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
+ sk_X509_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+ if (idx < 0) {
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ sk_X509_free(sk);
+ return NULL;
+ }
+ }
+ for (i = 0; i < cnt; i++, idx++) {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.x509;
+ if (!sk_X509_push(sk, X509_up_ref(x))) {
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return NULL;
+ }
+ }
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ return sk;
+
+}
+
+STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+ int i, idx, cnt;
+ STACK_OF(X509_CRL) *sk;
+ X509_CRL *x;
+ X509_OBJECT *obj, xobj;
+ sk = sk_X509_CRL_new_null();
+ if (sk == NULL)
+ return NULL;
+
+ /* Always do lookup to possibly add new CRLs to cache. */
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
+ if (idx < 0) {
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+
+ for (i = 0; i < cnt; i++, idx++) {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.crl;
+ X509_CRL_up_ref(x);
+ if (!sk_X509_CRL_push(sk, x)) {
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ X509_CRL_free(x);
+ sk_X509_CRL_pop_free(sk, X509_CRL_free);
+ return NULL;
+ }
+ }
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ return sk;
+}
+
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
+ X509_OBJECT *x)
+{
+ size_t idx, i;
+ X509_OBJECT *obj;
+
+ if (!sk_X509_OBJECT_find(h, &idx, x)) {
+ return NULL;
+ }
+ if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
+ return sk_X509_OBJECT_value(h, idx);
+ for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
+ obj = sk_X509_OBJECT_value(h, i);
+ if (x509_object_cmp
+ ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
+ return NULL;
+ if (x->type == X509_LU_X509) {
+ if (!X509_cmp(obj->data.x509, x->data.x509))
+ return obj;
+ } else if (x->type == X509_LU_CRL) {
+ if (!X509_CRL_match(obj->data.crl, x->data.crl))
+ return obj;
+ } else
+ return obj;
+ }
+ return NULL;
+}
+
+/*
+ * Try to get issuer certificate from store. Due to limitations of the API
+ * this can only retrieve a single certificate matching a given subject name.
+ * However it will fill the cache with all matching certificates, so we can
+ * examine the cache for all matches. Return values are: 1 lookup
+ * successful. 0 certificate not found. -1 some other error.
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
- {
- X509_NAME *xn;
- X509_OBJECT obj, *pobj;
- int ok, idx, ret;
- size_t i;
- xn=X509_get_issuer_name(x);
- ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
- if (ok != X509_LU_X509)
- {
- if (ok == X509_LU_RETRY)
- {
- X509_OBJECT_free_contents(&obj);
- OPENSSL_PUT_ERROR(X509, X509_R_SHOULD_RETRY);
- return -1;
- }
- else if (ok != X509_LU_FAIL)
- {
- X509_OBJECT_free_contents(&obj);
- /* not good :-(, break anyway */
- return -1;
- }
- return 0;
- }
- /* If certificate matches all OK */
- if (ctx->check_issued(ctx, x, obj.data.x509))
- {
- *issuer = obj.data.x509;
- return 1;
- }
- X509_OBJECT_free_contents(&obj);
-
- /* Else find index of first cert accepted by 'check_issued' */
- ret = 0;
- CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
- idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
- if (idx != -1) /* should be true as we've had at least one match */
- {
- /* Look through all matching certs for suitable issuer */
- for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
- {
- pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
- /* See if we've run past the matches */
- if (pobj->type != X509_LU_X509)
- break;
- if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
- break;
- if (ctx->check_issued(ctx, x, pobj->data.x509))
- {
- *issuer = pobj->data.x509;
- X509_OBJECT_up_ref_count(pobj);
- ret = 1;
- break;
- }
- }
- }
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
- return ret;
- }
+{
+ X509_NAME *xn;
+ X509_OBJECT obj, *pobj;
+ int ok, idx, ret;
+ size_t i;
+ xn = X509_get_issuer_name(x);
+ ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
+ if (ok != X509_LU_X509) {
+ if (ok == X509_LU_RETRY) {
+ X509_OBJECT_free_contents(&obj);
+ OPENSSL_PUT_ERROR(X509, X509_R_SHOULD_RETRY);
+ return -1;
+ } else if (ok != X509_LU_FAIL) {
+ X509_OBJECT_free_contents(&obj);
+ /* not good :-(, break anyway */
+ return -1;
+ }
+ return 0;
+ }
+ /* If certificate matches all OK */
+ if (ctx->check_issued(ctx, x, obj.data.x509)) {
+ *issuer = obj.data.x509;
+ return 1;
+ }
+ X509_OBJECT_free_contents(&obj);
+
+ /* Else find index of first cert accepted by 'check_issued' */
+ ret = 0;
+ CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+ idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
+ if (idx != -1) { /* should be true as we've had at least one
+ * match */
+ /* Look through all matching certs for suitable issuer */
+ for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
+ pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
+ /* See if we've run past the matches */
+ if (pobj->type != X509_LU_X509)
+ break;
+ if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
+ break;
+ if (ctx->check_issued(ctx, x, pobj->data.x509)) {
+ *issuer = pobj->data.x509;
+ X509_OBJECT_up_ref_count(pobj);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ return ret;
+}
int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
- {
- return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
- }
+{
+ return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+}
int X509_STORE_set_depth(X509_STORE *ctx, int depth)
- {
- X509_VERIFY_PARAM_set_depth(ctx->param, depth);
- return 1;
- }
+{
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+ return 1;
+}
int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
- {
- return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
- }
+{
+ return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+}
int X509_STORE_set_trust(X509_STORE *ctx, int trust)
- {
- return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
- }
+{
+ return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+}
int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
- {
- return X509_VERIFY_PARAM_set1(ctx->param, param);
- }
+{
+ return X509_VERIFY_PARAM_set1(ctx->param, param);
+}
void X509_STORE_set_verify_cb(X509_STORE *ctx,
- int (*verify_cb)(int, X509_STORE_CTX *))
- {
- ctx->verify_cb = verify_cb;
- }
+ int (*verify_cb) (int, X509_STORE_CTX *))
+{
+ ctx->verify_cb = verify_cb;
+}
void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
- STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm))
- {
- ctx->lookup_crls = cb;
- }
+ STACK_OF (X509_CRL) *
+ (*cb) (X509_STORE_CTX *ctx, X509_NAME *nm))
+{
+ ctx->lookup_crls = cb;
+}
X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
- {
- return ctx->ctx;
- }
+{
+ return ctx->ctx;
+}
diff --git a/src/crypto/x509/x509_obj.c b/src/crypto/x509/x509_obj.c
index b6f08164..641e308d 100644
--- a/src/crypto/x509/x509_obj.c
+++ b/src/crypto/x509/x509_obj.c
@@ -64,128 +64,117 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
- {
- X509_NAME_ENTRY *ne;
- size_t i;
- int n,lold,l,l1,l2,num,j,type;
- const char *s;
- char *p;
- unsigned char *q;
- BUF_MEM *b=NULL;
- static const char hex[17]="0123456789ABCDEF";
- int gs_doit[4];
- char tmp_buf[80];
-
- if (buf == NULL)
- {
- if ((b=BUF_MEM_new()) == NULL) goto err;
- if (!BUF_MEM_grow(b,200)) goto err;
- b->data[0]='\0';
- len=200;
- }
- if (a == NULL)
- {
- if(b)
- {
- buf=b->data;
- OPENSSL_free(b);
- }
- strncpy(buf,"NO X509_NAME",len);
- buf[len-1]='\0';
- return buf;
- }
+{
+ X509_NAME_ENTRY *ne;
+ size_t i;
+ int n, lold, l, l1, l2, num, j, type;
+ const char *s;
+ char *p;
+ unsigned char *q;
+ BUF_MEM *b = NULL;
+ static const char hex[17] = "0123456789ABCDEF";
+ int gs_doit[4];
+ char tmp_buf[80];
- len--; /* space for '\0' */
- l=0;
- for (i=0; i<sk_X509_NAME_ENTRY_num(a->entries); i++)
- {
- ne=sk_X509_NAME_ENTRY_value(a->entries,i);
- n=OBJ_obj2nid(ne->object);
- if ((n == NID_undef) || ((s=OBJ_nid2sn(n)) == NULL))
- {
- i2t_ASN1_OBJECT(tmp_buf,sizeof(tmp_buf),ne->object);
- s=tmp_buf;
- }
- l1=strlen(s);
+ if (buf == NULL) {
+ if ((b = BUF_MEM_new()) == NULL)
+ goto err;
+ if (!BUF_MEM_grow(b, 200))
+ goto err;
+ b->data[0] = '\0';
+ len = 200;
+ }
+ if (a == NULL) {
+ if (b) {
+ buf = b->data;
+ OPENSSL_free(b);
+ }
+ strncpy(buf, "NO X509_NAME", len);
+ buf[len - 1] = '\0';
+ return buf;
+ }
- type=ne->value->type;
- num=ne->value->length;
- q=ne->value->data;
+ len--; /* space for '\0' */
+ l = 0;
+ for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+ ne = sk_X509_NAME_ENTRY_value(a->entries, i);
+ n = OBJ_obj2nid(ne->object);
+ if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
+ i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object);
+ s = tmp_buf;
+ }
+ l1 = strlen(s);
- if ((type == V_ASN1_GENERALSTRING) && ((num%4) == 0))
- {
- gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=0;
- for (j=0; j<num; j++)
- if (q[j] != 0) gs_doit[j&3]=1;
+ type = ne->value->type;
+ num = ne->value->length;
+ q = ne->value->data;
- if (gs_doit[0]|gs_doit[1]|gs_doit[2])
- gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
- else
- {
- gs_doit[0]=gs_doit[1]=gs_doit[2]=0;
- gs_doit[3]=1;
- }
- }
- else
- gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
+ if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
+ gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0;
+ for (j = 0; j < num; j++)
+ if (q[j] != 0)
+ gs_doit[j & 3] = 1;
- for (l2=j=0; j<num; j++)
- {
- if (!gs_doit[j&3]) continue;
- l2++;
- if ((q[j] < ' ') || (q[j] > '~')) l2+=3;
- }
+ if (gs_doit[0] | gs_doit[1] | gs_doit[2])
+ gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
+ else {
+ gs_doit[0] = gs_doit[1] = gs_doit[2] = 0;
+ gs_doit[3] = 1;
+ }
+ } else
+ gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
- lold=l;
- l+=1+l1+1+l2;
- if (b != NULL)
- {
- if (!BUF_MEM_grow(b,l+1)) goto err;
- p= &(b->data[lold]);
- }
- else if (l > len)
- {
- break;
- }
- else
- p= &(buf[lold]);
- *(p++)='/';
- memcpy(p,s,(unsigned int)l1); p+=l1;
- *(p++)='=';
+ for (l2 = j = 0; j < num; j++) {
+ if (!gs_doit[j & 3])
+ continue;
+ l2++;
+ if ((q[j] < ' ') || (q[j] > '~'))
+ l2 += 3;
+ }
- q=ne->value->data;
+ lold = l;
+ l += 1 + l1 + 1 + l2;
+ if (b != NULL) {
+ if (!BUF_MEM_grow(b, l + 1))
+ goto err;
+ p = &(b->data[lold]);
+ } else if (l > len) {
+ break;
+ } else
+ p = &(buf[lold]);
+ *(p++) = '/';
+ memcpy(p, s, (unsigned int)l1);
+ p += l1;
+ *(p++) = '=';
- for (j=0; j<num; j++)
- {
- if (!gs_doit[j&3]) continue;
- n=q[j];
- if ((n < ' ') || (n > '~'))
- {
- *(p++)='\\';
- *(p++)='x';
- *(p++)=hex[(n>>4)&0x0f];
- *(p++)=hex[n&0x0f];
- }
- else
- *(p++)=n;
- }
- *p='\0';
- }
- if (b != NULL)
- {
- p=b->data;
- OPENSSL_free(b);
- }
- else
- p=buf;
- if (i == 0)
- *p = '\0';
- return(p);
-err:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- if (b != NULL) BUF_MEM_free(b);
- return(NULL);
- }
+ q = ne->value->data;
+ for (j = 0; j < num; j++) {
+ if (!gs_doit[j & 3])
+ continue;
+ n = q[j];
+ if ((n < ' ') || (n > '~')) {
+ *(p++) = '\\';
+ *(p++) = 'x';
+ *(p++) = hex[(n >> 4) & 0x0f];
+ *(p++) = hex[n & 0x0f];
+ } else
+ *(p++) = n;
+ }
+ *p = '\0';
+ }
+ if (b != NULL) {
+ p = b->data;
+ OPENSSL_free(b);
+ } else
+ p = buf;
+ if (i == 0)
+ *p = '\0';
+ return (p);
+ err:
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ if (b != NULL)
+ BUF_MEM_free(b);
+ return (NULL);
+}
diff --git a/src/crypto/x509/x509_r2x.c b/src/crypto/x509/x509_r2x.c
index 85979ac0..83951a2e 100644
--- a/src/crypto/x509/x509_r2x.c
+++ b/src/crypto/x509/x509_r2x.c
@@ -63,51 +63,51 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
- {
- X509 *ret=NULL;
- X509_CINF *xi=NULL;
- X509_NAME *xn;
-
- if ((ret=X509_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+{
+ X509 *ret = NULL;
+ X509_CINF *xi = NULL;
+ X509_NAME *xn;
- /* duplicate the request */
- xi=ret->cert_info;
+ if ((ret = X509_new()) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0)
- {
- if ((xi->version=M_ASN1_INTEGER_new()) == NULL) goto err;
- if (!ASN1_INTEGER_set(xi->version,2)) goto err;
-/* xi->extensions=ri->attributes; <- bad, should not ever be done
- ri->attributes=NULL; */
- }
+ /* duplicate the request */
+ xi = ret->cert_info;
- xn=X509_REQ_get_subject_name(r);
- if (X509_set_subject_name(ret,X509_NAME_dup(xn)) == 0)
- goto err;
- if (X509_set_issuer_name(ret,X509_NAME_dup(xn)) == 0)
- goto err;
+ if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) {
+ if ((xi->version = M_ASN1_INTEGER_new()) == NULL)
+ goto err;
+ if (!ASN1_INTEGER_set(xi->version, 2))
+ goto err;
+ /*
+ * xi->extensions=ri->attributes; <- bad, should not ever be done
+ * ri->attributes=NULL;
+ */
+ }
- if (X509_gmtime_adj(xi->validity->notBefore,0) == NULL)
- goto err;
- if (X509_gmtime_adj(xi->validity->notAfter,(long)60*60*24*days) == NULL)
- goto err;
+ xn = X509_REQ_get_subject_name(r);
+ if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0)
+ goto err;
+ if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0)
+ goto err;
- X509_set_pubkey(ret,X509_REQ_get_pubkey(r));
+ if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL)
+ goto err;
+ if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) ==
+ NULL)
+ goto err;
- if (!X509_sign(ret,pkey,EVP_md5()))
- goto err;
- if (0)
- {
-err:
- X509_free(ret);
- ret=NULL;
- }
- return(ret);
- }
+ X509_set_pubkey(ret, X509_REQ_get_pubkey(r));
+ if (!X509_sign(ret, pkey, EVP_md5()))
+ goto err;
+ if (0) {
+ err:
+ X509_free(ret);
+ ret = NULL;
+ }
+ return (ret);
+}
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
index 01c5113e..69bc6f11 100644
--- a/src/crypto/x509/x509_req.c
+++ b/src/crypto/x509/x509_req.c
@@ -66,250 +66,257 @@
#include <openssl/pem.h>
#include <openssl/x509.h>
-
X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
- {
- X509_REQ *ret;
- X509_REQ_INFO *ri;
- int i;
- EVP_PKEY *pktmp;
-
- ret=X509_REQ_new();
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- ri=ret->req_info;
-
- ri->version->length=1;
- ri->version->data=(unsigned char *)OPENSSL_malloc(1);
- if (ri->version->data == NULL) goto err;
- ri->version->data[0]=0; /* version == 0 */
-
- if (!X509_REQ_set_subject_name(ret,X509_get_subject_name(x)))
- goto err;
-
- pktmp = X509_get_pubkey(x);
- if (pktmp == NULL)
- goto err;
- i=X509_REQ_set_pubkey(ret,pktmp);
- EVP_PKEY_free(pktmp);
- if (!i) goto err;
-
- if (pkey != NULL)
- {
- if (!X509_REQ_sign(ret,pkey,md))
- goto err;
- }
- return(ret);
-err:
- X509_REQ_free(ret);
- return(NULL);
- }
+{
+ X509_REQ *ret;
+ X509_REQ_INFO *ri;
+ int i;
+ EVP_PKEY *pktmp;
+
+ ret = X509_REQ_new();
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ri = ret->req_info;
+
+ ri->version->length = 1;
+ ri->version->data = (unsigned char *)OPENSSL_malloc(1);
+ if (ri->version->data == NULL)
+ goto err;
+ ri->version->data[0] = 0; /* version == 0 */
+
+ if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
+ goto err;
+
+ pktmp = X509_get_pubkey(x);
+ if (pktmp == NULL)
+ goto err;
+ i = X509_REQ_set_pubkey(ret, pktmp);
+ EVP_PKEY_free(pktmp);
+ if (!i)
+ goto err;
+
+ if (pkey != NULL) {
+ if (!X509_REQ_sign(ret, pkey, md))
+ goto err;
+ }
+ return (ret);
+ err:
+ X509_REQ_free(ret);
+ return (NULL);
+}
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
- {
- if ((req == NULL) || (req->req_info == NULL))
- return(NULL);
- return(X509_PUBKEY_get(req->req_info->pubkey));
- }
+{
+ if ((req == NULL) || (req->req_info == NULL))
+ return (NULL);
+ return (X509_PUBKEY_get(req->req_info->pubkey));
+}
int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
- {
- EVP_PKEY *xk=NULL;
- int ok=0;
-
- xk=X509_REQ_get_pubkey(x);
- switch (EVP_PKEY_cmp(xk, k))
- {
- case 1:
- ok=1;
- break;
- case 0:
- OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
- break;
- case -1:
- OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
- break;
- case -2:
- if (k->type == EVP_PKEY_EC)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB);
- break;
- }
- if (k->type == EVP_PKEY_DH)
- {
- /* No idea */
- OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY);
- break;
- }
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
- }
-
- EVP_PKEY_free(xk);
- return(ok);
- }
-
-/* It seems several organisations had the same idea of including a list of
+{
+ EVP_PKEY *xk = NULL;
+ int ok = 0;
+
+ xk = X509_REQ_get_pubkey(x);
+ switch (EVP_PKEY_cmp(xk, k)) {
+ case 1:
+ ok = 1;
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ if (k->type == EVP_PKEY_EC) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB);
+ break;
+ }
+ if (k->type == EVP_PKEY_DH) {
+ /* No idea */
+ OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY);
+ break;
+ }
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+ }
+
+ EVP_PKEY_free(xk);
+ return (ok);
+}
+
+/*
+ * It seems several organisations had the same idea of including a list of
* extensions in a certificate request. There are at least two OIDs that are
* used and there may be more: so the list is configurable.
*/
-static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef};
+static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
static const int *ext_nids = ext_nid_list;
int X509_REQ_extension_nid(int req_nid)
{
- int i, nid;
- for(i = 0; ; i++) {
- nid = ext_nids[i];
- if(nid == NID_undef) return 0;
- else if (req_nid == nid) return 1;
- }
+ int i, nid;
+ for (i = 0;; i++) {
+ nid = ext_nids[i];
+ if (nid == NID_undef)
+ return 0;
+ else if (req_nid == nid)
+ return 1;
+ }
}
const int *X509_REQ_get_extension_nids(void)
{
- return ext_nids;
+ return ext_nids;
}
-
+
void X509_REQ_set_extension_nids(const int *nids)
{
- ext_nids = nids;
+ ext_nids = nids;
}
STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
- {
- X509_ATTRIBUTE *attr;
- ASN1_TYPE *ext = NULL;
- int idx;
- const int *pnid;
- const unsigned char *p;
-
- if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
- return(NULL);
- for (pnid = ext_nids; *pnid != NID_undef; pnid++)
- {
- idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
- if (idx == -1)
- continue;
- attr = X509_REQ_get_attr(req, idx);
- if(attr->single) ext = attr->value.single;
- else if(sk_ASN1_TYPE_num(attr->value.set))
- ext = sk_ASN1_TYPE_value(attr->value.set, 0);
- break;
- }
- if(!ext || (ext->type != V_ASN1_SEQUENCE))
- return NULL;
- p = ext->value.sequence->data;
- return (STACK_OF(X509_EXTENSION) *)
- ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
- ASN1_ITEM_rptr(X509_EXTENSIONS));
+{
+ X509_ATTRIBUTE *attr;
+ ASN1_TYPE *ext = NULL;
+ int idx;
+ const int *pnid;
+ const unsigned char *p;
+
+ if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
+ return (NULL);
+ for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
+ idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
+ if (idx == -1)
+ continue;
+ attr = X509_REQ_get_attr(req, idx);
+ if (attr->single)
+ ext = attr->value.single;
+ else if (sk_ASN1_TYPE_num(attr->value.set))
+ ext = sk_ASN1_TYPE_value(attr->value.set, 0);
+ break;
+ }
+ if (!ext || (ext->type != V_ASN1_SEQUENCE))
+ return NULL;
+ p = ext->value.sequence->data;
+ return (STACK_OF(X509_EXTENSION) *)
+ ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
+ ASN1_ITEM_rptr(X509_EXTENSIONS));
}
-/* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
+/*
+ * Add a STACK_OF extensions to a certificate request: allow alternative OIDs
* in case we want to create a non standard one.
*/
int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
- int nid)
+ int nid)
{
- ASN1_TYPE *at = NULL;
- X509_ATTRIBUTE *attr = NULL;
- if(!(at = ASN1_TYPE_new()) ||
- !(at->value.sequence = ASN1_STRING_new())) goto err;
-
- at->type = V_ASN1_SEQUENCE;
- /* Generate encoding of extensions */
- at->value.sequence->length =
- ASN1_item_i2d((ASN1_VALUE *)exts,
- &at->value.sequence->data,
- ASN1_ITEM_rptr(X509_EXTENSIONS));
- if(!(attr = X509_ATTRIBUTE_new())) goto err;
- if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
- if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err;
- at = NULL;
- attr->single = 0;
- attr->object = (ASN1_OBJECT*) OBJ_nid2obj(nid);
- if (!req->req_info->attributes)
- {
- if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
- goto err;
- }
- if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err;
- return 1;
- err:
- X509_ATTRIBUTE_free(attr);
- ASN1_TYPE_free(at);
- return 0;
+ ASN1_TYPE *at = NULL;
+ X509_ATTRIBUTE *attr = NULL;
+ if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new()))
+ goto err;
+
+ at->type = V_ASN1_SEQUENCE;
+ /* Generate encoding of extensions */
+ at->value.sequence->length =
+ ASN1_item_i2d((ASN1_VALUE *)exts,
+ &at->value.sequence->data,
+ ASN1_ITEM_rptr(X509_EXTENSIONS));
+ if (!(attr = X509_ATTRIBUTE_new()))
+ goto err;
+ if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
+ goto err;
+ if (!sk_ASN1_TYPE_push(attr->value.set, at))
+ goto err;
+ at = NULL;
+ attr->single = 0;
+ attr->object = (ASN1_OBJECT *)OBJ_nid2obj(nid);
+ if (!req->req_info->attributes) {
+ if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
+ goto err;
+ }
+ if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr))
+ goto err;
+ return 1;
+ err:
+ X509_ATTRIBUTE_free(attr);
+ ASN1_TYPE_free(at);
+ return 0;
}
+
/* This is the normal usage: use the "official" OID */
int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
{
- return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
+ return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
}
/* Request attribute functions */
int X509_REQ_get_attr_count(const X509_REQ *req)
{
- return X509at_get_attr_count(req->req_info->attributes);
+ return X509at_get_attr_count(req->req_info->attributes);
}
-int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
- int lastpos)
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
{
- return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
+ return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
}
int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
- int lastpos)
+ int lastpos)
{
- return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
+ return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
}
X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
{
- return X509at_get_attr(req->req_info->attributes, loc);
+ return X509at_get_attr(req->req_info->attributes, loc);
}
X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
{
- return X509at_delete_attr(req->req_info->attributes, loc);
+ return X509at_delete_attr(req->req_info->attributes, loc);
}
int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
{
- if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1;
- return 0;
+ if (X509at_add1_attr(&req->req_info->attributes, attr))
+ return 1;
+ return 0;
}
int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
- const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes, int len)
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len)
{
- if(X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
- type, bytes, len)) return 1;
- return 0;
+ if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
+ type, bytes, len))
+ return 1;
+ return 0;
}
int X509_REQ_add1_attr_by_NID(X509_REQ *req,
- int nid, int type,
- const unsigned char *bytes, int len)
+ int nid, int type,
+ const unsigned char *bytes, int len)
{
- if(X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
- type, bytes, len)) return 1;
- return 0;
+ if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
+ type, bytes, len))
+ return 1;
+ return 0;
}
int X509_REQ_add1_attr_by_txt(X509_REQ *req,
- const char *attrname, int type,
- const unsigned char *bytes, int len)
+ const char *attrname, int type,
+ const unsigned char *bytes, int len)
{
- if(X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
- type, bytes, len)) return 1;
- return 0;
+ if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
+ type, bytes, len))
+ return 1;
+ return 0;
}
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
index 06658b07..42e9cf0f 100644
--- a/src/crypto/x509/x509_set.c
+++ b/src/crypto/x509/x509_set.c
@@ -60,95 +60,90 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
int X509_set_version(X509 *x, long version)
- {
- if (x == NULL) return(0);
- if (version == 0)
- {
- M_ASN1_INTEGER_free(x->cert_info->version);
- x->cert_info->version = NULL;
- return(1);
- }
- if (x->cert_info->version == NULL)
- {
- if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL)
- return(0);
- }
- return(ASN1_INTEGER_set(x->cert_info->version,version));
- }
+{
+ if (x == NULL)
+ return (0);
+ if (version == 0) {
+ M_ASN1_INTEGER_free(x->cert_info->version);
+ x->cert_info->version = NULL;
+ return (1);
+ }
+ if (x->cert_info->version == NULL) {
+ if ((x->cert_info->version = M_ASN1_INTEGER_new()) == NULL)
+ return (0);
+ }
+ return (ASN1_INTEGER_set(x->cert_info->version, version));
+}
int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
- {
- ASN1_INTEGER *in;
+{
+ ASN1_INTEGER *in;
- if (x == NULL) return(0);
- in=x->cert_info->serialNumber;
- if (in != serial)
- {
- in=M_ASN1_INTEGER_dup(serial);
- if (in != NULL)
- {
- M_ASN1_INTEGER_free(x->cert_info->serialNumber);
- x->cert_info->serialNumber=in;
- }
- }
- return(in != NULL);
- }
+ if (x == NULL)
+ return (0);
+ in = x->cert_info->serialNumber;
+ if (in != serial) {
+ in = M_ASN1_INTEGER_dup(serial);
+ if (in != NULL) {
+ M_ASN1_INTEGER_free(x->cert_info->serialNumber);
+ x->cert_info->serialNumber = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_set_issuer_name(X509 *x, X509_NAME *name)
- {
- if ((x == NULL) || (x->cert_info == NULL)) return(0);
- return(X509_NAME_set(&x->cert_info->issuer,name));
- }
+{
+ if ((x == NULL) || (x->cert_info == NULL))
+ return (0);
+ return (X509_NAME_set(&x->cert_info->issuer, name));
+}
int X509_set_subject_name(X509 *x, X509_NAME *name)
- {
- if ((x == NULL) || (x->cert_info == NULL)) return(0);
- return(X509_NAME_set(&x->cert_info->subject,name));
- }
+{
+ if ((x == NULL) || (x->cert_info == NULL))
+ return (0);
+ return (X509_NAME_set(&x->cert_info->subject, name));
+}
int X509_set_notBefore(X509 *x, const ASN1_TIME *tm)
- {
- ASN1_TIME *in;
+{
+ ASN1_TIME *in;
- if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
- in=x->cert_info->validity->notBefore;
- if (in != tm)
- {
- in=M_ASN1_TIME_dup(tm);
- if (in != NULL)
- {
- M_ASN1_TIME_free(x->cert_info->validity->notBefore);
- x->cert_info->validity->notBefore=in;
- }
- }
- return(in != NULL);
- }
+ if ((x == NULL) || (x->cert_info->validity == NULL))
+ return (0);
+ in = x->cert_info->validity->notBefore;
+ if (in != tm) {
+ in = M_ASN1_TIME_dup(tm);
+ if (in != NULL) {
+ M_ASN1_TIME_free(x->cert_info->validity->notBefore);
+ x->cert_info->validity->notBefore = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
- {
- ASN1_TIME *in;
+{
+ ASN1_TIME *in;
- if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
- in=x->cert_info->validity->notAfter;
- if (in != tm)
- {
- in=M_ASN1_TIME_dup(tm);
- if (in != NULL)
- {
- M_ASN1_TIME_free(x->cert_info->validity->notAfter);
- x->cert_info->validity->notAfter=in;
- }
- }
- return(in != NULL);
- }
+ if ((x == NULL) || (x->cert_info->validity == NULL))
+ return (0);
+ in = x->cert_info->validity->notAfter;
+ if (in != tm) {
+ in = M_ASN1_TIME_dup(tm);
+ if (in != NULL) {
+ M_ASN1_TIME_free(x->cert_info->validity->notAfter);
+ x->cert_info->validity->notAfter = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
- {
- if ((x == NULL) || (x->cert_info == NULL)) return(0);
- return(X509_PUBKEY_set(&(x->cert_info->key),pkey));
- }
-
-
-
+{
+ if ((x == NULL) || (x->cert_info == NULL))
+ return (0);
+ return (X509_PUBKEY_set(&(x->cert_info->key), pkey));
+}
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
new file mode 100644
index 00000000..650163a8
--- /dev/null
+++ b/src/crypto/x509/x509_test.cc
@@ -0,0 +1,472 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <vector>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+#include "../test/scoped_types.h"
+
+
+static const char kCrossSigningRootPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowPDEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+"dCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwo3qFvSB9Zmlbpzn9wJp\n"
+"ikI75Rxkatez8VkLqyxbOhPYl2Haz8F5p1gDG96dCI6jcLGgu3AKT9uhEQyyUko5\n"
+"EKYasazSeA9CQrdyhPg0mkTYVETnPM1W/ebid1YtqQbq1CMWlq2aTDoSGAReGFKP\n"
+"RTdXAbuAXzpCfi/d8LqV13UCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIEMB0GA1Ud\n"
+"JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MBkGA1Ud\n"
+"DgQSBBBHKHC7V3Z/3oLvEZx0RZRwMBsGA1UdIwQUMBKAEEcocLtXdn/egu8RnHRF\n"
+"lHAwDQYJKoZIhvcNAQELBQADgYEAnglibsy6mGtpIXivtlcz4zIEnHw/lNW+r/eC\n"
+"CY7evZTmOoOuC/x9SS3MF9vawt1HFUummWM6ZgErqVBOXIB4//ykrcCgf5ZbF5Hr\n"
+"+3EFprKhBqYiXdD8hpBkrBoXwn85LPYWNd2TceCrx0YtLIprE2R5MB2RIq8y4Jk3\n"
+"YFXvkME=\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kRootCAPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICVTCCAb6gAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwLjEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwIBcNMTUwMTAx\n"
+"MDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMC4xGjAYBgNVBAoTEUJvcmluZ1NTTCBU\n"
+"RVNUSU5HMRAwDgYDVQQDEwdSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
+"iQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM\n"
+"2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2m8PX+plZ\n"
+"w7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQABo3oweDAO\n"
+"BgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8G\n"
+"A1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEEA31wH7QC+4HH5UBCeMWQEwGwYDVR0j\n"
+"BBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOBgQDXylEK77Za\n"
+"kKeY6ZerrScWyZhrjIGtHFu09qVpdJEzrk87k2G7iHHR9CAvSofCgEExKtWNS9dN\n"
+"+9WiZp/U48iHLk7qaYXdEuO07No4BYtXn+lkOykE+FUxmA4wvOF1cTd2tdj3MzX2\n"
+"kfGIBAYhzGZWhY3JbhIfTEfY1PNM1pWChQ==\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kRootCrossSignedPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICYzCCAcygAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowLjEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwgZ8wDQYJKoZI\n"
+"hvcNAQEBBQADgY0AMIGJAoGBAOkOfxEM5lrmhoNw9lEHLgJ4EfWyJJI47iZiAseU\n"
+"8T6hd2rAj9UiaLZd4kza4IURNcKSckmNgbSIl2u3/LJEW9lNBnD5DMaP6bPfo2qE\n"
+"bENZvp2y0Habw9f6mVnDuOXzUwO9SdazzKJD/q3CC7kBuFYplAMkpw0oISmprpRb\n"
+"SvmfAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcD\n"
+"AQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gc\n"
+"flQEJ4xZATAbBgNVHSMEFDASgBBHKHC7V3Z/3oLvEZx0RZRwMA0GCSqGSIb3DQEB\n"
+"CwUAA4GBAErTxYJ0en9HVRHAAr5OO5wuk5Iq3VMc79TMyQLCXVL8YH8Uk7KEwv+q\n"
+"9MEKZv2eR/Vfm4HlXlUuIqfgUXbwrAYC/YVVX86Wnbpy/jc73NYVCq8FEZeO+0XU\n"
+"90SWAPDdp+iL7aZdimnMtG1qlM1edmz8AKbrhN/R3IbA2CL0nCWV\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kIntermediatePEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICXjCCAcegAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMC4xGjAYBgNV\n"
+"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRAwDgYDVQQDEwdSb290IENBMCAXDTE1MDEw\n"
+"MTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA2MRowGAYDVQQKExFCb3JpbmdTU0wg\n"
+"VEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB\n"
+"AQUAA4GNADCBiQKBgQC7YtI0l8ocTYJ0gKyXTtPL4iMJCNY4OcxXl48jkncVG1Hl\n"
+"blicgNUa1r9m9YFtVkxvBinb8dXiUpEGhVg4awRPDcatlsBSEBuJkiZGYbRcAmSu\n"
+"CmZYnf6u3aYQ18SU8WqVERPpE4cwVVs+6kwlzRw0+XDoZAczu8ZezVhCUc6NbQID\n"
+"AQABo3oweDAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n"
+"AQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEIwaaKi1dttdV3sfjRSy\n"
+"BqMwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOB\n"
+"gQCvnolNWEHuQS8PFVVyuLR+FKBeUUdrVbSfHSzTqNAqQGp0C9fk5oCzDq6ZgTfY\n"
+"ESXM4cJhb3IAnW0UM0NFsYSKQJ50JZL2L3z5ZLQhHdbs4RmODGoC40BVdnJ4/qgB\n"
+"aGSh09eQRvAVmbVCviDK2ipkWNegdyI19jFfNP5uIkGlYg==\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kIntermediateSelfSignedPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICZjCCAc+gAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n"
+"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n"
+"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDYxGjAYBgNVBAoTEUJv\n"
+"cmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwgZ8wDQYJ\n"
+"KoZIhvcNAQEBBQADgY0AMIGJAoGBALti0jSXyhxNgnSArJdO08viIwkI1jg5zFeX\n"
+"jyOSdxUbUeVuWJyA1RrWv2b1gW1WTG8GKdvx1eJSkQaFWDhrBE8Nxq2WwFIQG4mS\n"
+"JkZhtFwCZK4KZlid/q7dphDXxJTxapURE+kThzBVWz7qTCXNHDT5cOhkBzO7xl7N\n"
+"WEJRzo1tAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEF\n"
+"BQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQjBpoqLV2\n"
+"211Xex+NFLIGozAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3\n"
+"DQEBCwUAA4GBALcccSrAQ0/EqQBsx0ZDTUydHXXNP2DrUkpUKmAXIe8McqIVSlkT\n"
+"6H4xz7z8VRKBo9j+drjjtCw2i0CQc8aOLxRb5WJ8eVLnaW2XRlUqAzhF0CrulfVI\n"
+"E4Vs6ZLU+fra1WAuIj6qFiigRja+3YkZArG8tMA9vtlhTX/g7YBZIkqH\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kLeafPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg\n"
+"Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y\n"
+"aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3\n"
+"DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c\n"
+"oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j\n"
+"5x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh\n"
+"TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG\n"
+"CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0\n"
+"4nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB\n"
+"gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y\n"
+"rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU\n"
+"xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg==\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kLeafNoKeyUsagePEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICNTCCAZ6gAwIBAgIJAIFQGaLQ0G2mMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n"
+"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n"
+"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDcxGjAYBgNVBAoTEUJv\n"
+"cmluZ1NTTCBURVNUSU5HMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29tMIGfMA0G\n"
+"CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOKoZe75NPz77EOaMMl4/0s3PyQw++zJvp\n"
+"ejHAxZiTPCJgMbEHLrSzNoHdopg+CLUH5bE4wTXM8w9Inv5P8OAFJt7gJuPUunmk\n"
+"j+NoU3QfzOR6BroePcz1vXX9jyVHRs087M/sLqWRHu9IR+/A+UTcBaWaFiDVUxtJ\n"
+"YOwFMwjNPQIDAQABo0gwRjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBJfLEUWHq1\n"
+"27rZ1AVx2J5GMBsGA1UdIwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwDQYJKoZIhvcN\n"
+"AQELBQADgYEALVKN2Y3LZJOtu6SxFIYKxbLaXhTGTdIjxipZhmbBRDFjbZjZZOTe\n"
+"6Oo+VDNPYco4rBexK7umYXJyfTqoY0E8dbiImhTcGTEj7OAB3DbBomgU1AYe+t2D\n"
+"uwBqh4Y3Eto+Zn4pMVsxGEfUpjzjZDel7bN1/oU/9KWPpDfywfUmjgk=\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kForgeryPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICZzCCAdCgAwIBAgIIdTlMzQoKkeMwDQYJKoZIhvcNAQELBQAwNzEaMBgGA1UE\n"
+"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGTAXBgNVBAMTEGV2aWwuZXhhbXBsZS5jb20w\n"
+"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDoxGjAYBgNVBAoTEUJv\n"
+"cmluZ1NTTCBURVNUSU5HMRwwGgYDVQQDExNmb3JnZXJ5LmV4YW1wbGUuY29tMIGf\n"
+"MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADTwruBQZGb7Ay6s9HiYv5d1lwtEy\n"
+"xQdA2Sy8Rn8uA20Q4KgqwVY7wzIZ+z5Butrsmwb70gdG1XU+yRaDeE7XVoW6jSpm\n"
+"0sw35/5vJbTcL4THEFbnX0OPZnvpuZDFUkvVtq5kxpDWsVyM24G8EEq7kPih3Sa3\n"
+"OMhXVXF8kso6UQIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\n"
+"KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEEYJ/WHM\n"
+"8p64erPWIg4/liwwGwYDVR0jBBQwEoAQSXyxFFh6tdu62dQFcdieRjANBgkqhkiG\n"
+"9w0BAQsFAAOBgQA+zH7bHPElWRWJvjxDqRexmYLn+D3Aivs8XgXQJsM94W0EzSUf\n"
+"DSLfRgaQwcb2gg2xpDFoG+W0vc6O651uF23WGt5JaFFJJxqjII05IexfCNhuPmp4\n"
+"4UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==\n"
+"-----END CERTIFICATE-----\n";
+
+// kExamplePSSCert is an example RSA-PSS self-signed certificate, signed with
+// the default hash functions.
+static const char kExamplePSSCert[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICYjCCAcagAwIBAgIJAI3qUyT6SIfzMBIGCSqGSIb3DQEBCjAFogMCAWowRTEL\n"
+"MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy\n"
+"bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDEwMDkxOTA5NTVaFw0xNTEwMDkxOTA5\n"
+"NTVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n"
+"DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A\n"
+"MIGJAoGBAPi4bIO0vNmoV8CltFl2jFQdeesiUgR+0zfrQf2D+fCmhRU0dXFahKg8\n"
+"0u9aTtPel4rd/7vPCqqGkr64UOTNb4AzMHYTj8p73OxaymPHAyXvqIqDWHYg+hZ3\n"
+"13mSYwFIGth7Z/FSVUlO1m5KXNd6NzYM3t2PROjCpywrta9kS2EHAgMBAAGjUDBO\n"
+"MB0GA1UdDgQWBBTQQfuJQR6nrVrsNF1JEflVgXgfEzAfBgNVHSMEGDAWgBTQQfuJ\n"
+"QR6nrVrsNF1JEflVgXgfEzAMBgNVHRMEBTADAQH/MBIGCSqGSIb3DQEBCjAFogMC\n"
+"AWoDgYEASUy2RZcgNbNQZA0/7F+V1YTLEXwD16bm+iSVnzGwtexmQVEYIZG74K/w\n"
+"xbdZQdTbpNJkp1QPjPfh0zsatw6dmt5QoZ8K8No0DjR9dgf+Wvv5WJvJUIQBoAVN\n"
+"Z0IL+OQFz6+LcTHxD27JJCebrATXZA0wThGTQDm7crL+a+SujBY=\n"
+"-----END CERTIFICATE-----\n";
+
+// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters.
+static const char kBadPSSCertPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n"
+"AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD\n"
+"VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz\n"
+"NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj\n"
+"ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH\n"
+"qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL\n"
+"IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT\n"
+"IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k\n"
+"dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq\n"
+"QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa\n"
+"5eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2\n"
+"4V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB\n"
+"Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii\n"
+"BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb\n"
+"xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn\n"
+"plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY\n"
+"DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p\n"
+"NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ\n"
+"lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=\n"
+"-----END CERTIFICATE-----\n";
+
+static const char kRSAKey[] =
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
+"kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
+"KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
+"AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
+"i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
+"WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
+"m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
+"QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
+"aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
+"LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
+"104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
+"tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
+"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
+"-----END RSA PRIVATE KEY-----\n";
+
+
+// CertFromPEM parses the given, NUL-terminated pem block and returns an
+// |X509*|.
+static ScopedX509 CertFromPEM(const char *pem) {
+ ScopedBIO bio(BIO_new_mem_buf(pem, strlen(pem)));
+ return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// PrivateKeyFromPEM parses the given, NUL-terminated pem block and returns an
+// |EVP_PKEY*|.
+static ScopedEVP_PKEY PrivateKeyFromPEM(const char *pem) {
+ ScopedBIO bio(BIO_new_mem_buf(const_cast<char *>(pem), strlen(pem)));
+ return ScopedEVP_PKEY(
+ PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509*),
+// bumping the reference counts for each certificate in question.
+static STACK_OF(X509)* CertsToStack(const std::vector<X509*> &certs) {
+ ScopedX509Stack stack(sk_X509_new_null());
+ if (!stack) {
+ return nullptr;
+ }
+ for (auto cert : certs) {
+ if (!sk_X509_push(stack.get(), cert)) {
+ return nullptr;
+ }
+ X509_up_ref(cert);
+ }
+
+ return stack.release();
+}
+
+static bool Verify(X509 *leaf, const std::vector<X509 *> &roots,
+ const std::vector<X509 *> &intermediates,
+ unsigned long flags = 0) {
+ ScopedX509Stack roots_stack(CertsToStack(roots));
+ ScopedX509Stack intermediates_stack(CertsToStack(intermediates));
+ if (!roots_stack ||
+ !intermediates_stack) {
+ return false;
+ }
+
+ ScopedX509_STORE_CTX ctx(X509_STORE_CTX_new());
+ if (!ctx) {
+ return false;
+ }
+ if (!X509_STORE_CTX_init(ctx.get(), nullptr /* no X509_STORE */, leaf,
+ intermediates_stack.get())) {
+ return false;
+ }
+
+ X509_STORE_CTX_trusted_stack(ctx.get(), roots_stack.get());
+
+ X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
+ if (param == nullptr) {
+ return false;
+ }
+ X509_VERIFY_PARAM_set_time(param, 1452807555 /* Jan 14th, 2016 */);
+ X509_VERIFY_PARAM_set_depth(param, 16);
+ if (flags) {
+ X509_VERIFY_PARAM_set_flags(param, flags);
+ }
+ X509_STORE_CTX_set0_param(ctx.get(), param);
+
+ ERR_clear_error();
+ return X509_verify_cert(ctx.get()) == 1;
+}
+
+static bool TestVerify() {
+ ScopedX509 cross_signing_root(CertFromPEM(kCrossSigningRootPEM));
+ ScopedX509 root(CertFromPEM(kRootCAPEM));
+ ScopedX509 root_cross_signed(CertFromPEM(kRootCrossSignedPEM));
+ ScopedX509 intermediate(CertFromPEM(kIntermediatePEM));
+ ScopedX509 intermediate_self_signed(CertFromPEM(kIntermediateSelfSignedPEM));
+ ScopedX509 leaf(CertFromPEM(kLeafPEM));
+ ScopedX509 leaf_no_key_usage(CertFromPEM(kLeafNoKeyUsagePEM));
+ ScopedX509 forgery(CertFromPEM(kForgeryPEM));
+
+ if (!cross_signing_root ||
+ !root ||
+ !root_cross_signed ||
+ !intermediate ||
+ !intermediate_self_signed ||
+ !leaf ||
+ !leaf_no_key_usage ||
+ !forgery) {
+ fprintf(stderr, "Failed to parse certificates\n");
+ return false;
+ }
+
+ std::vector<X509*> empty;
+ if (Verify(leaf.get(), empty, empty)) {
+ fprintf(stderr, "Leaf verified with no roots!\n");
+ return false;
+ }
+
+ if (Verify(leaf.get(), empty, {intermediate.get()})) {
+ fprintf(stderr, "Leaf verified with no roots!\n");
+ return false;
+ }
+
+ if (!Verify(leaf.get(), {root.get()}, {intermediate.get()})) {
+ ERR_print_errors_fp(stderr);
+ fprintf(stderr, "Basic chain didn't verify.\n");
+ return false;
+ }
+
+ if (!Verify(leaf.get(), {cross_signing_root.get()},
+ {intermediate.get(), root_cross_signed.get()})) {
+ ERR_print_errors_fp(stderr);
+ fprintf(stderr, "Cross-signed chain didn't verify.\n");
+ return false;
+ }
+
+ if (!Verify(leaf.get(), {cross_signing_root.get(), root.get()},
+ {intermediate.get(), root_cross_signed.get()})) {
+ ERR_print_errors_fp(stderr);
+ fprintf(stderr, "Cross-signed chain with root didn't verify.\n");
+ return false;
+ }
+
+ /* This is the “altchains” test – we remove the cross-signing CA but include
+ * the cross-sign in the intermediates. */
+ if (!Verify(leaf.get(), {root.get()},
+ {intermediate.get(), root_cross_signed.get()})) {
+ ERR_print_errors_fp(stderr);
+ fprintf(stderr, "Chain with cross-sign didn't backtrack to find root.\n");
+ return false;
+ }
+
+ if (Verify(leaf.get(), {root.get()},
+ {intermediate.get(), root_cross_signed.get()},
+ X509_V_FLAG_NO_ALT_CHAINS)) {
+ fprintf(stderr, "Altchains test still passed when disabled.\n");
+ return false;
+ }
+
+ if (Verify(forgery.get(), {intermediate_self_signed.get()},
+ {leaf_no_key_usage.get()})) {
+ fprintf(stderr, "Basic constraints weren't checked.\n");
+ return false;
+ }
+
+ /* Test that one cannot skip Basic Constraints checking with a contorted set
+ * of roots and intermediates. This is a regression test for CVE-2015-1793. */
+ if (Verify(forgery.get(),
+ {intermediate_self_signed.get(), root_cross_signed.get()},
+ {leaf_no_key_usage.get(), intermediate.get()})) {
+ fprintf(stderr, "Basic constraints weren't checked.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestPSS() {
+ ScopedX509 cert(CertFromPEM(kExamplePSSCert));
+ if (!cert) {
+ return false;
+ }
+
+ ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get()));
+ if (!pkey) {
+ return false;
+ }
+
+ if (!X509_verify(cert.get(), pkey.get())) {
+ fprintf(stderr, "Could not verify certificate.\n");
+ return false;
+ }
+ return true;
+}
+
+static bool TestBadPSSParameters() {
+ ScopedX509 cert(CertFromPEM(kBadPSSCertPEM));
+ if (!cert) {
+ return false;
+ }
+
+ ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get()));
+ if (!pkey) {
+ return false;
+ }
+
+ if (X509_verify(cert.get(), pkey.get())) {
+ fprintf(stderr, "Unexpectedly verified bad certificate.\n");
+ return false;
+ }
+ ERR_clear_error();
+ return true;
+}
+
+static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
+ // Make a certificate like signed with |md_ctx|'s settings.'
+ ScopedX509 cert(CertFromPEM(kLeafPEM));
+ if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) {
+ return false;
+ }
+
+ // Ensure that |pkey| may still be used to verify the resulting signature. All
+ // settings in |md_ctx| must have been serialized appropriately.
+ return !!X509_verify(cert.get(), pkey);
+}
+
+static bool TestSignCtx() {
+ ScopedEVP_PKEY pkey(PrivateKeyFromPEM(kRSAKey));
+ if (!pkey) {
+ return false;
+ }
+
+ // Test PKCS#1 v1.5.
+ ScopedEVP_MD_CTX md_ctx;
+ if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+ !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+ fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n");
+ return false;
+ }
+
+ // Test RSA-PSS with custom parameters.
+ md_ctx.Reset();
+ EVP_PKEY_CTX *pkey_ctx;
+ if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
+ pkey.get()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
+ !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+ fprintf(stderr, "RSA-PSS failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ if (!TestVerify() ||
+ !TestPSS() ||
+ !TestBadPSSParameters() ||
+ !TestSignCtx()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/x509/x509_trs.c b/src/crypto/x509/x509_trs.c
index 820e6052..c7dfcad6 100644
--- a/src/crypto/x509/x509_trs.c
+++ b/src/crypto/x509/x509_trs.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -58,9 +60,7 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static int tr_cmp(const X509_TRUST **a,
- const X509_TRUST **b);
+static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b);
static void trtable_free(X509_TRUST *p);
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
@@ -68,237 +68,259 @@ static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
static int obj_trust(int id, X509 *x, int flags);
-static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
+static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
-/* WARNING: the following table should be kept in order of trust
- * and without any gaps so we can just subtract the minimum trust
- * value to get an index into the table
+/*
+ * WARNING: the following table should be kept in order of trust and without
+ * any gaps so we can just subtract the minimum trust value to get an index
+ * into the table
*/
static X509_TRUST trstandard[] = {
-{X509_TRUST_COMPAT, 0, trust_compat, (char *) "compatible", 0, NULL},
-{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *) "SSL Client", NID_client_auth, NULL},
-{X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *) "SSL Server", NID_server_auth, NULL},
-{X509_TRUST_EMAIL, 0, trust_1oidany, (char *) "S/MIME email", NID_email_protect, NULL},
-{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *) "Object Signer", NID_code_sign, NULL},
-{X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *) "OCSP responder", NID_OCSP_sign, NULL},
-{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *) "OCSP request", NID_ad_OCSP, NULL},
-{X509_TRUST_TSA, 0, trust_1oidany, (char *) "TSA server", NID_time_stamp, NULL}
+ {X509_TRUST_COMPAT, 0, trust_compat, (char *)"compatible", 0, NULL},
+ {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *)"SSL Client",
+ NID_client_auth, NULL},
+ {X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *)"SSL Server",
+ NID_server_auth, NULL},
+ {X509_TRUST_EMAIL, 0, trust_1oidany, (char *)"S/MIME email",
+ NID_email_protect, NULL},
+ {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *)"Object Signer",
+ NID_code_sign, NULL},
+ {X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *)"OCSP responder",
+ NID_OCSP_sign, NULL},
+ {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *)"OCSP request",
+ NID_ad_OCSP, NULL},
+ {X509_TRUST_TSA, 0, trust_1oidany, (char *)"TSA server", NID_time_stamp,
+ NULL}
};
-#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
+#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
static STACK_OF(X509_TRUST) *trtable = NULL;
-static int tr_cmp(const X509_TRUST **a,
- const X509_TRUST **b)
+static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b)
{
- return (*a)->trust - (*b)->trust;
+ return (*a)->trust - (*b)->trust;
}
-int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int)
-{
- int (*oldtrust)(int , X509 *, int);
- oldtrust = default_trust;
- default_trust = trust;
- return oldtrust;
+int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
+ int) {
+ int (*oldtrust) (int, X509 *, int);
+ oldtrust = default_trust;
+ default_trust = trust;
+ return oldtrust;
}
-
int X509_check_trust(X509 *x, int id, int flags)
{
- X509_TRUST *pt;
- int idx;
- if(id == -1) return 1;
- /* We get this as a default value */
- if (id == 0)
- {
- int rv;
- rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
- if (rv != X509_TRUST_UNTRUSTED)
- return rv;
- return trust_compat(NULL, x, 0);
- }
- idx = X509_TRUST_get_by_id(id);
- if(idx == -1) return default_trust(id, x, flags);
- pt = X509_TRUST_get0(idx);
- return pt->check_trust(pt, x, flags);
+ X509_TRUST *pt;
+ int idx;
+ if (id == -1)
+ return 1;
+ /* We get this as a default value */
+ if (id == 0) {
+ int rv;
+ rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
+ if (rv != X509_TRUST_UNTRUSTED)
+ return rv;
+ return trust_compat(NULL, x, 0);
+ }
+ idx = X509_TRUST_get_by_id(id);
+ if (idx == -1)
+ return default_trust(id, x, flags);
+ pt = X509_TRUST_get0(idx);
+ return pt->check_trust(pt, x, flags);
}
int X509_TRUST_get_count(void)
{
- if(!trtable) return X509_TRUST_COUNT;
- return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
+ if (!trtable)
+ return X509_TRUST_COUNT;
+ return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
}
-X509_TRUST * X509_TRUST_get0(int idx)
+X509_TRUST *X509_TRUST_get0(int idx)
{
- if(idx < 0) return NULL;
- if(idx < (int)X509_TRUST_COUNT) return trstandard + idx;
- return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
+ if (idx < 0)
+ return NULL;
+ if (idx < (int)X509_TRUST_COUNT)
+ return trstandard + idx;
+ return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
}
int X509_TRUST_get_by_id(int id)
{
- X509_TRUST tmp;
- size_t idx;
-
- if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
- return id - X509_TRUST_MIN;
- tmp.trust = id;
- if(!trtable) return -1;
- if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
- return -1;
- }
- return idx + X509_TRUST_COUNT;
+ X509_TRUST tmp;
+ size_t idx;
+
+ if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
+ return id - X509_TRUST_MIN;
+ tmp.trust = id;
+ if (!trtable)
+ return -1;
+ if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
+ return -1;
+ }
+ return idx + X509_TRUST_COUNT;
}
int X509_TRUST_set(int *t, int trust)
{
- if(X509_TRUST_get_by_id(trust) == -1) {
- OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST);
- return 0;
- }
- *t = trust;
- return 1;
+ if (X509_TRUST_get_by_id(trust) == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST);
+ return 0;
+ }
+ *t = trust;
+ return 1;
}
-int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
- char *name, int arg1, void *arg2)
+int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
+ char *name, int arg1, void *arg2)
{
- int idx;
- X509_TRUST *trtmp;
- char *name_dup;
-
- /* This is set according to what we change: application can't set it */
- flags &= ~X509_TRUST_DYNAMIC;
- /* This will always be set for application modified trust entries */
- flags |= X509_TRUST_DYNAMIC_NAME;
- /* Get existing entry if any */
- idx = X509_TRUST_get_by_id(id);
- /* Need a new entry */
- if(idx == -1) {
- if(!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- trtmp->flags = X509_TRUST_DYNAMIC;
- } else trtmp = X509_TRUST_get0(idx);
-
- /* Duplicate the supplied name. */
- name_dup = BUF_strdup(name);
- if (name_dup == NULL) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- if (idx == -1)
- OPENSSL_free(trtmp);
- return 0;
- }
-
- /* OPENSSL_free existing name if dynamic */
- if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name);
- trtmp->name = name_dup;
- /* Keep the dynamic flag of existing entry */
- trtmp->flags &= X509_TRUST_DYNAMIC;
- /* Set all other flags */
- trtmp->flags |= flags;
-
- trtmp->trust = id;
- trtmp->check_trust = ck;
- trtmp->arg1 = arg1;
- trtmp->arg2 = arg2;
-
- /* If its a new entry manage the dynamic table */
- if(idx == -1) {
- if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- trtable_free(trtmp);
- return 0;
- }
- if (!sk_X509_TRUST_push(trtable, trtmp)) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- trtable_free(trtmp);
- return 0;
- }
- }
- return 1;
+ int idx;
+ X509_TRUST *trtmp;
+ char *name_dup;
+
+ /*
+ * This is set according to what we change: application can't set it
+ */
+ flags &= ~X509_TRUST_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_TRUST_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_TRUST_get_by_id(id);
+ /* Need a new entry */
+ if (idx == -1) {
+ if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ trtmp->flags = X509_TRUST_DYNAMIC;
+ } else
+ trtmp = X509_TRUST_get0(idx);
+
+ /* Duplicate the supplied name. */
+ name_dup = BUF_strdup(name);
+ if (name_dup == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ if (idx == -1)
+ OPENSSL_free(trtmp);
+ return 0;
+ }
+
+ /* OPENSSL_free existing name if dynamic */
+ if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(trtmp->name);
+ trtmp->name = name_dup;
+ /* Keep the dynamic flag of existing entry */
+ trtmp->flags &= X509_TRUST_DYNAMIC;
+ /* Set all other flags */
+ trtmp->flags |= flags;
+
+ trtmp->trust = id;
+ trtmp->check_trust = ck;
+ trtmp->arg1 = arg1;
+ trtmp->arg2 = arg2;
+
+ /* If its a new entry manage the dynamic table */
+ if (idx == -1) {
+ if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ if (!sk_X509_TRUST_push(trtable, trtmp)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ }
+ return 1;
}
static void trtable_free(X509_TRUST *p)
- {
- if(!p) return;
- if (p->flags & X509_TRUST_DYNAMIC)
- {
- if (p->flags & X509_TRUST_DYNAMIC_NAME)
- OPENSSL_free(p->name);
- OPENSSL_free(p);
- }
- }
+{
+ if (!p)
+ return;
+ if (p->flags & X509_TRUST_DYNAMIC) {
+ if (p->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(p->name);
+ OPENSSL_free(p);
+ }
+}
void X509_TRUST_cleanup(void)
{
- unsigned int i;
- for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i);
- sk_X509_TRUST_pop_free(trtable, trtable_free);
- trtable = NULL;
+ unsigned int i;
+ for (i = 0; i < X509_TRUST_COUNT; i++)
+ trtable_free(trstandard + i);
+ sk_X509_TRUST_pop_free(trtable, trtable_free);
+ trtable = NULL;
}
int X509_TRUST_get_flags(X509_TRUST *xp)
{
- return xp->flags;
+ return xp->flags;
}
char *X509_TRUST_get0_name(X509_TRUST *xp)
{
- return xp->name;
+ return xp->name;
}
int X509_TRUST_get_trust(X509_TRUST *xp)
{
- return xp->trust;
+ return xp->trust;
}
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
{
- if(x->aux && (x->aux->trust || x->aux->reject))
- return obj_trust(trust->arg1, x, flags);
- /* we don't have any trust settings: for compatibility
- * we return trusted if it is self signed
- */
- return trust_compat(trust, x, flags);
+ if (x->aux && (x->aux->trust || x->aux->reject))
+ return obj_trust(trust->arg1, x, flags);
+ /*
+ * we don't have any trust settings: for compatibility we return trusted
+ * if it is self signed
+ */
+ return trust_compat(trust, x, flags);
}
static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
{
- if(x->aux) return obj_trust(trust->arg1, x, flags);
- return X509_TRUST_UNTRUSTED;
+ if (x->aux)
+ return obj_trust(trust->arg1, x, flags);
+ return X509_TRUST_UNTRUSTED;
}
static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
- X509_check_purpose(x, -1, 0);
- if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED;
- else return X509_TRUST_UNTRUSTED;
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS)
+ return X509_TRUST_TRUSTED;
+ else
+ return X509_TRUST_UNTRUSTED;
}
static int obj_trust(int id, X509 *x, int flags)
{
- ASN1_OBJECT *obj;
- size_t i;
- X509_CERT_AUX *ax;
- ax = x->aux;
- if(!ax) return X509_TRUST_UNTRUSTED;
- if(ax->reject) {
- for(i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
- obj = sk_ASN1_OBJECT_value(ax->reject, i);
- if(OBJ_obj2nid(obj) == id) return X509_TRUST_REJECTED;
- }
- }
- if(ax->trust) {
- for(i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
- obj = sk_ASN1_OBJECT_value(ax->trust, i);
- if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED;
- }
- }
- return X509_TRUST_UNTRUSTED;
+ ASN1_OBJECT *obj;
+ size_t i;
+ X509_CERT_AUX *ax;
+ ax = x->aux;
+ if (!ax)
+ return X509_TRUST_UNTRUSTED;
+ if (ax->reject) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
+ obj = sk_ASN1_OBJECT_value(ax->reject, i);
+ if (OBJ_obj2nid(obj) == id)
+ return X509_TRUST_REJECTED;
+ }
+ }
+ if (ax->trust) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
+ obj = sk_ASN1_OBJECT_value(ax->trust, i);
+ if (OBJ_obj2nid(obj) == id)
+ return X509_TRUST_TRUSTED;
+ }
+ }
+ return X509_TRUST_UNTRUSTED;
}
-
diff --git a/src/crypto/x509/x509_txt.c b/src/crypto/x509/x509_txt.c
index c2867102..86af3fec 100644
--- a/src/crypto/x509/x509_txt.c
+++ b/src/crypto/x509/x509_txt.c
@@ -63,147 +63,144 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
const char *X509_verify_cert_error_string(long n)
- {
- static char buf[100];
-
- switch ((int)n)
- {
- case X509_V_OK:
- return("ok");
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- return("unable to get issuer certificate");
- case X509_V_ERR_UNABLE_TO_GET_CRL:
- return("unable to get certificate CRL");
- case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
- return("unable to decrypt certificate's signature");
- case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
- return("unable to decrypt CRL's signature");
- case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
- return("unable to decode issuer public key");
- case X509_V_ERR_CERT_SIGNATURE_FAILURE:
- return("certificate signature failure");
- case X509_V_ERR_CRL_SIGNATURE_FAILURE:
- return("CRL signature failure");
- case X509_V_ERR_CERT_NOT_YET_VALID:
- return("certificate is not yet valid");
- case X509_V_ERR_CRL_NOT_YET_VALID:
- return("CRL is not yet valid");
- case X509_V_ERR_CERT_HAS_EXPIRED:
- return("certificate has expired");
- case X509_V_ERR_CRL_HAS_EXPIRED:
- return("CRL has expired");
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- return("format error in certificate's notBefore field");
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- return("format error in certificate's notAfter field");
- case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
- return("format error in CRL's lastUpdate field");
- case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
- return("format error in CRL's nextUpdate field");
- case X509_V_ERR_OUT_OF_MEM:
- return("out of memory");
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- return("self signed certificate");
- case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- return("self signed certificate in certificate chain");
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- return("unable to get local issuer certificate");
- case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
- return("unable to verify the first certificate");
- case X509_V_ERR_CERT_CHAIN_TOO_LONG:
- return("certificate chain too long");
- case X509_V_ERR_CERT_REVOKED:
- return("certificate revoked");
- case X509_V_ERR_INVALID_CA:
- return ("invalid CA certificate");
- case X509_V_ERR_INVALID_NON_CA:
- return ("invalid non-CA certificate (has CA markings)");
- case X509_V_ERR_PATH_LENGTH_EXCEEDED:
- return ("path length constraint exceeded");
- case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
- return("proxy path length constraint exceeded");
- case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
- return("proxy certificates not allowed, please set the appropriate flag");
- case X509_V_ERR_INVALID_PURPOSE:
- return ("unsupported certificate purpose");
- case X509_V_ERR_CERT_UNTRUSTED:
- return ("certificate not trusted");
- case X509_V_ERR_CERT_REJECTED:
- return ("certificate rejected");
- case X509_V_ERR_APPLICATION_VERIFICATION:
- return("application verification failure");
- case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
- return("subject issuer mismatch");
- case X509_V_ERR_AKID_SKID_MISMATCH:
- return("authority and subject key identifier mismatch");
- case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
- return("authority and issuer serial number mismatch");
- case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
- return("key usage does not include certificate signing");
- case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
- return("unable to get CRL issuer certificate");
- case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
- return("unhandled critical extension");
- case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
- return("key usage does not include CRL signing");
- case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
- return("key usage does not include digital signature");
- case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
- return("unhandled critical CRL extension");
- case X509_V_ERR_INVALID_EXTENSION:
- return("invalid or inconsistent certificate extension");
- case X509_V_ERR_INVALID_POLICY_EXTENSION:
- return("invalid or inconsistent certificate policy extension");
- case X509_V_ERR_NO_EXPLICIT_POLICY:
- return("no explicit policy");
- case X509_V_ERR_DIFFERENT_CRL_SCOPE:
- return("Different CRL scope");
- case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
- return("Unsupported extension feature");
- case X509_V_ERR_UNNESTED_RESOURCE:
- return("RFC 3779 resource not subset of parent's resources");
-
- case X509_V_ERR_PERMITTED_VIOLATION:
- return("permitted subtree violation");
- case X509_V_ERR_EXCLUDED_VIOLATION:
- return("excluded subtree violation");
- case X509_V_ERR_SUBTREE_MINMAX:
- return("name constraints minimum and maximum not supported");
- case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
- return("unsupported name constraint type");
- case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
- return("unsupported or invalid name constraint syntax");
- case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
- return("unsupported or invalid name syntax");
- case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
- return("CRL path validation error");
+{
+ static char buf[100];
- case X509_V_ERR_SUITE_B_INVALID_VERSION:
- return("Suite B: certificate version invalid");
- case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
- return("Suite B: invalid public key algorithm");
- case X509_V_ERR_SUITE_B_INVALID_CURVE:
- return("Suite B: invalid ECC curve");
- case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
- return("Suite B: invalid signature algorithm");
- case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
- return("Suite B: curve not allowed for this LOS");
- case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
- return("Suite B: cannot sign P-384 with P-256");
+ switch ((int)n) {
+ case X509_V_OK:
+ return ("ok");
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ return ("unable to get issuer certificate");
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ return ("unable to get certificate CRL");
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ return ("unable to decrypt certificate's signature");
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ return ("unable to decrypt CRL's signature");
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ return ("unable to decode issuer public key");
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ return ("certificate signature failure");
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ return ("CRL signature failure");
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ return ("certificate is not yet valid");
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ return ("CRL is not yet valid");
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ return ("certificate has expired");
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ return ("CRL has expired");
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ return ("format error in certificate's notBefore field");
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ return ("format error in certificate's notAfter field");
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ return ("format error in CRL's lastUpdate field");
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ return ("format error in CRL's nextUpdate field");
+ case X509_V_ERR_OUT_OF_MEM:
+ return ("out of memory");
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ return ("self signed certificate");
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ return ("self signed certificate in certificate chain");
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ return ("unable to get local issuer certificate");
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ return ("unable to verify the first certificate");
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ return ("certificate chain too long");
+ case X509_V_ERR_CERT_REVOKED:
+ return ("certificate revoked");
+ case X509_V_ERR_INVALID_CA:
+ return ("invalid CA certificate");
+ case X509_V_ERR_INVALID_NON_CA:
+ return ("invalid non-CA certificate (has CA markings)");
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ return ("path length constraint exceeded");
+ case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
+ return ("proxy path length constraint exceeded");
+ case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
+ return
+ ("proxy certificates not allowed, please set the appropriate flag");
+ case X509_V_ERR_INVALID_PURPOSE:
+ return ("unsupported certificate purpose");
+ case X509_V_ERR_CERT_UNTRUSTED:
+ return ("certificate not trusted");
+ case X509_V_ERR_CERT_REJECTED:
+ return ("certificate rejected");
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ return ("application verification failure");
+ case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
+ return ("subject issuer mismatch");
+ case X509_V_ERR_AKID_SKID_MISMATCH:
+ return ("authority and subject key identifier mismatch");
+ case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+ return ("authority and issuer serial number mismatch");
+ case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+ return ("key usage does not include certificate signing");
+ case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+ return ("unable to get CRL issuer certificate");
+ case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ return ("unhandled critical extension");
+ case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
+ return ("key usage does not include CRL signing");
+ case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
+ return ("key usage does not include digital signature");
+ case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
+ return ("unhandled critical CRL extension");
+ case X509_V_ERR_INVALID_EXTENSION:
+ return ("invalid or inconsistent certificate extension");
+ case X509_V_ERR_INVALID_POLICY_EXTENSION:
+ return ("invalid or inconsistent certificate policy extension");
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ return ("no explicit policy");
+ case X509_V_ERR_DIFFERENT_CRL_SCOPE:
+ return ("Different CRL scope");
+ case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
+ return ("Unsupported extension feature");
+ case X509_V_ERR_UNNESTED_RESOURCE:
+ return ("RFC 3779 resource not subset of parent's resources");
- case X509_V_ERR_HOSTNAME_MISMATCH:
- return("Hostname mismatch");
- case X509_V_ERR_EMAIL_MISMATCH:
- return("Email address mismatch");
- case X509_V_ERR_IP_ADDRESS_MISMATCH:
- return("IP address mismatch");
+ case X509_V_ERR_PERMITTED_VIOLATION:
+ return ("permitted subtree violation");
+ case X509_V_ERR_EXCLUDED_VIOLATION:
+ return ("excluded subtree violation");
+ case X509_V_ERR_SUBTREE_MINMAX:
+ return ("name constraints minimum and maximum not supported");
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+ return ("unsupported name constraint type");
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+ return ("unsupported or invalid name constraint syntax");
+ case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
+ return ("unsupported or invalid name syntax");
+ case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
+ return ("CRL path validation error");
- default:
- BIO_snprintf(buf,sizeof buf,"error number %ld",n);
- return(buf);
- }
- }
+ case X509_V_ERR_SUITE_B_INVALID_VERSION:
+ return ("Suite B: certificate version invalid");
+ case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
+ return ("Suite B: invalid public key algorithm");
+ case X509_V_ERR_SUITE_B_INVALID_CURVE:
+ return ("Suite B: invalid ECC curve");
+ case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
+ return ("Suite B: invalid signature algorithm");
+ case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
+ return ("Suite B: curve not allowed for this LOS");
+ case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
+ return ("Suite B: cannot sign P-384 with P-256");
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ return ("Hostname mismatch");
+ case X509_V_ERR_EMAIL_MISMATCH:
+ return ("Email address mismatch");
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ return ("IP address mismatch");
+ default:
+ BIO_snprintf(buf, sizeof buf, "error number %ld", n);
+ return (buf);
+ }
+}
diff --git a/src/crypto/x509/x509_v3.c b/src/crypto/x509/x509_v3.c
index b0429851..ecbc0ddc 100644
--- a/src/crypto/x509/x509_v3.c
+++ b/src/crypto/x509/x509_v3.c
@@ -62,210 +62,217 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
- {
- if (x == NULL) return(0);
- return(sk_X509_EXTENSION_num(x));
- }
+{
+ if (x == NULL)
+ return (0);
+ return (sk_X509_EXTENSION_num(x));
+}
int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
- int lastpos)
- {
- const ASN1_OBJECT *obj;
+ int lastpos)
+{
+ const ASN1_OBJECT *obj;
- obj=OBJ_nid2obj(nid);
- if (obj == NULL) return(-2);
- return(X509v3_get_ext_by_OBJ(x,obj,lastpos));
- }
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ return (-2);
+ return (X509v3_get_ext_by_OBJ(x, obj, lastpos));
+}
-int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, const ASN1_OBJECT *obj,
- int lastpos)
- {
- int n;
- X509_EXTENSION *ex;
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk,
+ const ASN1_OBJECT *obj, int lastpos)
+{
+ int n;
+ X509_EXTENSION *ex;
- if (sk == NULL) return(-1);
- lastpos++;
- if (lastpos < 0)
- lastpos=0;
- n=sk_X509_EXTENSION_num(sk);
- for ( ; lastpos < n; lastpos++)
- {
- ex=sk_X509_EXTENSION_value(sk,lastpos);
- if (OBJ_cmp(ex->object,obj) == 0)
- return(lastpos);
- }
- return(-1);
- }
+ if (sk == NULL)
+ return (-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos = 0;
+ n = sk_X509_EXTENSION_num(sk);
+ for (; lastpos < n; lastpos++) {
+ ex = sk_X509_EXTENSION_value(sk, lastpos);
+ if (OBJ_cmp(ex->object, obj) == 0)
+ return (lastpos);
+ }
+ return (-1);
+}
int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit,
- int lastpos)
- {
- int n;
- X509_EXTENSION *ex;
+ int lastpos)
+{
+ int n;
+ X509_EXTENSION *ex;
- if (sk == NULL) return(-1);
- lastpos++;
- if (lastpos < 0)
- lastpos=0;
- n=sk_X509_EXTENSION_num(sk);
- for ( ; lastpos < n; lastpos++)
- {
- ex=sk_X509_EXTENSION_value(sk,lastpos);
- if ( ((ex->critical > 0) && crit) ||
- ((ex->critical <= 0) && !crit))
- return(lastpos);
- }
- return(-1);
- }
+ if (sk == NULL)
+ return (-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos = 0;
+ n = sk_X509_EXTENSION_num(sk);
+ for (; lastpos < n; lastpos++) {
+ ex = sk_X509_EXTENSION_value(sk, lastpos);
+ if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit))
+ return (lastpos);
+ }
+ return (-1);
+}
X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
- {
- if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
- return NULL;
- else
- return sk_X509_EXTENSION_value(x,loc);
- }
+{
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc)
+ return NULL;
+ else
+ return sk_X509_EXTENSION_value(x, loc);
+}
X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
- {
- X509_EXTENSION *ret;
+{
+ X509_EXTENSION *ret;
- if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
- return(NULL);
- ret=sk_X509_EXTENSION_delete(x,loc);
- return(ret);
- }
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc)
+ return (NULL);
+ ret = sk_X509_EXTENSION_delete(x, loc);
+ return (ret);
+}
STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
- X509_EXTENSION *ex, int loc)
- {
- X509_EXTENSION *new_ex=NULL;
- int n;
- STACK_OF(X509_EXTENSION) *sk=NULL;
+ X509_EXTENSION *ex, int loc)
+{
+ X509_EXTENSION *new_ex = NULL;
+ int n;
+ STACK_OF(X509_EXTENSION) *sk = NULL;
- if (x == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
- goto err2;
- }
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+ goto err2;
+ }
- if (*x == NULL)
- {
- if ((sk=sk_X509_EXTENSION_new_null()) == NULL)
- goto err;
- }
- else
- sk= *x;
+ if (*x == NULL) {
+ if ((sk = sk_X509_EXTENSION_new_null()) == NULL)
+ goto err;
+ } else
+ sk = *x;
- n=sk_X509_EXTENSION_num(sk);
- if (loc > n) loc=n;
- else if (loc < 0) loc=n;
+ n = sk_X509_EXTENSION_num(sk);
+ if (loc > n)
+ loc = n;
+ else if (loc < 0)
+ loc = n;
- if ((new_ex=X509_EXTENSION_dup(ex)) == NULL)
- goto err2;
- if (!sk_X509_EXTENSION_insert(sk,new_ex,loc))
- goto err;
- if (*x == NULL)
- *x=sk;
- return(sk);
-err:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-err2:
- if (new_ex != NULL) X509_EXTENSION_free(new_ex);
- if (sk != NULL) sk_X509_EXTENSION_free(sk);
- return(NULL);
- }
+ if ((new_ex = X509_EXTENSION_dup(ex)) == NULL)
+ goto err2;
+ if (!sk_X509_EXTENSION_insert(sk, new_ex, loc))
+ goto err;
+ if (*x == NULL)
+ *x = sk;
+ return (sk);
+ err:
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ err2:
+ if (new_ex != NULL)
+ X509_EXTENSION_free(new_ex);
+ if (sk != NULL)
+ sk_X509_EXTENSION_free(sk);
+ return (NULL);
+}
X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
- int crit, ASN1_OCTET_STRING *data)
- {
- const ASN1_OBJECT *obj;
- X509_EXTENSION *ret;
+ int crit,
+ ASN1_OCTET_STRING *data)
+{
+ const ASN1_OBJECT *obj;
+ X509_EXTENSION *ret;
- obj=OBJ_nid2obj(nid);
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
- return(NULL);
- }
- ret=X509_EXTENSION_create_by_OBJ(ex,obj,crit,data);
- return(ret);
- }
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+ return (NULL);
+ }
+ ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data);
+ return (ret);
+}
X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
- const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data)
- {
- X509_EXTENSION *ret;
+ const ASN1_OBJECT *obj, int crit,
+ ASN1_OCTET_STRING *data)
+{
+ X509_EXTENSION *ret;
+
+ if ((ex == NULL) || (*ex == NULL)) {
+ if ((ret = X509_EXTENSION_new()) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+ } else
+ ret = *ex;
- if ((ex == NULL) || (*ex == NULL))
- {
- if ((ret=X509_EXTENSION_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
- }
- else
- ret= *ex;
+ if (!X509_EXTENSION_set_object(ret, obj))
+ goto err;
+ if (!X509_EXTENSION_set_critical(ret, crit))
+ goto err;
+ if (!X509_EXTENSION_set_data(ret, data))
+ goto err;
- if (!X509_EXTENSION_set_object(ret,obj))
- goto err;
- if (!X509_EXTENSION_set_critical(ret,crit))
- goto err;
- if (!X509_EXTENSION_set_data(ret,data))
- goto err;
-
- if ((ex != NULL) && (*ex == NULL)) *ex=ret;
- return(ret);
-err:
- if ((ex == NULL) || (ret != *ex))
- X509_EXTENSION_free(ret);
- return(NULL);
- }
+ if ((ex != NULL) && (*ex == NULL))
+ *ex = ret;
+ return (ret);
+ err:
+ if ((ex == NULL) || (ret != *ex))
+ X509_EXTENSION_free(ret);
+ return (NULL);
+}
int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
- {
- if ((ex == NULL) || (obj == NULL))
- return(0);
- ASN1_OBJECT_free(ex->object);
- ex->object=OBJ_dup(obj);
- return ex->object != NULL;
- }
+{
+ if ((ex == NULL) || (obj == NULL))
+ return (0);
+ ASN1_OBJECT_free(ex->object);
+ ex->object = OBJ_dup(obj);
+ return ex->object != NULL;
+}
int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
- {
- if (ex == NULL) return(0);
- ex->critical=(crit)?0xFF:-1;
- return(1);
- }
+{
+ if (ex == NULL)
+ return (0);
+ ex->critical = (crit) ? 0xFF : -1;
+ return (1);
+}
int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
- {
- int i;
+{
+ int i;
- if (ex == NULL) return(0);
- i=M_ASN1_OCTET_STRING_set(ex->value,data->data,data->length);
- if (!i) return(0);
- return(1);
- }
+ if (ex == NULL)
+ return (0);
+ i = M_ASN1_OCTET_STRING_set(ex->value, data->data, data->length);
+ if (!i)
+ return (0);
+ return (1);
+}
ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex)
- {
- if (ex == NULL) return(NULL);
- return(ex->object);
- }
+{
+ if (ex == NULL)
+ return (NULL);
+ return (ex->object);
+}
ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex)
- {
- if (ex == NULL) return(NULL);
- return(ex->value);
- }
+{
+ if (ex == NULL)
+ return (NULL);
+ return (ex->value);
+}
int X509_EXTENSION_get_critical(X509_EXTENSION *ex)
- {
- if (ex == NULL) return(0);
- if(ex->critical > 0) return 1;
- return 0;
- }
+{
+ if (ex == NULL)
+ return (0);
+ if (ex->critical > 0)
+ return 1;
+ return 0;
+}
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index c62a6f58..2ed2f03e 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -71,27 +71,26 @@
#include "vpm_int.h"
#include "../internal.h"
-
static CRYPTO_EX_DATA_CLASS g_ex_data_class =
- CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
+ CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
/* CRL score values */
/* No unhandled critical extensions */
-#define CRL_SCORE_NOCRITICAL 0x100
+#define CRL_SCORE_NOCRITICAL 0x100
/* certificate is within CRL scope */
-#define CRL_SCORE_SCOPE 0x080
+#define CRL_SCORE_SCOPE 0x080
/* CRL times valid */
-#define CRL_SCORE_TIME 0x040
+#define CRL_SCORE_TIME 0x040
/* Issuer name matches certificate */
-#define CRL_SCORE_ISSUER_NAME 0x020
+#define CRL_SCORE_ISSUER_NAME 0x020
/* If this score or above CRL is probably valid */
@@ -99,21 +98,21 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class =
/* CRL issuer is certificate issuer */
-#define CRL_SCORE_ISSUER_CERT 0x018
+#define CRL_SCORE_ISSUER_CERT 0x018
/* CRL issuer is on certificate path */
-#define CRL_SCORE_SAME_PATH 0x008
+#define CRL_SCORE_SAME_PATH 0x008
/* CRL issuer matches CRL AKID */
-#define CRL_SCORE_AKID 0x004
+#define CRL_SCORE_AKID 0x004
/* Have a delta CRL with valid times */
-#define CRL_SCORE_TIME_DELTA 0x002
+#define CRL_SCORE_TIME_DELTA 0x002
-static int null_callback(int ok,X509_STORE_CTX *e);
+static int null_callback(int ok, X509_STORE_CTX *e);
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
static int check_chain_extensions(X509_STORE_CTX *ctx);
@@ -125,2336 +124,2284 @@ static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
- unsigned int *preasons,
- X509_CRL *crl, X509 *x);
+ unsigned int *preasons, X509_CRL *crl, X509 *x);
static int get_crl_delta(X509_STORE_CTX *ctx,
- X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
-static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score,
- X509_CRL *base, STACK_OF(X509_CRL) *crls);
-static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
- X509 **pissuer, int *pcrl_score);
+ X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
+static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl,
+ int *pcrl_score, X509_CRL *base,
+ STACK_OF(X509_CRL) *crls);
+static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
+ int *pcrl_score);
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
- unsigned int *preasons);
+ unsigned int *preasons);
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
static int check_crl_chain(X509_STORE_CTX *ctx,
- STACK_OF(X509) *cert_path,
- STACK_OF(X509) *crl_path);
+ STACK_OF(X509) *cert_path,
+ STACK_OF(X509) *crl_path);
static int internal_verify(X509_STORE_CTX *ctx);
-
static int null_callback(int ok, X509_STORE_CTX *e)
- {
- return ok;
- }
+{
+ return ok;
+}
#if 0
static int x509_subject_cmp(X509 **a, X509 **b)
- {
- return X509_subject_name_cmp(*a,*b);
- }
+{
+ return X509_subject_name_cmp(*a, *b);
+}
#endif
/* Return 1 is a certificate is self signed */
static int cert_self_signed(X509 *x)
- {
- X509_check_purpose(x, -1, 0);
- if (x->ex_flags & EXFLAG_SS)
- return 1;
- else
- return 0;
- }
+{
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS)
+ return 1;
+ else
+ return 0;
+}
/* Given a certificate try and find an exact match in the store */
static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
- {
- STACK_OF(X509) *certs;
- X509 *xtmp = NULL;
- size_t i;
- /* Lookup all certs with matching subject name */
- certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
- if (certs == NULL)
- return NULL;
- /* Look for exact match */
- for (i = 0; i < sk_X509_num(certs); i++)
- {
- xtmp = sk_X509_value(certs, i);
- if (!X509_cmp(xtmp, x))
- break;
- }
- if (i < sk_X509_num(certs))
- X509_up_ref(xtmp);
- else
- xtmp = NULL;
- sk_X509_pop_free(certs, X509_free);
- return xtmp;
- }
+{
+ STACK_OF(X509) *certs;
+ X509 *xtmp = NULL;
+ size_t i;
+ /* Lookup all certs with matching subject name */
+ certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
+ if (certs == NULL)
+ return NULL;
+ /* Look for exact match */
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ xtmp = sk_X509_value(certs, i);
+ if (!X509_cmp(xtmp, x))
+ break;
+ }
+ if (i < sk_X509_num(certs))
+ X509_up_ref(xtmp);
+ else
+ xtmp = NULL;
+ sk_X509_pop_free(certs, X509_free);
+ return xtmp;
+}
int X509_verify_cert(X509_STORE_CTX *ctx)
- {
- X509 *x,*xtmp,*chain_ss=NULL;
- int bad_chain = 0;
- X509_VERIFY_PARAM *param = ctx->param;
- int depth,i,ok=0;
- int num;
- int (*cb)(int xok,X509_STORE_CTX *xctx);
- STACK_OF(X509) *sktmp=NULL;
- if (ctx->cert == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
- return -1;
- }
- if (ctx->chain != NULL)
- {
- /* This X509_STORE_CTX has already been used to verify a
- * cert. We cannot do another one. */
- OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return -1;
- }
-
- cb=ctx->verify_cb;
-
- /* first we make sure the chain we are going to build is
- * present and that the first entry is in place */
- ctx->chain = sk_X509_new_null();
- if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto end;
- }
- X509_up_ref(ctx->cert);
- ctx->last_untrusted = 1;
-
- /* We use a temporary STACK so we can chop and hack at it */
- if (ctx->untrusted != NULL
- && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto end;
- }
-
- num=sk_X509_num(ctx->chain);
- x=sk_X509_value(ctx->chain,num-1);
- depth=param->depth;
-
-
- for (;;)
- {
- /* If we have enough, we break */
- if (depth < num) break; /* FIXME: If this happens, we should take
- * note of it and, if appropriate, use the
- * X509_V_ERR_CERT_CHAIN_TOO_LONG error
- * code later.
- */
-
- /* If we are self signed, we break */
- if (cert_self_signed(x))
- break;
- /* If asked see if we can find issuer in trusted store first */
- if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
- {
- ok = ctx->get_issuer(&xtmp, ctx, x);
- if (ok < 0)
- goto end;
- /* If successful for now free up cert so it
- * will be picked up again later.
- */
- if (ok > 0)
- {
- X509_free(xtmp);
- break;
- }
- }
-
- /* If we were passed a cert chain, use it first */
- if (ctx->untrusted != NULL)
- {
- xtmp=find_issuer(ctx, sktmp,x);
- if (xtmp != NULL)
- {
- if (!sk_X509_push(ctx->chain,xtmp))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto end;
- }
- X509_up_ref(xtmp);
- (void)sk_X509_delete_ptr(sktmp,xtmp);
- ctx->last_untrusted++;
- x=xtmp;
- num++;
- /* reparse the full chain for
- * the next one */
- continue;
- }
- }
- break;
- }
-
- /* at this point, chain should contain a list of untrusted
- * certificates. We now need to add at least one trusted one,
- * if possible, otherwise we complain. */
-
- /* Examine last certificate in chain and see if it
- * is self signed.
- */
-
- i=sk_X509_num(ctx->chain);
- x=sk_X509_value(ctx->chain,i-1);
- if (cert_self_signed(x))
- {
- /* we have a self signed certificate */
- if (sk_X509_num(ctx->chain) == 1)
- {
- /* We have a single self signed certificate: see if
- * we can find it in the store. We must have an exact
- * match to avoid possible impersonation.
- */
- ok = ctx->get_issuer(&xtmp, ctx, x);
- if ((ok <= 0) || X509_cmp(x, xtmp))
- {
- ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
- ctx->current_cert=x;
- ctx->error_depth=i-1;
- if (ok == 1) X509_free(xtmp);
- bad_chain = 1;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- else
- {
- /* We have a match: replace certificate with store version
- * so we get any trust settings.
- */
- X509_free(x);
- x = xtmp;
- (void)sk_X509_set(ctx->chain, i - 1, x);
- ctx->last_untrusted=0;
- }
- }
- else
- {
- /* extract and save self signed certificate for later use */
- chain_ss=sk_X509_pop(ctx->chain);
- ctx->last_untrusted--;
- num--;
- x=sk_X509_value(ctx->chain,num-1);
- }
- }
-
- /* We now lookup certs from the certificate store */
- for (;;)
- {
- /* If we have enough, we break */
- if (depth < num) break;
-
- /* If we are self signed, we break */
- if (cert_self_signed(x))
- break;
-
- ok = ctx->get_issuer(&xtmp, ctx, x);
-
- if (ok < 0) goto end;
- if (ok == 0) break;
-
- x = xtmp;
- if (!sk_X509_push(ctx->chain,x))
- {
- X509_free(xtmp);
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- ok = 0;
- goto end;
- }
- num++;
- }
-
- /* we now have our chain, lets check it... */
-
- i = check_trust(ctx);
-
- /* If explicitly rejected error */
- if (i == X509_TRUST_REJECTED)
- goto end;
- /* If not explicitly trusted then indicate error unless it's
- * a single self signed certificate in which case we've indicated
- * an error already and set bad_chain == 1
- */
- if (i != X509_TRUST_TRUSTED && !bad_chain)
- {
- if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
- {
- if (ctx->last_untrusted >= num)
- ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
- else
- ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
- ctx->current_cert=x;
- }
- else
- {
-
- sk_X509_push(ctx->chain,chain_ss);
- num++;
- ctx->last_untrusted=num;
- ctx->current_cert=chain_ss;
- ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
- chain_ss=NULL;
- }
-
- ctx->error_depth=num-1;
- bad_chain = 1;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
-
- /* We have the chain complete: now we need to check its purpose */
- ok = check_chain_extensions(ctx);
-
- if (!ok) goto end;
-
- /* Check name constraints */
-
- ok = check_name_constraints(ctx);
-
- if (!ok) goto end;
-
- ok = check_id(ctx);
-
- if (!ok) goto end;
-
- /* Check revocation status: we do this after copying parameters
- * because they may be needed for CRL signature verification.
- */
-
- ok = ctx->check_revocation(ctx);
- if(!ok) goto end;
-
- i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
- ctx->param->flags);
- if (i != X509_V_OK)
- {
- ctx->error = i;
- ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
- ok = cb(0, ctx);
- if (!ok)
- goto end;
- }
-
- /* At this point, we have a chain and need to verify it */
- if (ctx->verify != NULL)
- ok=ctx->verify(ctx);
- else
- ok=internal_verify(ctx);
- if(!ok) goto end;
-
- /* If we get this far evaluate policies */
- if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
- ok = ctx->check_policy(ctx);
-
-end:
- if (sktmp != NULL) sk_X509_free(sktmp);
- if (chain_ss != NULL) X509_free(chain_ss);
- return ok;
- }
-
-
-/* Given a STACK_OF(X509) find the issuer of cert (if any)
+{
+ X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
+ int bad_chain = 0;
+ X509_VERIFY_PARAM *param = ctx->param;
+ int depth, i, ok = 0;
+ int num, j, retry, trust;
+ int (*cb) (int xok, X509_STORE_CTX *xctx);
+ STACK_OF(X509) *sktmp = NULL;
+ if (ctx->cert == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ return -1;
+ }
+ if (ctx->chain != NULL) {
+ /*
+ * This X509_STORE_CTX has already been used to verify a cert. We
+ * cannot do another one.
+ */
+ OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return -1;
+ }
+
+ cb = ctx->verify_cb;
+
+ /*
+ * first we make sure the chain we are going to build is present and that
+ * the first entry is in place
+ */
+ ctx->chain = sk_X509_new_null();
+ if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ X509_up_ref(ctx->cert);
+ ctx->last_untrusted = 1;
+
+ /* We use a temporary STACK so we can chop and hack at it */
+ if (ctx->untrusted != NULL
+ && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ num = sk_X509_num(ctx->chain);
+ x = sk_X509_value(ctx->chain, num - 1);
+ depth = param->depth;
+
+ for (;;) {
+ /* If we have enough, we break */
+ if (depth < num)
+ break; /* FIXME: If this happens, we should take
+ * note of it and, if appropriate, use the
+ * X509_V_ERR_CERT_CHAIN_TOO_LONG error code
+ * later. */
+
+ /* If we are self signed, we break */
+ if (cert_self_signed(x))
+ break;
+ /*
+ * If asked see if we can find issuer in trusted store first
+ */
+ if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+ if (ok < 0)
+ goto end;
+ /*
+ * If successful for now free up cert so it will be picked up
+ * again later.
+ */
+ if (ok > 0) {
+ X509_free(xtmp);
+ break;
+ }
+ }
+
+ /* If we were passed a cert chain, use it first */
+ if (ctx->untrusted != NULL) {
+ xtmp = find_issuer(ctx, sktmp, x);
+ if (xtmp != NULL) {
+ if (!sk_X509_push(ctx->chain, xtmp)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ok = 0;
+ goto end;
+ }
+ X509_up_ref(xtmp);
+ (void)sk_X509_delete_ptr(sktmp, xtmp);
+ ctx->last_untrusted++;
+ x = xtmp;
+ num++;
+ /*
+ * reparse the full chain for the next one
+ */
+ continue;
+ }
+ }
+ break;
+ }
+
+ /* Remember how many untrusted certs we have */
+ j = num;
+ /*
+ * at this point, chain should contain a list of untrusted certificates.
+ * We now need to add at least one trusted one, if possible, otherwise we
+ * complain.
+ */
+
+ do {
+ /*
+ * Examine last certificate in chain and see if it is self signed.
+ */
+ i = sk_X509_num(ctx->chain);
+ x = sk_X509_value(ctx->chain, i - 1);
+ if (cert_self_signed(x)) {
+ /* we have a self signed certificate */
+ if (sk_X509_num(ctx->chain) == 1) {
+ /*
+ * We have a single self signed certificate: see if we can
+ * find it in the store. We must have an exact match to avoid
+ * possible impersonation.
+ */
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+ if ((ok <= 0) || X509_cmp(x, xtmp)) {
+ ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+ ctx->current_cert = x;
+ ctx->error_depth = i - 1;
+ if (ok == 1)
+ X509_free(xtmp);
+ bad_chain = 1;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ } else {
+ /*
+ * We have a match: replace certificate with store
+ * version so we get any trust settings.
+ */
+ X509_free(x);
+ x = xtmp;
+ (void)sk_X509_set(ctx->chain, i - 1, x);
+ ctx->last_untrusted = 0;
+ }
+ } else {
+ /*
+ * extract and save self signed certificate for later use
+ */
+ chain_ss = sk_X509_pop(ctx->chain);
+ ctx->last_untrusted--;
+ num--;
+ j--;
+ x = sk_X509_value(ctx->chain, num - 1);
+ }
+ }
+ /* We now lookup certs from the certificate store */
+ for (;;) {
+ /* If we have enough, we break */
+ if (depth < num)
+ break;
+ /* If we are self signed, we break */
+ if (cert_self_signed(x))
+ break;
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+
+ if (ok < 0)
+ goto end;
+ if (ok == 0)
+ break;
+ x = xtmp;
+ if (!sk_X509_push(ctx->chain, x)) {
+ X509_free(xtmp);
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ok = 0;
+ goto end;
+ }
+ num++;
+ }
+
+ /* we now have our chain, lets check it... */
+ trust = check_trust(ctx);
+
+ /* If explicitly rejected error */
+ if (trust == X509_TRUST_REJECTED) {
+ ok = 0;
+ goto end;
+ }
+ /*
+ * If it's not explicitly trusted then check if there is an alternative
+ * chain that could be used. We only do this if we haven't already
+ * checked via TRUSTED_FIRST and the user hasn't switched off alternate
+ * chain checking
+ */
+ retry = 0;
+ if (trust != X509_TRUST_TRUSTED
+ && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
+ && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
+ while (j-- > 1) {
+ xtmp2 = sk_X509_value(ctx->chain, j - 1);
+ ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
+ if (ok < 0)
+ goto end;
+ /* Check if we found an alternate chain */
+ if (ok > 0) {
+ /*
+ * Free up the found cert we'll add it again later
+ */
+ X509_free(xtmp);
+
+ /*
+ * Dump all the certs above this point - we've found an
+ * alternate chain
+ */
+ while (num > j) {
+ xtmp = sk_X509_pop(ctx->chain);
+ X509_free(xtmp);
+ num--;
+ }
+ ctx->last_untrusted = sk_X509_num(ctx->chain);
+ retry = 1;
+ break;
+ }
+ }
+ }
+ } while (retry);
+
+ /*
+ * If not explicitly trusted then indicate error unless it's a single
+ * self signed certificate in which case we've indicated an error already
+ * and set bad_chain == 1
+ */
+ if (trust != X509_TRUST_TRUSTED && !bad_chain) {
+ if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
+ if (ctx->last_untrusted >= num)
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
+ else
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+ ctx->current_cert = x;
+ } else {
+
+ sk_X509_push(ctx->chain, chain_ss);
+ num++;
+ ctx->last_untrusted = num;
+ ctx->current_cert = chain_ss;
+ ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+ chain_ss = NULL;
+ }
+
+ ctx->error_depth = num - 1;
+ bad_chain = 1;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+
+ /* We have the chain complete: now we need to check its purpose */
+ ok = check_chain_extensions(ctx);
+
+ if (!ok)
+ goto end;
+
+ /* Check name constraints */
+
+ ok = check_name_constraints(ctx);
+
+ if (!ok)
+ goto end;
+
+ ok = check_id(ctx);
+
+ if (!ok)
+ goto end;
+
+ /*
+ * Check revocation status: we do this after copying parameters because
+ * they may be needed for CRL signature verification.
+ */
+
+ ok = ctx->check_revocation(ctx);
+ if (!ok)
+ goto end;
+
+ int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
+ ctx->param->flags);
+ if (err != X509_V_OK) {
+ ctx->error = err;
+ ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+
+ /* At this point, we have a chain and need to verify it */
+ if (ctx->verify != NULL)
+ ok = ctx->verify(ctx);
+ else
+ ok = internal_verify(ctx);
+ if (!ok)
+ goto end;
+
+ /* If we get this far evaluate policies */
+ if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
+ ok = ctx->check_policy(ctx);
+
+ end:
+ if (sktmp != NULL)
+ sk_X509_free(sktmp);
+ if (chain_ss != NULL)
+ X509_free(chain_ss);
+ return ok;
+}
+
+/*
+ * Given a STACK_OF(X509) find the issuer of cert (if any)
*/
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
- size_t i;
- X509 *issuer;
- for (i = 0; i < sk_X509_num(sk); i++)
- {
- issuer = sk_X509_value(sk, i);
- if (ctx->check_issued(ctx, x, issuer))
- return issuer;
- }
- return NULL;
+ size_t i;
+ X509 *issuer;
+ for (i = 0; i < sk_X509_num(sk); i++) {
+ issuer = sk_X509_value(sk, i);
+ if (ctx->check_issued(ctx, x, issuer))
+ return issuer;
+ }
+ return NULL;
}
/* Given a possible certificate and issuer check them */
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
- int ret;
- ret = X509_check_issued(issuer, x);
- if (ret == X509_V_OK)
- return 1;
- /* If we haven't asked for issuer errors don't set ctx */
- if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
- return 0;
-
- ctx->error = ret;
- ctx->current_cert = x;
- ctx->current_issuer = issuer;
- return ctx->verify_cb(0, ctx);
+ int ret;
+ ret = X509_check_issued(issuer, x);
+ if (ret == X509_V_OK)
+ return 1;
+ /* If we haven't asked for issuer errors don't set ctx */
+ if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
+ return 0;
+
+ ctx->error = ret;
+ ctx->current_cert = x;
+ ctx->current_issuer = issuer;
+ return ctx->verify_cb(0, ctx);
}
/* Alternative lookup method: look from a STACK stored in other_ctx */
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
- *issuer = find_issuer(ctx, ctx->other_ctx, x);
- if (*issuer)
- {
- X509_up_ref(*issuer);
- return 1;
- }
- else
- return 0;
+ *issuer = find_issuer(ctx, ctx->other_ctx, x);
+ if (*issuer) {
+ X509_up_ref(*issuer);
+ return 1;
+ } else
+ return 0;
}
-
-/* Check a certificate chains extensions for consistency
- * with the supplied purpose
+/*
+ * Check a certificate chains extensions for consistency with the supplied
+ * purpose
*/
static int check_chain_extensions(X509_STORE_CTX *ctx)
{
- int i, ok=0, must_be_ca, plen = 0;
- X509 *x;
- int (*cb)(int xok,X509_STORE_CTX *xctx);
- int proxy_path_length = 0;
- int purpose;
- int allow_proxy_certs;
- cb=ctx->verify_cb;
-
- /* must_be_ca can have 1 of 3 values:
- -1: we accept both CA and non-CA certificates, to allow direct
- use of self-signed certificates (which are marked as CA).
- 0: we only accept non-CA certificates. This is currently not
- used, but the possibility is present for future extensions.
- 1: we only accept CA certificates. This is currently used for
- all certificates in the chain except the leaf certificate.
- */
- must_be_ca = -1;
-
- /* CRL path validation */
- if (ctx->parent)
- {
- allow_proxy_certs = 0;
- purpose = X509_PURPOSE_CRL_SIGN;
- }
- else
- {
- allow_proxy_certs =
- !!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
- /* A hack to keep people who don't want to modify their
- software happy */
- if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
- allow_proxy_certs = 1;
- purpose = ctx->param->purpose;
- }
-
- /* Check all untrusted certificates */
- for (i = 0; i < ctx->last_untrusted; i++)
- {
- int ret;
- x = sk_X509_value(ctx->chain, i);
- if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
- && (x->ex_flags & EXFLAG_CRITICAL))
- {
- ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
- {
- ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- ret = X509_check_ca(x);
- switch(must_be_ca)
- {
- case -1:
- if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
- && (ret != 1) && (ret != 0))
- {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_CA;
- }
- else
- ret = 1;
- break;
- case 0:
- if (ret != 0)
- {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_NON_CA;
- }
- else
- ret = 1;
- break;
- default:
- if ((ret == 0)
- || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
- && (ret != 1)))
- {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_CA;
- }
- else
- ret = 1;
- break;
- }
- if (ret == 0)
- {
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- if (ctx->param->purpose > 0)
- {
- ret = X509_check_purpose(x, purpose, must_be_ca > 0);
- if ((ret == 0)
- || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
- && (ret != 1)))
- {
- ctx->error = X509_V_ERR_INVALID_PURPOSE;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- }
- /* Check pathlen if not self issued */
- if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
- && (x->ex_pathlen != -1)
- && (plen > (x->ex_pathlen + proxy_path_length + 1)))
- {
- ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- /* Increment path length if not self issued */
- if (!(x->ex_flags & EXFLAG_SI))
- plen++;
- /* If this certificate is a proxy certificate, the next
- certificate must be another proxy certificate or a EE
- certificate. If not, the next certificate must be a
- CA certificate. */
- if (x->ex_flags & EXFLAG_PROXY)
- {
- if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
- {
- ctx->error =
- X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok=cb(0,ctx);
- if (!ok) goto end;
- }
- proxy_path_length++;
- must_be_ca = 0;
- }
- else
- must_be_ca = 1;
- }
- ok = 1;
+ int i, ok = 0, must_be_ca, plen = 0;
+ X509 *x;
+ int (*cb) (int xok, X509_STORE_CTX *xctx);
+ int proxy_path_length = 0;
+ int purpose;
+ int allow_proxy_certs;
+ cb = ctx->verify_cb;
+
+ /*
+ * must_be_ca can have 1 of 3 values: -1: we accept both CA and non-CA
+ * certificates, to allow direct use of self-signed certificates (which
+ * are marked as CA). 0: we only accept non-CA certificates. This is
+ * currently not used, but the possibility is present for future
+ * extensions. 1: we only accept CA certificates. This is currently used
+ * for all certificates in the chain except the leaf certificate.
+ */
+ must_be_ca = -1;
+
+ /* CRL path validation */
+ if (ctx->parent) {
+ allow_proxy_certs = 0;
+ purpose = X509_PURPOSE_CRL_SIGN;
+ } else {
+ allow_proxy_certs =
+ ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
+ /*
+ * A hack to keep people who don't want to modify their software
+ * happy
+ */
+ if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
+ allow_proxy_certs = 1;
+ purpose = ctx->param->purpose;
+ }
+
+ /* Check all untrusted certificates */
+ for (i = 0; i < ctx->last_untrusted; i++) {
+ int ret;
+ x = sk_X509_value(ctx->chain, i);
+ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+ && (x->ex_flags & EXFLAG_CRITICAL)) {
+ ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
+ ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ ret = X509_check_ca(x);
+ switch (must_be_ca) {
+ case -1:
+ if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1) && (ret != 0)) {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_CA;
+ } else
+ ret = 1;
+ break;
+ case 0:
+ if (ret != 0) {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_NON_CA;
+ } else
+ ret = 1;
+ break;
+ default:
+ if ((ret == 0)
+ || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1))) {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_CA;
+ } else
+ ret = 1;
+ break;
+ }
+ if (ret == 0) {
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ if (ctx->param->purpose > 0) {
+ ret = X509_check_purpose(x, purpose, must_be_ca > 0);
+ if ((ret == 0)
+ || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1))) {
+ ctx->error = X509_V_ERR_INVALID_PURPOSE;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ }
+ /* Check pathlen if not self issued */
+ if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
+ && (x->ex_pathlen != -1)
+ && (plen > (x->ex_pathlen + proxy_path_length + 1))) {
+ ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ /* Increment path length if not self issued */
+ if (!(x->ex_flags & EXFLAG_SI))
+ plen++;
+ /*
+ * If this certificate is a proxy certificate, the next certificate
+ * must be another proxy certificate or a EE certificate. If not,
+ * the next certificate must be a CA certificate.
+ */
+ if (x->ex_flags & EXFLAG_PROXY) {
+ if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) {
+ ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ proxy_path_length++;
+ must_be_ca = 0;
+ } else
+ must_be_ca = 1;
+ }
+ ok = 1;
end:
- return ok;
+ return ok;
}
static int check_name_constraints(X509_STORE_CTX *ctx)
- {
- X509 *x;
- int i, j, rv;
- /* Check name constraints for all certificates */
- for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--)
- {
- x = sk_X509_value(ctx->chain, i);
- /* Ignore self issued certs unless last in chain */
- if (i && (x->ex_flags & EXFLAG_SI))
- continue;
- /* Check against constraints for all certificates higher in
- * chain including trust anchor. Trust anchor not strictly
- * speaking needed but if it includes constraints it is to be
- * assumed it expects them to be obeyed.
- */
- for (j = sk_X509_num(ctx->chain) - 1; j > i; j--)
- {
- NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
- if (nc)
- {
- rv = NAME_CONSTRAINTS_check(x, nc);
- if (rv != X509_V_OK)
- {
- ctx->error = rv;
- ctx->error_depth = i;
- ctx->current_cert = x;
- if (!ctx->verify_cb(0,ctx))
- return 0;
- }
- }
- }
- }
- return 1;
- }
+{
+ X509 *x;
+ int i, j, rv;
+ /* Check name constraints for all certificates */
+ for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) {
+ x = sk_X509_value(ctx->chain, i);
+ /* Ignore self issued certs unless last in chain */
+ if (i && (x->ex_flags & EXFLAG_SI))
+ continue;
+ /*
+ * Check against constraints for all certificates higher in chain
+ * including trust anchor. Trust anchor not strictly speaking needed
+ * but if it includes constraints it is to be assumed it expects them
+ * to be obeyed.
+ */
+ for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) {
+ NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
+ if (nc) {
+ rv = NAME_CONSTRAINTS_check(x, nc);
+ if (rv != X509_V_OK) {
+ ctx->error = rv;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+}
static int check_id_error(X509_STORE_CTX *ctx, int errcode)
- {
- ctx->error = errcode;
- ctx->current_cert = ctx->cert;
- ctx->error_depth = 0;
- return ctx->verify_cb(0, ctx);
- }
+{
+ ctx->error = errcode;
+ ctx->current_cert = ctx->cert;
+ ctx->error_depth = 0;
+ return ctx->verify_cb(0, ctx);
+}
static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
- {
- size_t i;
- size_t n = sk_OPENSSL_STRING_num(id->hosts);
- char *name;
-
- for (i = 0; i < n; ++i)
- {
- name = sk_OPENSSL_STRING_value(id->hosts, i);
- if (X509_check_host(x, name, strlen(name), id->hostflags,
- &id->peername) > 0)
- return 1;
- }
- return n == 0;
- }
+{
+ size_t i;
+ size_t n = sk_OPENSSL_STRING_num(id->hosts);
+ char *name;
+
+ if (id->peername != NULL) {
+ OPENSSL_free(id->peername);
+ id->peername = NULL;
+ }
+ for (i = 0; i < n; ++i) {
+ name = sk_OPENSSL_STRING_value(id->hosts, i);
+ if (X509_check_host(x, name, strlen(name), id->hostflags,
+ &id->peername) > 0)
+ return 1;
+ }
+ return n == 0;
+}
static int check_id(X509_STORE_CTX *ctx)
- {
- X509_VERIFY_PARAM *vpm = ctx->param;
- X509_VERIFY_PARAM_ID *id = vpm->id;
- X509 *x = ctx->cert;
- if (id->hosts && check_hosts(x, id) <= 0)
- {
- if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
- return 0;
- }
- if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0)
- {
- if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
- return 0;
- }
- if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0)
- {
- if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
- return 0;
- }
- return 1;
- }
+{
+ X509_VERIFY_PARAM *vpm = ctx->param;
+ X509_VERIFY_PARAM_ID *id = vpm->id;
+ X509 *x = ctx->cert;
+ if (id->hosts && check_hosts(x, id) <= 0) {
+ if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
+ return 0;
+ }
+ if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0) {
+ if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
+ return 0;
+ }
+ if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) {
+ if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
+ return 0;
+ }
+ return 1;
+}
static int check_trust(X509_STORE_CTX *ctx)
{
- size_t i;
- int ok;
- X509 *x = NULL;
- int (*cb)(int xok,X509_STORE_CTX *xctx);
- cb=ctx->verify_cb;
- /* Check all trusted certificates in chain */
- for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++)
- {
- x = sk_X509_value(ctx->chain, i);
- ok = X509_check_trust(x, ctx->param->trust, 0);
- /* If explicitly trusted return trusted */
- if (ok == X509_TRUST_TRUSTED)
- return X509_TRUST_TRUSTED;
- /* If explicitly rejected notify callback and reject if
- * not overridden.
- */
- if (ok == X509_TRUST_REJECTED)
- {
- ctx->error_depth = i;
- ctx->current_cert = x;
- ctx->error = X509_V_ERR_CERT_REJECTED;
- ok = cb(0, ctx);
- if (!ok)
- return X509_TRUST_REJECTED;
- }
- }
- /* If we accept partial chains and have at least one trusted
- * certificate return success.
- */
- if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
- {
- X509 *mx;
- if (ctx->last_untrusted < (int) sk_X509_num(ctx->chain))
- return X509_TRUST_TRUSTED;
- x = sk_X509_value(ctx->chain, 0);
- mx = lookup_cert_match(ctx, x);
- if (mx)
- {
- (void)sk_X509_set(ctx->chain, 0, mx);
- X509_free(x);
- ctx->last_untrusted = 0;
- return X509_TRUST_TRUSTED;
- }
- }
-
- /* If no trusted certs in chain at all return untrusted and
- * allow standard (no issuer cert) etc errors to be indicated.
- */
- return X509_TRUST_UNTRUSTED;
+ size_t i;
+ int ok;
+ X509 *x = NULL;
+ int (*cb) (int xok, X509_STORE_CTX *xctx);
+ cb = ctx->verify_cb;
+ /* Check all trusted certificates in chain */
+ for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) {
+ x = sk_X509_value(ctx->chain, i);
+ ok = X509_check_trust(x, ctx->param->trust, 0);
+ /* If explicitly trusted return trusted */
+ if (ok == X509_TRUST_TRUSTED)
+ return X509_TRUST_TRUSTED;
+ /*
+ * If explicitly rejected notify callback and reject if not
+ * overridden.
+ */
+ if (ok == X509_TRUST_REJECTED) {
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ctx->error = X509_V_ERR_CERT_REJECTED;
+ ok = cb(0, ctx);
+ if (!ok)
+ return X509_TRUST_REJECTED;
+ }
+ }
+ /*
+ * If we accept partial chains and have at least one trusted certificate
+ * return success.
+ */
+ if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+ X509 *mx;
+ if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain))
+ return X509_TRUST_TRUSTED;
+ x = sk_X509_value(ctx->chain, 0);
+ mx = lookup_cert_match(ctx, x);
+ if (mx) {
+ (void)sk_X509_set(ctx->chain, 0, mx);
+ X509_free(x);
+ ctx->last_untrusted = 0;
+ return X509_TRUST_TRUSTED;
+ }
+ }
+
+ /*
+ * If no trusted certs in chain at all return untrusted and allow
+ * standard (no issuer cert) etc errors to be indicated.
+ */
+ return X509_TRUST_UNTRUSTED;
}
static int check_revocation(X509_STORE_CTX *ctx)
- {
- int i, last, ok;
- if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
- return 1;
- if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
- last = sk_X509_num(ctx->chain) - 1;
- else
- {
- /* If checking CRL paths this isn't the EE certificate */
- if (ctx->parent)
- return 1;
- last = 0;
- }
- for(i = 0; i <= last; i++)
- {
- ctx->error_depth = i;
- ok = check_cert(ctx);
- if (!ok) return ok;
- }
- return 1;
- }
+{
+ int i, last, ok;
+ if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
+ return 1;
+ if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
+ last = sk_X509_num(ctx->chain) - 1;
+ else {
+ /* If checking CRL paths this isn't the EE certificate */
+ if (ctx->parent)
+ return 1;
+ last = 0;
+ }
+ for (i = 0; i <= last; i++) {
+ ctx->error_depth = i;
+ ok = check_cert(ctx);
+ if (!ok)
+ return ok;
+ }
+ return 1;
+}
static int check_cert(X509_STORE_CTX *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
- {
- X509_CRL *crl = NULL, *dcrl = NULL;
- X509 *x;
- int ok, cnum;
- unsigned int last_reasons;
- cnum = ctx->error_depth;
- x = sk_X509_value(ctx->chain, cnum);
- ctx->current_cert = x;
- ctx->current_issuer = NULL;
- ctx->current_crl_score = 0;
- ctx->current_reasons = 0;
- while (ctx->current_reasons != CRLDP_ALL_REASONS)
- {
- last_reasons = ctx->current_reasons;
- /* Try to retrieve relevant CRL */
- if (ctx->get_crl)
- ok = ctx->get_crl(ctx, &crl, x);
- else
- ok = get_crl_delta(ctx, &crl, &dcrl, x);
- /* If error looking up CRL, nothing we can do except
- * notify callback
- */
- if(!ok)
- {
- ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
- ok = ctx->verify_cb(0, ctx);
- goto err;
- }
- ctx->current_crl = crl;
- ok = ctx->check_crl(ctx, crl);
- if (!ok)
- goto err;
-
- if (dcrl)
- {
- ok = ctx->check_crl(ctx, dcrl);
- if (!ok)
- goto err;
- ok = ctx->cert_crl(ctx, dcrl, x);
- if (!ok)
- goto err;
- }
- else
- ok = 1;
-
- /* Don't look in full CRL if delta reason is removefromCRL */
- if (ok != 2)
- {
- ok = ctx->cert_crl(ctx, crl, x);
- if (!ok)
- goto err;
- }
-
- X509_CRL_free(crl);
- X509_CRL_free(dcrl);
- crl = NULL;
- dcrl = NULL;
- /* If reasons not updated we wont get anywhere by
- * another iteration, so exit loop.
- */
- if (last_reasons == ctx->current_reasons)
- {
- ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
- ok = ctx->verify_cb(0, ctx);
- goto err;
- }
- }
- err:
- X509_CRL_free(crl);
- X509_CRL_free(dcrl);
-
- ctx->current_crl = NULL;
- return ok;
-
- }
+{
+ X509_CRL *crl = NULL, *dcrl = NULL;
+ X509 *x;
+ int ok = 0, cnum;
+ unsigned int last_reasons;
+ cnum = ctx->error_depth;
+ x = sk_X509_value(ctx->chain, cnum);
+ ctx->current_cert = x;
+ ctx->current_issuer = NULL;
+ ctx->current_crl_score = 0;
+ ctx->current_reasons = 0;
+ while (ctx->current_reasons != CRLDP_ALL_REASONS) {
+ last_reasons = ctx->current_reasons;
+ /* Try to retrieve relevant CRL */
+ if (ctx->get_crl)
+ ok = ctx->get_crl(ctx, &crl, x);
+ else
+ ok = get_crl_delta(ctx, &crl, &dcrl, x);
+ /*
+ * If error looking up CRL, nothing we can do except notify callback
+ */
+ if (!ok) {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+ ok = ctx->verify_cb(0, ctx);
+ goto err;
+ }
+ ctx->current_crl = crl;
+ ok = ctx->check_crl(ctx, crl);
+ if (!ok)
+ goto err;
+
+ if (dcrl) {
+ ok = ctx->check_crl(ctx, dcrl);
+ if (!ok)
+ goto err;
+ ok = ctx->cert_crl(ctx, dcrl, x);
+ if (!ok)
+ goto err;
+ } else
+ ok = 1;
+
+ /* Don't look in full CRL if delta reason is removefromCRL */
+ if (ok != 2) {
+ ok = ctx->cert_crl(ctx, crl, x);
+ if (!ok)
+ goto err;
+ }
+
+ X509_CRL_free(crl);
+ X509_CRL_free(dcrl);
+ crl = NULL;
+ dcrl = NULL;
+ /*
+ * If reasons not updated we wont get anywhere by another iteration,
+ * so exit loop.
+ */
+ if (last_reasons == ctx->current_reasons) {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+ ok = ctx->verify_cb(0, ctx);
+ goto err;
+ }
+ }
+ err:
+ X509_CRL_free(crl);
+ X509_CRL_free(dcrl);
+
+ ctx->current_crl = NULL;
+ return ok;
+
+}
/* Check CRL times against values in X509_STORE_CTX */
static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
- {
- time_t *ptime;
- int i;
- if (notify)
- ctx->current_crl = crl;
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
- ptime = &ctx->param->check_time;
- else
- ptime = NULL;
-
- i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
- if (i == 0)
- {
- if (!notify)
- return 0;
- ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- if (i > 0)
- {
- if (!notify)
- return 0;
- ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- if(X509_CRL_get_nextUpdate(crl))
- {
- i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
-
- if (i == 0)
- {
- if (!notify)
- return 0;
- ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
- /* Ignore expiry of base CRL is delta is valid */
- if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA))
- {
- if (!notify)
- return 0;
- ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
- }
-
- if (notify)
- ctx->current_crl = NULL;
-
- return 1;
- }
+{
+ time_t *ptime;
+ int i;
+ if (notify)
+ ctx->current_crl = crl;
+ if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ ptime = &ctx->param->check_time;
+ else
+ ptime = NULL;
+
+ i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
+ if (i == 0) {
+ if (!notify)
+ return 0;
+ ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i > 0) {
+ if (!notify)
+ return 0;
+ ctx->error = X509_V_ERR_CRL_NOT_YET_VALID;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (X509_CRL_get_nextUpdate(crl)) {
+ i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
+
+ if (i == 0) {
+ if (!notify)
+ return 0;
+ ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ /* Ignore expiry of base CRL is delta is valid */
+ if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) {
+ if (!notify)
+ return 0;
+ ctx->error = X509_V_ERR_CRL_HAS_EXPIRED;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ }
+
+ if (notify)
+ ctx->current_crl = NULL;
+
+ return 1;
+}
static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
- X509 **pissuer, int *pscore, unsigned int *preasons,
- STACK_OF(X509_CRL) *crls)
- {
- int crl_score, best_score = *pscore;
- size_t i;
- unsigned int reasons, best_reasons = 0;
- X509 *x = ctx->current_cert;
- X509_CRL *crl, *best_crl = NULL;
- X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
-
- for (i = 0; i < sk_X509_CRL_num(crls); i++)
- {
- crl = sk_X509_CRL_value(crls, i);
- reasons = *preasons;
- crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
-
- if (crl_score > best_score)
- {
- best_crl = crl;
- best_crl_issuer = crl_issuer;
- best_score = crl_score;
- best_reasons = reasons;
- }
- }
-
- if (best_crl)
- {
- if (*pcrl)
- X509_CRL_free(*pcrl);
- *pcrl = best_crl;
- *pissuer = best_crl_issuer;
- *pscore = best_score;
- *preasons = best_reasons;
- X509_CRL_up_ref(best_crl);
- if (*pdcrl)
- {
- X509_CRL_free(*pdcrl);
- *pdcrl = NULL;
- }
- get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
- }
-
- if (best_score >= CRL_SCORE_VALID)
- return 1;
-
- return 0;
- }
-
-/* Compare two CRL extensions for delta checking purposes. They should be
+ X509 **pissuer, int *pscore, unsigned int *preasons,
+ STACK_OF(X509_CRL) *crls)
+{
+ int crl_score, best_score = *pscore;
+ size_t i;
+ unsigned int reasons, best_reasons = 0;
+ X509 *x = ctx->current_cert;
+ X509_CRL *crl, *best_crl = NULL;
+ X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
+
+ for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+ crl = sk_X509_CRL_value(crls, i);
+ reasons = *preasons;
+ crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
+
+ if (crl_score > best_score) {
+ best_crl = crl;
+ best_crl_issuer = crl_issuer;
+ best_score = crl_score;
+ best_reasons = reasons;
+ }
+ }
+
+ if (best_crl) {
+ if (*pcrl)
+ X509_CRL_free(*pcrl);
+ *pcrl = best_crl;
+ *pissuer = best_crl_issuer;
+ *pscore = best_score;
+ *preasons = best_reasons;
+ X509_CRL_up_ref(best_crl);
+ if (*pdcrl) {
+ X509_CRL_free(*pdcrl);
+ *pdcrl = NULL;
+ }
+ get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
+ }
+
+ if (best_score >= CRL_SCORE_VALID)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Compare two CRL extensions for delta checking purposes. They should be
* both present or both absent. If both present all fields must be identical.
*/
static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
- {
- ASN1_OCTET_STRING *exta, *extb;
- int i;
- i = X509_CRL_get_ext_by_NID(a, nid, -1);
- if (i >= 0)
- {
- /* Can't have multiple occurrences */
- if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
- return 0;
- exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
- }
- else
- exta = NULL;
-
- i = X509_CRL_get_ext_by_NID(b, nid, -1);
+{
+ ASN1_OCTET_STRING *exta, *extb;
+ int i;
+ i = X509_CRL_get_ext_by_NID(a, nid, -1);
+ if (i >= 0) {
+ /* Can't have multiple occurrences */
+ if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
+ return 0;
+ exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
+ } else
+ exta = NULL;
- if (i >= 0)
- {
+ i = X509_CRL_get_ext_by_NID(b, nid, -1);
- if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
- return 0;
- extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
- }
- else
- extb = NULL;
+ if (i >= 0) {
- if (!exta && !extb)
- return 1;
+ if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
+ return 0;
+ extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
+ } else
+ extb = NULL;
- if (!exta || !extb)
- return 0;
+ if (!exta && !extb)
+ return 1;
+ if (!exta || !extb)
+ return 0;
- if (ASN1_OCTET_STRING_cmp(exta, extb))
- return 0;
+ if (ASN1_OCTET_STRING_cmp(exta, extb))
+ return 0;
- return 1;
- }
+ return 1;
+}
/* See if a base and delta are compatible */
static int check_delta_base(X509_CRL *delta, X509_CRL *base)
- {
- /* Delta CRL must be a delta */
- if (!delta->base_crl_number)
- return 0;
- /* Base must have a CRL number */
- if (!base->crl_number)
- return 0;
- /* Issuer names must match */
- if (X509_NAME_cmp(X509_CRL_get_issuer(base),
- X509_CRL_get_issuer(delta)))
- return 0;
- /* AKID and IDP must match */
- if (!crl_extension_match(delta, base, NID_authority_key_identifier))
- return 0;
- if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
- return 0;
- /* Delta CRL base number must not exceed Full CRL number. */
- if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
- return 0;
- /* Delta CRL number must exceed full CRL number */
- if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
- return 1;
- return 0;
- }
-
-/* For a given base CRL find a delta... maybe extend to delta scoring
- * or retrieve a chain of deltas...
+{
+ /* Delta CRL must be a delta */
+ if (!delta->base_crl_number)
+ return 0;
+ /* Base must have a CRL number */
+ if (!base->crl_number)
+ return 0;
+ /* Issuer names must match */
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta)))
+ return 0;
+ /* AKID and IDP must match */
+ if (!crl_extension_match(delta, base, NID_authority_key_identifier))
+ return 0;
+ if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
+ return 0;
+ /* Delta CRL base number must not exceed Full CRL number. */
+ if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
+ return 0;
+ /* Delta CRL number must exceed full CRL number */
+ if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * For a given base CRL find a delta... maybe extend to delta scoring or
+ * retrieve a chain of deltas...
*/
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
- X509_CRL *base, STACK_OF(X509_CRL) *crls)
- {
- X509_CRL *delta;
- size_t i;
- if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
- return;
- if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
- return;
- for (i = 0; i < sk_X509_CRL_num(crls); i++)
- {
- delta = sk_X509_CRL_value(crls, i);
- if (check_delta_base(delta, base))
- {
- if (check_crl_time(ctx, delta, 0))
- *pscore |= CRL_SCORE_TIME_DELTA;
- X509_CRL_up_ref(delta);
- *dcrl = delta;
- return;
- }
- }
- *dcrl = NULL;
- }
-
-/* For a given CRL return how suitable it is for the supplied certificate 'x'.
- * The return value is a mask of several criteria.
- * If the issuer is not the certificate issuer this is returned in *pissuer.
- * The reasons mask is also used to determine if the CRL is suitable: if
- * no new reasons the CRL is rejected, otherwise reasons is updated.
+ X509_CRL *base, STACK_OF(X509_CRL) *crls)
+{
+ X509_CRL *delta;
+ size_t i;
+ if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
+ return;
+ if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
+ return;
+ for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+ delta = sk_X509_CRL_value(crls, i);
+ if (check_delta_base(delta, base)) {
+ if (check_crl_time(ctx, delta, 0))
+ *pscore |= CRL_SCORE_TIME_DELTA;
+ X509_CRL_up_ref(delta);
+ *dcrl = delta;
+ return;
+ }
+ }
+ *dcrl = NULL;
+}
+
+/*
+ * For a given CRL return how suitable it is for the supplied certificate
+ * 'x'. The return value is a mask of several criteria. If the issuer is not
+ * the certificate issuer this is returned in *pissuer. The reasons mask is
+ * also used to determine if the CRL is suitable: if no new reasons the CRL
+ * is rejected, otherwise reasons is updated.
*/
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
- unsigned int *preasons,
- X509_CRL *crl, X509 *x)
- {
-
- int crl_score = 0;
- unsigned int tmp_reasons = *preasons, crl_reasons;
-
- /* First see if we can reject CRL straight away */
-
- /* Invalid IDP cannot be processed */
- if (crl->idp_flags & IDP_INVALID)
- return 0;
- /* Reason codes or indirect CRLs need extended CRL support */
- if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
- {
- if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
- return 0;
- }
- else if (crl->idp_flags & IDP_REASONS)
- {
- /* If no new reasons reject */
- if (!(crl->idp_reasons & ~tmp_reasons))
- return 0;
- }
- /* Don't process deltas at this stage */
- else if (crl->base_crl_number)
- return 0;
- /* If issuer name doesn't match certificate need indirect CRL */
- if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)))
- {
- if (!(crl->idp_flags & IDP_INDIRECT))
- return 0;
- }
- else
- crl_score |= CRL_SCORE_ISSUER_NAME;
-
- if (!(crl->flags & EXFLAG_CRITICAL))
- crl_score |= CRL_SCORE_NOCRITICAL;
-
- /* Check expiry */
- if (check_crl_time(ctx, crl, 0))
- crl_score |= CRL_SCORE_TIME;
-
- /* Check authority key ID and locate certificate issuer */
- crl_akid_check(ctx, crl, pissuer, &crl_score);
-
- /* If we can't locate certificate issuer at this point forget it */
-
- if (!(crl_score & CRL_SCORE_AKID))
- return 0;
-
- /* Check cert for matching CRL distribution points */
-
- if (crl_crldp_check(x, crl, crl_score, &crl_reasons))
- {
- /* If no new reasons reject */
- if (!(crl_reasons & ~tmp_reasons))
- return 0;
- tmp_reasons |= crl_reasons;
- crl_score |= CRL_SCORE_SCOPE;
- }
-
- *preasons = tmp_reasons;
-
- return crl_score;
-
- }
+ unsigned int *preasons, X509_CRL *crl, X509 *x)
+{
+
+ int crl_score = 0;
+ unsigned int tmp_reasons = *preasons, crl_reasons;
+
+ /* First see if we can reject CRL straight away */
+
+ /* Invalid IDP cannot be processed */
+ if (crl->idp_flags & IDP_INVALID)
+ return 0;
+ /* Reason codes or indirect CRLs need extended CRL support */
+ if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) {
+ if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
+ return 0;
+ } else if (crl->idp_flags & IDP_REASONS) {
+ /* If no new reasons reject */
+ if (!(crl->idp_reasons & ~tmp_reasons))
+ return 0;
+ }
+ /* Don't process deltas at this stage */
+ else if (crl->base_crl_number)
+ return 0;
+ /* If issuer name doesn't match certificate need indirect CRL */
+ if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) {
+ if (!(crl->idp_flags & IDP_INDIRECT))
+ return 0;
+ } else
+ crl_score |= CRL_SCORE_ISSUER_NAME;
+
+ if (!(crl->flags & EXFLAG_CRITICAL))
+ crl_score |= CRL_SCORE_NOCRITICAL;
+
+ /* Check expiry */
+ if (check_crl_time(ctx, crl, 0))
+ crl_score |= CRL_SCORE_TIME;
+
+ /* Check authority key ID and locate certificate issuer */
+ crl_akid_check(ctx, crl, pissuer, &crl_score);
+
+ /* If we can't locate certificate issuer at this point forget it */
+
+ if (!(crl_score & CRL_SCORE_AKID))
+ return 0;
+
+ /* Check cert for matching CRL distribution points */
+
+ if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) {
+ /* If no new reasons reject */
+ if (!(crl_reasons & ~tmp_reasons))
+ return 0;
+ tmp_reasons |= crl_reasons;
+ crl_score |= CRL_SCORE_SCOPE;
+ }
+
+ *preasons = tmp_reasons;
+
+ return crl_score;
+
+}
static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
- X509 **pissuer, int *pcrl_score)
- {
- X509 *crl_issuer = NULL;
- X509_NAME *cnm = X509_CRL_get_issuer(crl);
- int cidx = ctx->error_depth;
- size_t i;
-
- if ((size_t) cidx != sk_X509_num(ctx->chain) - 1)
- cidx++;
-
- crl_issuer = sk_X509_value(ctx->chain, cidx);
-
- if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
- {
- if (*pcrl_score & CRL_SCORE_ISSUER_NAME)
- {
- *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT;
- *pissuer = crl_issuer;
- return;
- }
- }
-
- for (cidx++; cidx < (int) sk_X509_num(ctx->chain); cidx++)
- {
- crl_issuer = sk_X509_value(ctx->chain, cidx);
- if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
- continue;
- if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
- {
- *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH;
- *pissuer = crl_issuer;
- return;
- }
- }
-
- /* Anything else needs extended CRL support */
-
- if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
- return;
-
- /* Otherwise the CRL issuer is not on the path. Look for it in the
- * set of untrusted certificates.
- */
- for (i = 0; i < sk_X509_num(ctx->untrusted); i++)
- {
- crl_issuer = sk_X509_value(ctx->untrusted, i);
- if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
- continue;
- if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
- {
- *pissuer = crl_issuer;
- *pcrl_score |= CRL_SCORE_AKID;
- return;
- }
- }
- }
-
-/* Check the path of a CRL issuer certificate. This creates a new
+ X509 **pissuer, int *pcrl_score)
+{
+ X509 *crl_issuer = NULL;
+ X509_NAME *cnm = X509_CRL_get_issuer(crl);
+ int cidx = ctx->error_depth;
+ size_t i;
+
+ if ((size_t)cidx != sk_X509_num(ctx->chain) - 1)
+ cidx++;
+
+ crl_issuer = sk_X509_value(ctx->chain, cidx);
+
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+ if (*pcrl_score & CRL_SCORE_ISSUER_NAME) {
+ *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT;
+ *pissuer = crl_issuer;
+ return;
+ }
+ }
+
+ for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) {
+ crl_issuer = sk_X509_value(ctx->chain, cidx);
+ if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+ continue;
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+ *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH;
+ *pissuer = crl_issuer;
+ return;
+ }
+ }
+
+ /* Anything else needs extended CRL support */
+
+ if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
+ return;
+
+ /*
+ * Otherwise the CRL issuer is not on the path. Look for it in the set of
+ * untrusted certificates.
+ */
+ for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
+ crl_issuer = sk_X509_value(ctx->untrusted, i);
+ if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+ continue;
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+ *pissuer = crl_issuer;
+ *pcrl_score |= CRL_SCORE_AKID;
+ return;
+ }
+ }
+}
+
+/*
+ * Check the path of a CRL issuer certificate. This creates a new
* X509_STORE_CTX and populates it with most of the parameters from the
- * parent. This could be optimised somewhat since a lot of path checking
- * will be duplicated by the parent, but this will rarely be used in
- * practice.
+ * parent. This could be optimised somewhat since a lot of path checking will
+ * be duplicated by the parent, but this will rarely be used in practice.
*/
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
- {
- X509_STORE_CTX crl_ctx;
- int ret;
- /* Don't allow recursive CRL path validation */
- if (ctx->parent)
- return 0;
- if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
- return -1;
-
- crl_ctx.crls = ctx->crls;
- /* Copy verify params across */
- X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
-
- crl_ctx.parent = ctx;
- crl_ctx.verify_cb = ctx->verify_cb;
-
- /* Verify CRL issuer */
- ret = X509_verify_cert(&crl_ctx);
-
- if (ret <= 0)
- goto err;
-
- /* Check chain is acceptable */
-
- ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
- err:
- X509_STORE_CTX_cleanup(&crl_ctx);
- return ret;
- }
-
-/* RFC3280 says nothing about the relationship between CRL path
- * and certificate path, which could lead to situations where a
- * certificate could be revoked or validated by a CA not authorised
- * to do so. RFC5280 is more strict and states that the two paths must
- * end in the same trust anchor, though some discussions remain...
- * until this is resolved we use the RFC5280 version
+{
+ X509_STORE_CTX crl_ctx;
+ int ret;
+ /* Don't allow recursive CRL path validation */
+ if (ctx->parent)
+ return 0;
+ if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
+ return -1;
+
+ crl_ctx.crls = ctx->crls;
+ /* Copy verify params across */
+ X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
+
+ crl_ctx.parent = ctx;
+ crl_ctx.verify_cb = ctx->verify_cb;
+
+ /* Verify CRL issuer */
+ ret = X509_verify_cert(&crl_ctx);
+
+ if (ret <= 0)
+ goto err;
+
+ /* Check chain is acceptable */
+
+ ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
+ err:
+ X509_STORE_CTX_cleanup(&crl_ctx);
+ return ret;
+}
+
+/*
+ * RFC3280 says nothing about the relationship between CRL path and
+ * certificate path, which could lead to situations where a certificate could
+ * be revoked or validated by a CA not authorised to do so. RFC5280 is more
+ * strict and states that the two paths must end in the same trust anchor,
+ * though some discussions remain... until this is resolved we use the
+ * RFC5280 version
*/
static int check_crl_chain(X509_STORE_CTX *ctx,
- STACK_OF(X509) *cert_path,
- STACK_OF(X509) *crl_path)
- {
- X509 *cert_ta, *crl_ta;
- cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
- crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
- if (!X509_cmp(cert_ta, crl_ta))
- return 1;
- return 0;
- }
-
-/* Check for match between two dist point names: three separate cases.
- * 1. Both are relative names and compare X509_NAME types.
- * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
- * 3. Both are full names and compare two GENERAL_NAMES.
- * 4. One is NULL: automatic match.
- */
+ STACK_OF(X509) *cert_path,
+ STACK_OF(X509) *crl_path)
+{
+ X509 *cert_ta, *crl_ta;
+ cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
+ crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
+ if (!X509_cmp(cert_ta, crl_ta))
+ return 1;
+ return 0;
+}
+/*
+ * Check for match between two dist point names: three separate cases. 1.
+ * Both are relative names and compare X509_NAME types. 2. One full, one
+ * relative. Compare X509_NAME to GENERAL_NAMES. 3. Both are full names and
+ * compare two GENERAL_NAMES. 4. One is NULL: automatic match.
+ */
static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
- {
- X509_NAME *nm = NULL;
- GENERAL_NAMES *gens = NULL;
- GENERAL_NAME *gena, *genb;
- size_t i, j;
- if (!a || !b)
- return 1;
- if (a->type == 1)
- {
- if (!a->dpname)
- return 0;
- /* Case 1: two X509_NAME */
- if (b->type == 1)
- {
- if (!b->dpname)
- return 0;
- if (!X509_NAME_cmp(a->dpname, b->dpname))
- return 1;
- else
- return 0;
- }
- /* Case 2: set name and GENERAL_NAMES appropriately */
- nm = a->dpname;
- gens = b->name.fullname;
- }
- else if (b->type == 1)
- {
- if (!b->dpname)
- return 0;
- /* Case 2: set name and GENERAL_NAMES appropriately */
- gens = a->name.fullname;
- nm = b->dpname;
- }
-
- /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
- if (nm)
- {
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
- {
- gena = sk_GENERAL_NAME_value(gens, i);
- if (gena->type != GEN_DIRNAME)
- continue;
- if (!X509_NAME_cmp(nm, gena->d.directoryName))
- return 1;
- }
- return 0;
- }
-
- /* Else case 3: two GENERAL_NAMES */
-
- for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++)
- {
- gena = sk_GENERAL_NAME_value(a->name.fullname, i);
- for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++)
- {
- genb = sk_GENERAL_NAME_value(b->name.fullname, j);
- if (!GENERAL_NAME_cmp(gena, genb))
- return 1;
- }
- }
-
- return 0;
-
- }
+{
+ X509_NAME *nm = NULL;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gena, *genb;
+ size_t i, j;
+ if (!a || !b)
+ return 1;
+ if (a->type == 1) {
+ if (!a->dpname)
+ return 0;
+ /* Case 1: two X509_NAME */
+ if (b->type == 1) {
+ if (!b->dpname)
+ return 0;
+ if (!X509_NAME_cmp(a->dpname, b->dpname))
+ return 1;
+ else
+ return 0;
+ }
+ /* Case 2: set name and GENERAL_NAMES appropriately */
+ nm = a->dpname;
+ gens = b->name.fullname;
+ } else if (b->type == 1) {
+ if (!b->dpname)
+ return 0;
+ /* Case 2: set name and GENERAL_NAMES appropriately */
+ gens = a->name.fullname;
+ nm = b->dpname;
+ }
+
+ /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
+ if (nm) {
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gena = sk_GENERAL_NAME_value(gens, i);
+ if (gena->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(nm, gena->d.directoryName))
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Else case 3: two GENERAL_NAMES */
+
+ for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) {
+ gena = sk_GENERAL_NAME_value(a->name.fullname, i);
+ for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
+ genb = sk_GENERAL_NAME_value(b->name.fullname, j);
+ if (!GENERAL_NAME_cmp(gena, genb))
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
- {
- size_t i;
- X509_NAME *nm = X509_CRL_get_issuer(crl);
- /* If no CRLissuer return is successful iff don't need a match */
- if (!dp->CRLissuer)
- return !!(crl_score & CRL_SCORE_ISSUER_NAME);
- for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
- {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
- if (gen->type != GEN_DIRNAME)
- continue;
- if (!X509_NAME_cmp(gen->d.directoryName, nm))
- return 1;
- }
- return 0;
- }
+{
+ size_t i;
+ X509_NAME *nm = X509_CRL_get_issuer(crl);
+ /* If no CRLissuer return is successful iff don't need a match */
+ if (!dp->CRLissuer)
+ return ! !(crl_score & CRL_SCORE_ISSUER_NAME);
+ for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+ if (gen->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(gen->d.directoryName, nm))
+ return 1;
+ }
+ return 0;
+}
/* Check CRLDP and IDP */
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
- unsigned int *preasons)
- {
- size_t i;
- if (crl->idp_flags & IDP_ONLYATTR)
- return 0;
- if (x->ex_flags & EXFLAG_CA)
- {
- if (crl->idp_flags & IDP_ONLYUSER)
- return 0;
- }
- else
- {
- if (crl->idp_flags & IDP_ONLYCA)
- return 0;
- }
- *preasons = crl->idp_reasons;
- for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
- {
- DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
- if (crldp_check_crlissuer(dp, crl, crl_score))
- {
- if (!crl->idp ||
- idp_check_dp(dp->distpoint, crl->idp->distpoint))
- {
- *preasons &= dp->dp_reasons;
- return 1;
- }
- }
- }
- if ((!crl->idp || !crl->idp->distpoint) && (crl_score & CRL_SCORE_ISSUER_NAME))
- return 1;
- return 0;
- }
-
-/* Retrieve CRL corresponding to current certificate.
- * If deltas enabled try to find a delta CRL too
+ unsigned int *preasons)
+{
+ size_t i;
+ if (crl->idp_flags & IDP_ONLYATTR)
+ return 0;
+ if (x->ex_flags & EXFLAG_CA) {
+ if (crl->idp_flags & IDP_ONLYUSER)
+ return 0;
+ } else {
+ if (crl->idp_flags & IDP_ONLYCA)
+ return 0;
+ }
+ *preasons = crl->idp_reasons;
+ for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
+ DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
+ if (crldp_check_crlissuer(dp, crl, crl_score)) {
+ if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
+ *preasons &= dp->dp_reasons;
+ return 1;
+ }
+ }
+ }
+ if ((!crl->idp || !crl->idp->distpoint)
+ && (crl_score & CRL_SCORE_ISSUER_NAME))
+ return 1;
+ return 0;
+}
+
+/*
+ * Retrieve CRL corresponding to current certificate. If deltas enabled try
+ * to find a delta CRL too
*/
-
+
static int get_crl_delta(X509_STORE_CTX *ctx,
- X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
- {
- int ok;
- X509 *issuer = NULL;
- int crl_score = 0;
- unsigned int reasons;
- X509_CRL *crl = NULL, *dcrl = NULL;
- STACK_OF(X509_CRL) *skcrl;
- X509_NAME *nm = X509_get_issuer_name(x);
- reasons = ctx->current_reasons;
- ok = get_crl_sk(ctx, &crl, &dcrl,
- &issuer, &crl_score, &reasons, ctx->crls);
-
- if (ok)
- goto done;
-
- /* Lookup CRLs from store */
-
- skcrl = ctx->lookup_crls(ctx, nm);
-
- /* If no CRLs found and a near match from get_crl_sk use that */
- if (!skcrl && crl)
- goto done;
-
- get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
-
- sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
-
- done:
-
- /* If we got any kind of CRL use it and return success */
- if (crl)
- {
- ctx->current_issuer = issuer;
- ctx->current_crl_score = crl_score;
- ctx->current_reasons = reasons;
- *pcrl = crl;
- *pdcrl = dcrl;
- return 1;
- }
-
- return 0;
- }
+ X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
+{
+ int ok;
+ X509 *issuer = NULL;
+ int crl_score = 0;
+ unsigned int reasons;
+ X509_CRL *crl = NULL, *dcrl = NULL;
+ STACK_OF(X509_CRL) *skcrl;
+ X509_NAME *nm = X509_get_issuer_name(x);
+ reasons = ctx->current_reasons;
+ ok = get_crl_sk(ctx, &crl, &dcrl,
+ &issuer, &crl_score, &reasons, ctx->crls);
+
+ if (ok)
+ goto done;
+
+ /* Lookup CRLs from store */
+
+ skcrl = ctx->lookup_crls(ctx, nm);
+
+ /* If no CRLs found and a near match from get_crl_sk use that */
+ if (!skcrl && crl)
+ goto done;
+
+ get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
+
+ sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
+
+ done:
+
+ /* If we got any kind of CRL use it and return success */
+ if (crl) {
+ ctx->current_issuer = issuer;
+ ctx->current_crl_score = crl_score;
+ ctx->current_reasons = reasons;
+ *pcrl = crl;
+ *pdcrl = dcrl;
+ return 1;
+ }
+
+ return 0;
+}
/* Check CRL validity */
static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
- {
- X509 *issuer = NULL;
- EVP_PKEY *ikey = NULL;
- int ok = 0, chnum, cnum;
- cnum = ctx->error_depth;
- chnum = sk_X509_num(ctx->chain) - 1;
- /* if we have an alternative CRL issuer cert use that */
- if (ctx->current_issuer)
- issuer = ctx->current_issuer;
-
- /* Else find CRL issuer: if not last certificate then issuer
- * is next certificate in chain.
- */
- else if (cnum < chnum)
- issuer = sk_X509_value(ctx->chain, cnum + 1);
- else
- {
- issuer = sk_X509_value(ctx->chain, chnum);
- /* If not self signed, can't check signature */
- if(!ctx->check_issued(ctx, issuer, issuer))
- {
- ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
- ok = ctx->verify_cb(0, ctx);
- if(!ok) goto err;
- }
- }
-
- if(issuer)
- {
- /* Skip most tests for deltas because they have already
- * been done
- */
- if (!crl->base_crl_number)
- {
- /* Check for cRLSign bit if keyUsage present */
- if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
- !(issuer->ex_kusage & KU_CRL_SIGN))
- {
- ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
- ok = ctx->verify_cb(0, ctx);
- if(!ok) goto err;
- }
-
- if (!(ctx->current_crl_score & CRL_SCORE_SCOPE))
- {
- ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
- ok = ctx->verify_cb(0, ctx);
- if(!ok) goto err;
- }
-
- if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
- {
- if (check_crl_path(ctx, ctx->current_issuer) <= 0)
- {
- ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
- ok = ctx->verify_cb(0, ctx);
- if(!ok) goto err;
- }
- }
-
- if (crl->idp_flags & IDP_INVALID)
- {
- ctx->error = X509_V_ERR_INVALID_EXTENSION;
- ok = ctx->verify_cb(0, ctx);
- if(!ok) goto err;
- }
-
-
- }
-
- if (!(ctx->current_crl_score & CRL_SCORE_TIME))
- {
- ok = check_crl_time(ctx, crl, 1);
- if (!ok)
- goto err;
- }
-
- /* Attempt to get issuer certificate public key */
- ikey = X509_get_pubkey(issuer);
-
- if(!ikey)
- {
- ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
- ok = ctx->verify_cb(0, ctx);
- if (!ok) goto err;
- }
- else
- {
- int rv;
- rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
- if (rv != X509_V_OK)
- {
- ctx->error=rv;
- ok = ctx->verify_cb(0, ctx);
- if (!ok)
- goto err;
- }
- /* Verify CRL signature */
- if(X509_CRL_verify(crl, ikey) <= 0)
- {
- ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
- ok = ctx->verify_cb(0, ctx);
- if (!ok) goto err;
- }
- }
- }
-
- ok = 1;
-
- err:
- EVP_PKEY_free(ikey);
- return ok;
- }
+{
+ X509 *issuer = NULL;
+ EVP_PKEY *ikey = NULL;
+ int ok = 0, chnum, cnum;
+ cnum = ctx->error_depth;
+ chnum = sk_X509_num(ctx->chain) - 1;
+ /* if we have an alternative CRL issuer cert use that */
+ if (ctx->current_issuer)
+ issuer = ctx->current_issuer;
+
+ /*
+ * Else find CRL issuer: if not last certificate then issuer is next
+ * certificate in chain.
+ */
+ else if (cnum < chnum)
+ issuer = sk_X509_value(ctx->chain, cnum + 1);
+ else {
+ issuer = sk_X509_value(ctx->chain, chnum);
+ /* If not self signed, can't check signature */
+ if (!ctx->check_issued(ctx, issuer, issuer)) {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ }
+
+ if (issuer) {
+ /*
+ * Skip most tests for deltas because they have already been done
+ */
+ if (!crl->base_crl_number) {
+ /* Check for cRLSign bit if keyUsage present */
+ if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
+ !(issuer->ex_kusage & KU_CRL_SIGN)) {
+ ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) {
+ ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) {
+ if (check_crl_path(ctx, ctx->current_issuer) <= 0) {
+ ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ }
+
+ if (crl->idp_flags & IDP_INVALID) {
+ ctx->error = X509_V_ERR_INVALID_EXTENSION;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_TIME)) {
+ ok = check_crl_time(ctx, crl, 1);
+ if (!ok)
+ goto err;
+ }
+
+ /* Attempt to get issuer certificate public key */
+ ikey = X509_get_pubkey(issuer);
+
+ if (!ikey) {
+ ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ } else {
+ int rv;
+ rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
+ if (rv != X509_V_OK) {
+ ctx->error = rv;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ /* Verify CRL signature */
+ if (X509_CRL_verify(crl, ikey) <= 0) {
+ ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ }
+ }
+
+ ok = 1;
+
+ err:
+ EVP_PKEY_free(ikey);
+ return ok;
+}
/* Check certificate against CRL */
static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
- {
- int ok;
- X509_REVOKED *rev;
- /* The rules changed for this... previously if a CRL contained
- * unhandled critical extensions it could still be used to indicate
- * a certificate was revoked. This has since been changed since
- * critical extension can change the meaning of CRL entries.
- */
- if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
- && (crl->flags & EXFLAG_CRITICAL))
- {
- ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
- ok = ctx->verify_cb(0, ctx);
- if(!ok)
- return 0;
- }
- /* Look for serial number of certificate in CRL
- * If found make sure reason is not removeFromCRL.
- */
- if (X509_CRL_get0_by_cert(crl, &rev, x))
- {
- if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
- return 2;
- ctx->error = X509_V_ERR_CERT_REVOKED;
- ok = ctx->verify_cb(0, ctx);
- if (!ok)
- return 0;
- }
-
- return 1;
- }
+{
+ int ok;
+ X509_REVOKED *rev;
+ /*
+ * The rules changed for this... previously if a CRL contained unhandled
+ * critical extensions it could still be used to indicate a certificate
+ * was revoked. This has since been changed since critical extension can
+ * change the meaning of CRL entries.
+ */
+ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+ && (crl->flags & EXFLAG_CRITICAL)) {
+ ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ return 0;
+ }
+ /*
+ * Look for serial number of certificate in CRL If found make sure reason
+ * is not removeFromCRL.
+ */
+ if (X509_CRL_get0_by_cert(crl, &rev, x)) {
+ if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+ return 2;
+ ctx->error = X509_V_ERR_CERT_REVOKED;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ return 0;
+ }
+
+ return 1;
+}
static int check_policy(X509_STORE_CTX *ctx)
- {
- int ret;
- if (ctx->parent)
- return 1;
- ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
- ctx->param->policies, ctx->param->flags);
- if (ret == 0)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- /* Invalid or inconsistent extensions */
- if (ret == -1)
- {
- /* Locate certificates with bad extensions and notify
- * callback.
- */
- X509 *x;
- size_t i;
- for (i = 1; i < sk_X509_num(ctx->chain); i++)
- {
- x = sk_X509_value(ctx->chain, i);
- if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
- continue;
- ctx->current_cert = x;
- ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
- if(!ctx->verify_cb(0, ctx))
- return 0;
- }
- return 1;
- }
- if (ret == -2)
- {
- ctx->current_cert = NULL;
- ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
- return ctx->verify_cb(0, ctx);
- }
-
- if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
- {
- ctx->current_cert = NULL;
- ctx->error = X509_V_OK;
- if (!ctx->verify_cb(2, ctx))
- return 0;
- }
-
- return 1;
- }
+{
+ int ret;
+ if (ctx->parent)
+ return 1;
+ ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
+ ctx->param->policies, ctx->param->flags);
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /* Invalid or inconsistent extensions */
+ if (ret == -1) {
+ /*
+ * Locate certificates with bad extensions and notify callback.
+ */
+ X509 *x;
+ size_t i;
+ for (i = 1; i < sk_X509_num(ctx->chain); i++) {
+ x = sk_X509_value(ctx->chain, i);
+ if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
+ continue;
+ ctx->current_cert = x;
+ ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ return 1;
+ }
+ if (ret == -2) {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
+ return ctx->verify_cb(0, ctx);
+ }
+
+ if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_OK;
+ if (!ctx->verify_cb(2, ctx))
+ return 0;
+ }
+
+ return 1;
+}
static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
- {
- time_t *ptime;
- int i;
-
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
- ptime = &ctx->param->check_time;
- else
- ptime = NULL;
-
- i=X509_cmp_time(X509_get_notBefore(x), ptime);
- if (i == 0)
- {
- ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
- ctx->current_cert=x;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- if (i > 0)
- {
- ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
- ctx->current_cert=x;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- i=X509_cmp_time(X509_get_notAfter(x), ptime);
- if (i == 0)
- {
- ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
- ctx->current_cert=x;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- if (i < 0)
- {
- ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
- ctx->current_cert=x;
- if (!ctx->verify_cb(0, ctx))
- return 0;
- }
-
- return 1;
- }
+{
+ time_t *ptime;
+ int i;
+
+ if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ ptime = &ctx->param->check_time;
+ else
+ ptime = NULL;
+
+ i = X509_cmp_time(X509_get_notBefore(x), ptime);
+ if (i == 0) {
+ ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i > 0) {
+ ctx->error = X509_V_ERR_CERT_NOT_YET_VALID;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ i = X509_cmp_time(X509_get_notAfter(x), ptime);
+ if (i == 0) {
+ ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i < 0) {
+ ctx->error = X509_V_ERR_CERT_HAS_EXPIRED;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ return 1;
+}
static int internal_verify(X509_STORE_CTX *ctx)
- {
- int ok=0,n;
- X509 *xs,*xi;
- EVP_PKEY *pkey=NULL;
- int (*cb)(int xok,X509_STORE_CTX *xctx);
-
- cb=ctx->verify_cb;
-
- n=sk_X509_num(ctx->chain);
- ctx->error_depth=n-1;
- n--;
- xi=sk_X509_value(ctx->chain,n);
-
- if (ctx->check_issued(ctx, xi, xi))
- xs=xi;
- else
- {
- if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
- {
- xs = xi;
- goto check_cert;
- }
- if (n <= 0)
- {
- ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
- ctx->current_cert=xi;
- ok=cb(0,ctx);
- goto end;
- }
- else
- {
- n--;
- ctx->error_depth=n;
- xs=sk_X509_value(ctx->chain,n);
- }
- }
-
-/* ctx->error=0; not needed */
- while (n >= 0)
- {
- ctx->error_depth=n;
-
- /* Skip signature check for self signed certificates unless
- * explicitly asked for. It doesn't add any security and
- * just wastes time.
- */
- if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
- {
- if ((pkey=X509_get_pubkey(xi)) == NULL)
- {
- ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
- ctx->current_cert=xi;
- ok=(*cb)(0,ctx);
- if (!ok) goto end;
- }
- else if (X509_verify(xs,pkey) <= 0)
- {
- ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
- ctx->current_cert=xs;
- ok=(*cb)(0,ctx);
- if (!ok)
- {
- EVP_PKEY_free(pkey);
- goto end;
- }
- }
- EVP_PKEY_free(pkey);
- pkey=NULL;
- }
-
- xs->valid = 1;
-
- check_cert:
- ok = check_cert_time(ctx, xs);
- if (!ok)
- goto end;
-
- /* The last error (if any) is still in the error value */
- ctx->current_issuer=xi;
- ctx->current_cert=xs;
- ok=(*cb)(1,ctx);
- if (!ok) goto end;
-
- n--;
- if (n >= 0)
- {
- xi=xs;
- xs=sk_X509_value(ctx->chain,n);
- }
- }
- ok=1;
-end:
- return ok;
- }
+{
+ int ok = 0, n;
+ X509 *xs, *xi;
+ EVP_PKEY *pkey = NULL;
+ int (*cb) (int xok, X509_STORE_CTX *xctx);
+
+ cb = ctx->verify_cb;
+
+ n = sk_X509_num(ctx->chain);
+ ctx->error_depth = n - 1;
+ n--;
+ xi = sk_X509_value(ctx->chain, n);
+
+ if (ctx->check_issued(ctx, xi, xi))
+ xs = xi;
+ else {
+ if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+ xs = xi;
+ goto check_cert;
+ }
+ if (n <= 0) {
+ ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+ ctx->current_cert = xi;
+ ok = cb(0, ctx);
+ goto end;
+ } else {
+ n--;
+ ctx->error_depth = n;
+ xs = sk_X509_value(ctx->chain, n);
+ }
+ }
+
+/* ctx->error=0; not needed */
+ while (n >= 0) {
+ ctx->error_depth = n;
+
+ /*
+ * Skip signature check for self signed certificates unless
+ * explicitly asked for. It doesn't add any security and just wastes
+ * time.
+ */
+ if (!xs->valid
+ && (xs != xi
+ || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) {
+ if ((pkey = X509_get_pubkey(xi)) == NULL) {
+ ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+ ctx->current_cert = xi;
+ ok = (*cb) (0, ctx);
+ if (!ok)
+ goto end;
+ } else if (X509_verify(xs, pkey) <= 0) {
+ ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
+ ctx->current_cert = xs;
+ ok = (*cb) (0, ctx);
+ if (!ok) {
+ EVP_PKEY_free(pkey);
+ goto end;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+
+ xs->valid = 1;
+
+ check_cert:
+ ok = check_cert_time(ctx, xs);
+ if (!ok)
+ goto end;
+
+ /* The last error (if any) is still in the error value */
+ ctx->current_issuer = xi;
+ ctx->current_cert = xs;
+ ok = (*cb) (1, ctx);
+ if (!ok)
+ goto end;
+
+ n--;
+ if (n >= 0) {
+ xi = xs;
+ xs = sk_X509_value(ctx->chain, n);
+ }
+ }
+ ok = 1;
+ end:
+ return ok;
+}
int X509_cmp_current_time(const ASN1_TIME *ctm)
{
- return X509_cmp_time(ctm, NULL);
+ return X509_cmp_time(ctm, NULL);
}
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
- {
- char *str;
- ASN1_TIME atm;
- long offset;
- char buff1[24],buff2[24],*p;
- int i, j, remaining;
-
- p=buff1;
- remaining = ctm->length;
- str=(char *)ctm->data;
- /* Note that the following (historical) code allows much more slack in
- * the time format than RFC5280. In RFC5280, the representation is
- * fixed:
- * UTCTime: YYMMDDHHMMSSZ
- * GeneralizedTime: YYYYMMDDHHMMSSZ */
- if (ctm->type == V_ASN1_UTCTIME)
- {
- /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
- int min_length = sizeof("YYMMDDHHMMZ") - 1;
- int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
- if (remaining < min_length || remaining > max_length)
- return 0;
- memcpy(p,str,10);
- p+=10;
- str+=10;
- remaining -= 10;
- }
- else
- {
- /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
- int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
- int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
- if (remaining < min_length || remaining > max_length)
- return 0;
- memcpy(p,str,12);
- p+=12;
- str+=12;
- remaining -= 12;
- }
-
- if ((*str == 'Z') || (*str == '-') || (*str == '+'))
- { *(p++)='0'; *(p++)='0'; }
- else
- {
- /* SS (seconds) */
- if (remaining < 2)
- return 0;
- *(p++)= *(str++);
- *(p++)= *(str++);
- remaining -= 2;
- /* Skip any (up to three) fractional seconds...
- * TODO(emilia): in RFC5280, fractional seconds are forbidden.
- * Can we just kill them altogether? */
- if (remaining && *str == '.')
- {
- str++;
- remaining--;
- for (i = 0; i < 3 && remaining; i++, str++, remaining--)
- {
- if (*str < '0' || *str > '9')
- break;
- }
- }
-
- }
- *(p++)='Z';
- *(p++)='\0';
-
- /* We now need either a terminating 'Z' or an offset. */
- if (!remaining)
- return 0;
- if (*str == 'Z')
- {
- if (remaining != 1)
- return 0;
- offset=0;
- }
- else
- {
- /* (+-)HHMM */
- if ((*str != '+') && (*str != '-'))
- return 0;
- /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
- if (remaining != 5)
- return 0;
- if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
- str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
- return 0;
- offset=((str[1]-'0')*10+(str[2]-'0'))*60;
- offset+=(str[3]-'0')*10+(str[4]-'0');
- if (*str == '-')
- offset= -offset;
- }
- atm.type=ctm->type;
- atm.flags = 0;
- atm.length=sizeof(buff2);
- atm.data=(unsigned char *)buff2;
-
- if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
- return 0;
-
- if (ctm->type == V_ASN1_UTCTIME)
- {
- i=(buff1[0]-'0')*10+(buff1[1]-'0');
- if (i < 50) i+=100; /* cf. RFC 2459 */
- j=(buff2[0]-'0')*10+(buff2[1]-'0');
- if (j < 50) j+=100;
-
- if (i < j) return -1;
- if (i > j) return 1;
- }
- i=strcmp(buff1,buff2);
- if (i == 0) /* wait a second then return younger :-) */
- return -1;
- else
- return i;
- }
+{
+ char *str;
+ ASN1_TIME atm;
+ long offset;
+ char buff1[24], buff2[24], *p;
+ int i, j, remaining;
+
+ p = buff1;
+ remaining = ctm->length;
+ str = (char *)ctm->data;
+ /*
+ * Note that the following (historical) code allows much more slack in
+ * the time format than RFC5280. In RFC5280, the representation is fixed:
+ * UTCTime: YYMMDDHHMMSSZ GeneralizedTime: YYYYMMDDHHMMSSZ
+ */
+ if (ctm->type == V_ASN1_UTCTIME) {
+ /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+ int min_length = sizeof("YYMMDDHHMMZ") - 1;
+ int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+ if (remaining < min_length || remaining > max_length)
+ return 0;
+ memcpy(p, str, 10);
+ p += 10;
+ str += 10;
+ remaining -= 10;
+ } else {
+ /*
+ * YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm
+ */
+ int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+ int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+ if (remaining < min_length || remaining > max_length)
+ return 0;
+ memcpy(p, str, 12);
+ p += 12;
+ str += 12;
+ remaining -= 12;
+ }
+
+ if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+ *(p++) = '0';
+ *(p++) = '0';
+ } else {
+ /* SS (seconds) */
+ if (remaining < 2)
+ return 0;
+ *(p++) = *(str++);
+ *(p++) = *(str++);
+ remaining -= 2;
+ /*
+ * Skip any (up to three) fractional seconds... TODO(emilia): in
+ * RFC5280, fractional seconds are forbidden. Can we just kill them
+ * altogether?
+ */
+ if (remaining && *str == '.') {
+ str++;
+ remaining--;
+ for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+ if (*str < '0' || *str > '9')
+ break;
+ }
+ }
+
+ }
+ *(p++) = 'Z';
+ *(p++) = '\0';
+
+ /* We now need either a terminating 'Z' or an offset. */
+ if (!remaining)
+ return 0;
+ if (*str == 'Z') {
+ if (remaining != 1)
+ return 0;
+ offset = 0;
+ } else {
+ /* (+-)HHMM */
+ if ((*str != '+') && (*str != '-'))
+ return 0;
+ /*
+ * Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280.
+ */
+ if (remaining != 5)
+ return 0;
+ if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+ str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+ return 0;
+ offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+ offset += (str[3] - '0') * 10 + (str[4] - '0');
+ if (*str == '-')
+ offset = -offset;
+ }
+ atm.type = ctm->type;
+ atm.flags = 0;
+ atm.length = sizeof(buff2);
+ atm.data = (unsigned char *)buff2;
+
+ if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
+ return 0;
+
+ if (ctm->type == V_ASN1_UTCTIME) {
+ i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+ if (i < 50)
+ i += 100; /* cf. RFC 2459 */
+ j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+ if (j < 50)
+ j += 100;
+
+ if (i < j)
+ return -1;
+ if (i > j)
+ return 1;
+ }
+ i = strcmp(buff1, buff2);
+ if (i == 0) /* wait a second then return younger :-) */
+ return -1;
+ else
+ return i;
+}
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
- return X509_time_adj(s, adj, NULL);
+ return X509_time_adj(s, adj, NULL);
}
ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
- {
- return X509_time_adj_ex(s, 0, offset_sec, in_tm);
- }
+{
+ return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+}
ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
- int offset_day, long offset_sec, time_t *in_tm)
- {
- time_t t = 0;
-
- if (in_tm) t = *in_tm;
- else time(&t);
-
- if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
- {
- if (s->type == V_ASN1_UTCTIME)
- return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
- if (s->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
- offset_sec);
- }
- return ASN1_TIME_adj(s, t, offset_day, offset_sec);
- }
+ int offset_day, long offset_sec, time_t *in_tm)
+{
+ time_t t = 0;
+
+ if (in_tm)
+ t = *in_tm;
+ else
+ time(&t);
+
+ if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) {
+ if (s->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
+ if (s->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
+ }
+ return ASN1_TIME_adj(s, t, offset_day, offset_sec);
+}
/* Make a delta CRL as the diff between two full CRLs */
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
- EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
- {
- X509_CRL *crl = NULL;
- int i;
- size_t j;
- STACK_OF(X509_REVOKED) *revs = NULL;
- /* CRLs can't be delta already */
- if (base->base_crl_number || newer->base_crl_number)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA);
- return NULL;
- }
- /* Base and new CRL must have a CRL number */
- if (!base->crl_number || !newer->crl_number)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER);
- return NULL;
- }
- /* Issuer names must match */
- if (X509_NAME_cmp(X509_CRL_get_issuer(base),
- X509_CRL_get_issuer(newer)))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH);
- return NULL;
- }
- /* AKID and IDP must match */
- if (!crl_extension_match(base, newer, NID_authority_key_identifier))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH);
- return NULL;
- }
- if (!crl_extension_match(base, newer, NID_issuing_distribution_point))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH);
- return NULL;
- }
- /* Newer CRL number must exceed full CRL number */
- if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER);
- return NULL;
- }
- /* CRLs must verify */
- if (skey && (X509_CRL_verify(base, skey) <= 0 ||
- X509_CRL_verify(newer, skey) <= 0))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE);
- return NULL;
- }
- /* Create new CRL */
- crl = X509_CRL_new();
- if (!crl || !X509_CRL_set_version(crl, 1))
- goto memerr;
- /* Set issuer name */
- if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
- goto memerr;
-
- if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
- goto memerr;
- if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
- goto memerr;
-
- /* Set base CRL number: must be critical */
-
- if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
- goto memerr;
-
- /* Copy extensions across from newest CRL to delta: this will set
- * CRL number to correct value too.
- */
-
- for (i = 0; i < X509_CRL_get_ext_count(newer); i++)
- {
- X509_EXTENSION *ext;
- ext = X509_CRL_get_ext(newer, i);
- if (!X509_CRL_add_ext(crl, ext, -1))
- goto memerr;
- }
-
- /* Go through revoked entries, copying as needed */
-
- revs = X509_CRL_get_REVOKED(newer);
-
- for (j = 0; j < sk_X509_REVOKED_num(revs); j++)
- {
- X509_REVOKED *rvn, *rvtmp;
- rvn = sk_X509_REVOKED_value(revs, j);
- /* Add only if not also in base.
- * TODO: need something cleverer here for some more complex
- * CRLs covering multiple CAs.
- */
- if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber))
- {
- rvtmp = X509_REVOKED_dup(rvn);
- if (!rvtmp)
- goto memerr;
- if (!X509_CRL_add0_revoked(crl, rvtmp))
- {
- X509_REVOKED_free(rvtmp);
- goto memerr;
- }
- }
- }
- /* TODO: optionally prune deleted entries */
-
- if (skey && md && !X509_CRL_sign(crl, skey, md))
- goto memerr;
-
- return crl;
-
- memerr:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- if (crl)
- X509_CRL_free(crl);
- return NULL;
- }
-
-int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
- CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
- {
- /* This function is (usually) called only once, by
- * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
- int index;
- if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
- dup_func, free_func))
- {
- return -1;
- }
- return index;
- }
+ EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
+{
+ X509_CRL *crl = NULL;
+ int i;
+ size_t j;
+ STACK_OF(X509_REVOKED) *revs = NULL;
+ /* CRLs can't be delta already */
+ if (base->base_crl_number || newer->base_crl_number) {
+ OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA);
+ return NULL;
+ }
+ /* Base and new CRL must have a CRL number */
+ if (!base->crl_number || !newer->crl_number) {
+ OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER);
+ return NULL;
+ }
+ /* Issuer names must match */
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) {
+ OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH);
+ return NULL;
+ }
+ /* AKID and IDP must match */
+ if (!crl_extension_match(base, newer, NID_authority_key_identifier)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH);
+ return NULL;
+ }
+ if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH);
+ return NULL;
+ }
+ /* Newer CRL number must exceed full CRL number */
+ if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) {
+ OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER);
+ return NULL;
+ }
+ /* CRLs must verify */
+ if (skey && (X509_CRL_verify(base, skey) <= 0 ||
+ X509_CRL_verify(newer, skey) <= 0)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE);
+ return NULL;
+ }
+ /* Create new CRL */
+ crl = X509_CRL_new();
+ if (!crl || !X509_CRL_set_version(crl, 1))
+ goto memerr;
+ /* Set issuer name */
+ if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
+ goto memerr;
+
+ if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
+ goto memerr;
+ if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
+ goto memerr;
+
+ /* Set base CRL number: must be critical */
+
+ if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
+ goto memerr;
+
+ /*
+ * Copy extensions across from newest CRL to delta: this will set CRL
+ * number to correct value too.
+ */
+
+ for (i = 0; i < X509_CRL_get_ext_count(newer); i++) {
+ X509_EXTENSION *ext;
+ ext = X509_CRL_get_ext(newer, i);
+ if (!X509_CRL_add_ext(crl, ext, -1))
+ goto memerr;
+ }
+
+ /* Go through revoked entries, copying as needed */
+
+ revs = X509_CRL_get_REVOKED(newer);
+
+ for (j = 0; j < sk_X509_REVOKED_num(revs); j++) {
+ X509_REVOKED *rvn, *rvtmp;
+ rvn = sk_X509_REVOKED_value(revs, j);
+ /*
+ * Add only if not also in base. TODO: need something cleverer here
+ * for some more complex CRLs covering multiple CAs.
+ */
+ if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) {
+ rvtmp = X509_REVOKED_dup(rvn);
+ if (!rvtmp)
+ goto memerr;
+ if (!X509_CRL_add0_revoked(crl, rvtmp)) {
+ X509_REVOKED_free(rvtmp);
+ goto memerr;
+ }
+ }
+ }
+ /* TODO: optionally prune deleted entries */
+
+ if (skey && md && !X509_CRL_sign(crl, skey, md))
+ goto memerr;
+
+ return crl;
+
+ memerr:
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ if (crl)
+ X509_CRL_free(crl);
+ return NULL;
+}
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp,
+ CRYPTO_EX_unused * unused,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func)
+{
+ /*
+ * This function is (usually) called only once, by
+ * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c).
+ */
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
+}
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
- {
- return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
- }
+{
+ return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+}
void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
- {
- return CRYPTO_get_ex_data(&ctx->ex_data,idx);
- }
+{
+ return CRYPTO_get_ex_data(&ctx->ex_data, idx);
+}
int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
- {
- return ctx->error;
- }
+{
+ return ctx->error;
+}
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
- {
- ctx->error=err;
- }
+{
+ ctx->error = err;
+}
int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
- {
- return ctx->error_depth;
- }
+{
+ return ctx->error_depth;
+}
X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
- {
- return ctx->current_cert;
- }
+{
+ return ctx->current_cert;
+}
STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
- {
- return ctx->chain;
- }
+{
+ return ctx->chain;
+}
STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
- {
- if (!ctx->chain)
- return NULL;
- return X509_chain_up_ref(ctx->chain);
- }
+{
+ if (!ctx->chain)
+ return NULL;
+ return X509_chain_up_ref(ctx->chain);
+}
X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
- {
- return ctx->current_issuer;
- }
+{
+ return ctx->current_issuer;
+}
X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
- {
- return ctx->current_crl;
- }
+{
+ return ctx->current_crl;
+}
X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
- {
- return ctx->parent;
- }
+{
+ return ctx->parent;
+}
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
- {
- ctx->cert=x;
- }
+{
+ ctx->cert = x;
+}
void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
- {
- ctx->untrusted=sk;
- }
+{
+ ctx->untrusted = sk;
+}
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
- {
- ctx->crls=sk;
- }
+{
+ ctx->crls = sk;
+}
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
- {
- return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
- }
+{
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
+}
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
- {
- return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
- }
-
-/* This function is used to set the X509_STORE_CTX purpose and trust
- * values. This is intended to be used when another structure has its
- * own trust and purpose values which (if set) will be inherited by
- * the ctx. If they aren't set then we will usually have a default
- * purpose in mind which should then be used to set the trust value.
- * An example of this is SSL use: an SSL structure will have its own
- * purpose and trust settings which the application can set: if they
- * aren't set then we use the default of SSL client/server.
+{
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
+}
+
+/*
+ * This function is used to set the X509_STORE_CTX purpose and trust values.
+ * This is intended to be used when another structure has its own trust and
+ * purpose values which (if set) will be inherited by the ctx. If they aren't
+ * set then we will usually have a default purpose in mind which should then
+ * be used to set the trust value. An example of this is SSL use: an SSL
+ * structure will have its own purpose and trust settings which the
+ * application can set: if they aren't set then we use the default of SSL
+ * client/server.
*/
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
- int purpose, int trust)
-{
- int idx;
- /* If purpose not set use default */
- if (!purpose) purpose = def_purpose;
- /* If we have a purpose then check it is valid */
- if (purpose)
- {
- X509_PURPOSE *ptmp;
- idx = X509_PURPOSE_get_by_id(purpose);
- if (idx == -1)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
- return 0;
- }
- ptmp = X509_PURPOSE_get0(idx);
- if (ptmp->trust == X509_TRUST_DEFAULT)
- {
- idx = X509_PURPOSE_get_by_id(def_purpose);
- if (idx == -1)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
- return 0;
- }
- ptmp = X509_PURPOSE_get0(idx);
- }
- /* If trust not set then get from purpose default */
- if (!trust) trust = ptmp->trust;
- }
- if (trust)
- {
- idx = X509_TRUST_get_by_id(trust);
- if (idx == -1)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
- return 0;
- }
- }
-
- if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
- if (trust && !ctx->param->trust) ctx->param->trust = trust;
- return 1;
+ int purpose, int trust)
+{
+ int idx;
+ /* If purpose not set use default */
+ if (!purpose)
+ purpose = def_purpose;
+ /* If we have a purpose then check it is valid */
+ if (purpose) {
+ X509_PURPOSE *ptmp;
+ idx = X509_PURPOSE_get_by_id(purpose);
+ if (idx == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
+ return 0;
+ }
+ ptmp = X509_PURPOSE_get0(idx);
+ if (ptmp->trust == X509_TRUST_DEFAULT) {
+ idx = X509_PURPOSE_get_by_id(def_purpose);
+ if (idx == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
+ return 0;
+ }
+ ptmp = X509_PURPOSE_get0(idx);
+ }
+ /* If trust not set then get from purpose default */
+ if (!trust)
+ trust = ptmp->trust;
+ }
+ if (trust) {
+ idx = X509_TRUST_get_by_id(trust);
+ if (idx == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
+ return 0;
+ }
+ }
+
+ if (purpose && !ctx->param->purpose)
+ ctx->param->purpose = purpose;
+ if (trust && !ctx->param->trust)
+ ctx->param->trust = trust;
+ return 1;
}
X509_STORE_CTX *X509_STORE_CTX_new(void)
{
- X509_STORE_CTX *ctx;
- ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
- if (!ctx)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- memset(ctx, 0, sizeof(X509_STORE_CTX));
- return ctx;
+ X509_STORE_CTX *ctx;
+ ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
+ if (!ctx) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ return ctx;
}
void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
{
- X509_STORE_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
+ if (ctx == NULL) {
+ return;
+ }
+ X509_STORE_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
}
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
- STACK_OF(X509) *chain)
- {
- int ret = 1;
-
- memset(ctx, 0, sizeof(X509_STORE_CTX));
- ctx->ctx=store;
- ctx->cert=x509;
- ctx->untrusted=chain;
-
- CRYPTO_new_ex_data(&ctx->ex_data);
-
- ctx->param = X509_VERIFY_PARAM_new();
- if (!ctx->param)
- goto err;
-
- /* Inherit callbacks and flags from X509_STORE if not set
- * use defaults. */
-
- if (store)
- ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
- else
- ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
-
- if (store)
- {
- ctx->verify_cb = store->verify_cb;
- ctx->cleanup = store->cleanup;
- }
- else
- ctx->cleanup = 0;
-
- if (ret)
- ret = X509_VERIFY_PARAM_inherit(ctx->param,
- X509_VERIFY_PARAM_lookup("default"));
-
- if (ret == 0)
- goto err;
-
- if (store && store->check_issued)
- ctx->check_issued = store->check_issued;
- else
- ctx->check_issued = check_issued;
-
- if (store && store->get_issuer)
- ctx->get_issuer = store->get_issuer;
- else
- ctx->get_issuer = X509_STORE_CTX_get1_issuer;
-
- if (store && store->verify_cb)
- ctx->verify_cb = store->verify_cb;
- else
- ctx->verify_cb = null_callback;
-
- if (store && store->verify)
- ctx->verify = store->verify;
- else
- ctx->verify = internal_verify;
-
- if (store && store->check_revocation)
- ctx->check_revocation = store->check_revocation;
- else
- ctx->check_revocation = check_revocation;
-
- if (store && store->get_crl)
- ctx->get_crl = store->get_crl;
- else
- ctx->get_crl = NULL;
-
- if (store && store->check_crl)
- ctx->check_crl = store->check_crl;
- else
- ctx->check_crl = check_crl;
-
- if (store && store->cert_crl)
- ctx->cert_crl = store->cert_crl;
- else
- ctx->cert_crl = cert_crl;
-
- if (store && store->lookup_certs)
- ctx->lookup_certs = store->lookup_certs;
- else
- ctx->lookup_certs = X509_STORE_get1_certs;
-
- if (store && store->lookup_crls)
- ctx->lookup_crls = store->lookup_crls;
- else
- ctx->lookup_crls = X509_STORE_get1_crls;
-
- ctx->check_policy = check_policy;
-
- return 1;
-
-err:
- CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
- if (ctx->param != NULL)
- {
- X509_VERIFY_PARAM_free(ctx->param);
- }
-
- memset(ctx, 0, sizeof(X509_STORE_CTX));
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
-/* Set alternative lookup method: just a STACK of trusted certificates.
- * This avoids X509_STORE nastiness where it isn't needed.
+ STACK_OF(X509) *chain)
+{
+ int ret = 1;
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ ctx->ctx = store;
+ ctx->cert = x509;
+ ctx->untrusted = chain;
+
+ CRYPTO_new_ex_data(&ctx->ex_data);
+
+ ctx->param = X509_VERIFY_PARAM_new();
+ if (!ctx->param)
+ goto err;
+
+ /*
+ * Inherit callbacks and flags from X509_STORE if not set use defaults.
+ */
+
+ if (store)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
+ else
+ ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
+
+ if (store) {
+ ctx->verify_cb = store->verify_cb;
+ ctx->cleanup = store->cleanup;
+ } else
+ ctx->cleanup = 0;
+
+ if (ret)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param,
+ X509_VERIFY_PARAM_lookup("default"));
+
+ if (ret == 0)
+ goto err;
+
+ if (store && store->check_issued)
+ ctx->check_issued = store->check_issued;
+ else
+ ctx->check_issued = check_issued;
+
+ if (store && store->get_issuer)
+ ctx->get_issuer = store->get_issuer;
+ else
+ ctx->get_issuer = X509_STORE_CTX_get1_issuer;
+
+ if (store && store->verify_cb)
+ ctx->verify_cb = store->verify_cb;
+ else
+ ctx->verify_cb = null_callback;
+
+ if (store && store->verify)
+ ctx->verify = store->verify;
+ else
+ ctx->verify = internal_verify;
+
+ if (store && store->check_revocation)
+ ctx->check_revocation = store->check_revocation;
+ else
+ ctx->check_revocation = check_revocation;
+
+ if (store && store->get_crl)
+ ctx->get_crl = store->get_crl;
+ else
+ ctx->get_crl = NULL;
+
+ if (store && store->check_crl)
+ ctx->check_crl = store->check_crl;
+ else
+ ctx->check_crl = check_crl;
+
+ if (store && store->cert_crl)
+ ctx->cert_crl = store->cert_crl;
+ else
+ ctx->cert_crl = cert_crl;
+
+ if (store && store->lookup_certs)
+ ctx->lookup_certs = store->lookup_certs;
+ else
+ ctx->lookup_certs = X509_STORE_get1_certs;
+
+ if (store && store->lookup_crls)
+ ctx->lookup_crls = store->lookup_crls;
+ else
+ ctx->lookup_crls = X509_STORE_get1_crls;
+
+ ctx->check_policy = check_policy;
+
+ return 1;
+
+ err:
+ CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
+ if (ctx->param != NULL) {
+ X509_VERIFY_PARAM_free(ctx->param);
+ }
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+/*
+ * Set alternative lookup method: just a STACK of trusted certificates. This
+ * avoids X509_STORE nastiness where it isn't needed.
*/
void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
- ctx->other_ctx = sk;
- ctx->get_issuer = get_issuer_sk;
+ ctx->other_ctx = sk;
+ ctx->get_issuer = get_issuer_sk;
}
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
- {
- if (ctx->cleanup) ctx->cleanup(ctx);
- if (ctx->param != NULL)
- {
- if (ctx->parent == NULL)
- X509_VERIFY_PARAM_free(ctx->param);
- ctx->param=NULL;
- }
- if (ctx->tree != NULL)
- {
- X509_policy_tree_free(ctx->tree);
- ctx->tree=NULL;
- }
- if (ctx->chain != NULL)
- {
- sk_X509_pop_free(ctx->chain,X509_free);
- ctx->chain=NULL;
- }
- CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
- memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
- }
+{
+ /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free|
+ * also calls this function. */
+ if (ctx->cleanup != NULL) {
+ ctx->cleanup(ctx);
+ ctx->cleanup = NULL;
+ }
+ if (ctx->param != NULL) {
+ if (ctx->parent == NULL)
+ X509_VERIFY_PARAM_free(ctx->param);
+ ctx->param = NULL;
+ }
+ if (ctx->tree != NULL) {
+ X509_policy_tree_free(ctx->tree);
+ ctx->tree = NULL;
+ }
+ if (ctx->chain != NULL) {
+ sk_X509_pop_free(ctx->chain, X509_free);
+ ctx->chain = NULL;
+ }
+ CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
+ memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA));
+}
void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
- {
- X509_VERIFY_PARAM_set_depth(ctx->param, depth);
- }
+{
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
- {
- X509_VERIFY_PARAM_set_flags(ctx->param, flags);
- }
+{
+ X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+}
-void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
- {
- X509_VERIFY_PARAM_set_time(ctx->param, t);
- }
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+ time_t t)
+{
+ X509_VERIFY_PARAM_set_time(ctx->param, t);
+}
void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
- int (*verify_cb)(int, X509_STORE_CTX *))
- {
- ctx->verify_cb=verify_cb;
- }
+ int (*verify_cb) (int, X509_STORE_CTX *))
+{
+ ctx->verify_cb = verify_cb;
+}
X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
- {
- return ctx->tree;
- }
+{
+ return ctx->tree;
+}
int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
- {
- return ctx->explicit_policy;
- }
+{
+ return ctx->explicit_policy;
+}
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
- {
- const X509_VERIFY_PARAM *param;
- param = X509_VERIFY_PARAM_lookup(name);
- if (!param)
- return 0;
- return X509_VERIFY_PARAM_inherit(ctx->param, param);
- }
+{
+ const X509_VERIFY_PARAM *param;
+ param = X509_VERIFY_PARAM_lookup(name);
+ if (!param)
+ return 0;
+ return X509_VERIFY_PARAM_inherit(ctx->param, param);
+}
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
- {
- return ctx->param;
- }
+{
+ return ctx->param;
+}
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
- {
- if (ctx->param)
- X509_VERIFY_PARAM_free(ctx->param);
- ctx->param = param;
- }
+{
+ if (ctx->param)
+ X509_VERIFY_PARAM_free(ctx->param);
+ ctx->param = param;
+}
IMPLEMENT_ASN1_SET_OF(X509)
+
IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
index 8c8f98ea..b51bc176 100644
--- a/src/crypto/x509/x509_vpm.c
+++ b/src/crypto/x509/x509_vpm.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
+ */
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -64,609 +66,571 @@
#include "vpm_int.h"
-
/* X509_VERIFY_PARAM functions */
#define SET_HOST 0
#define ADD_HOST 1
-static char *str_copy(char *s) { return OPENSSL_strdup(s); }
-static void str_free(char *s) { OPENSSL_free(s); }
+static char *str_copy(char *s)
+{
+ return OPENSSL_strdup(s);
+}
+
+static void str_free(char *s)
+{
+ OPENSSL_free(s);
+}
#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
- const char *name, size_t namelen)
- {
- char *copy;
-
- /*
- * Refuse names with embedded NUL bytes.
- * XXX: Do we need to push an error onto the error stack?
- */
- if (name && memchr(name, '\0', namelen))
- return 0;
-
- if (mode == SET_HOST && id->hosts)
- {
- string_stack_free(id->hosts);
- id->hosts = NULL;
- }
- if (name == NULL || namelen == 0)
- return 1;
-
- copy = BUF_strndup(name, namelen);
- if (copy == NULL)
- return 0;
-
- if (id->hosts == NULL &&
- (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL)
- {
- OPENSSL_free(copy);
- return 0;
- }
-
- if (!sk_OPENSSL_STRING_push(id->hosts, copy))
- {
- OPENSSL_free(copy);
- if (sk_OPENSSL_STRING_num(id->hosts) == 0)
- {
- sk_OPENSSL_STRING_free(id->hosts);
- id->hosts = NULL;
- }
- return 0;
- }
-
- return 1;
- }
+ const char *name, size_t namelen)
+{
+ char *copy;
+
+ /*
+ * Refuse names with embedded NUL bytes.
+ * XXX: Do we need to push an error onto the error stack?
+ */
+ if (name && memchr(name, '\0', namelen))
+ return 0;
+
+ if (mode == SET_HOST && id->hosts) {
+ string_stack_free(id->hosts);
+ id->hosts = NULL;
+ }
+ if (name == NULL || namelen == 0)
+ return 1;
+
+ copy = BUF_strndup(name, namelen);
+ if (copy == NULL)
+ return 0;
+
+ if (id->hosts == NULL &&
+ (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
+ OPENSSL_free(copy);
+ return 0;
+ }
+
+ if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
+ OPENSSL_free(copy);
+ if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
+ sk_OPENSSL_STRING_free(id->hosts);
+ id->hosts = NULL;
+ }
+ return 0;
+ }
+
+ return 1;
+}
static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
- {
- X509_VERIFY_PARAM_ID *paramid;
- if (!param)
- return;
- param->name = NULL;
- param->purpose = 0;
- param->trust = 0;
- /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
- param->inh_flags = 0;
- param->flags = 0;
- param->depth = -1;
- if (param->policies)
- {
- sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
- param->policies = NULL;
- }
- paramid = param->id;
- if (paramid->hosts)
- {
- string_stack_free(paramid->hosts);
- paramid->hosts = NULL;
- }
- if (paramid->peername)
- {
- OPENSSL_free(paramid->peername);
- paramid->peername = NULL;
- }
- if (paramid->email)
- {
- OPENSSL_free(paramid->email);
- paramid->email = NULL;
- paramid->emaillen = 0;
- }
- if (paramid->ip)
- {
- OPENSSL_free(paramid->ip);
- paramid->ip = NULL;
- paramid->iplen = 0;
- }
-
- }
+{
+ X509_VERIFY_PARAM_ID *paramid;
+ if (!param)
+ return;
+ param->name = NULL;
+ param->purpose = 0;
+ param->trust = 0;
+ /*
+ * param->inh_flags = X509_VP_FLAG_DEFAULT;
+ */
+ param->inh_flags = 0;
+ param->flags = 0;
+ param->depth = -1;
+ if (param->policies) {
+ sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+ param->policies = NULL;
+ }
+ paramid = param->id;
+ if (paramid->hosts) {
+ string_stack_free(paramid->hosts);
+ paramid->hosts = NULL;
+ }
+ if (paramid->peername) {
+ OPENSSL_free(paramid->peername);
+ paramid->peername = NULL;
+ }
+ if (paramid->email) {
+ OPENSSL_free(paramid->email);
+ paramid->email = NULL;
+ paramid->emaillen = 0;
+ }
+ if (paramid->ip) {
+ OPENSSL_free(paramid->ip);
+ paramid->ip = NULL;
+ paramid->iplen = 0;
+ }
+
+}
X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
- {
- X509_VERIFY_PARAM *param;
- X509_VERIFY_PARAM_ID *paramid;
- param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
- if (!param)
- return NULL;
- paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
- if (!paramid)
- {
- OPENSSL_free(param);
- return NULL;
- }
- memset(param, 0, sizeof(X509_VERIFY_PARAM));
- memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
- param->id = paramid;
- x509_verify_param_zero(param);
- return param;
- }
+{
+ X509_VERIFY_PARAM *param;
+ X509_VERIFY_PARAM_ID *paramid;
+ param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
+ if (!param)
+ return NULL;
+ paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
+ if (!paramid) {
+ OPENSSL_free(param);
+ return NULL;
+ }
+ memset(param, 0, sizeof(X509_VERIFY_PARAM));
+ memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
+ param->id = paramid;
+ x509_verify_param_zero(param);
+ return param;
+}
void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
- {
- if (param == NULL)
- return;
- x509_verify_param_zero(param);
- OPENSSL_free(param->id);
- OPENSSL_free(param);
- }
-
-/* This function determines how parameters are "inherited" from one structure
- * to another. There are several different ways this can happen.
- *
- * 1. If a child structure needs to have its values initialized from a parent
- * they are simply copied across. For example SSL_CTX copied to SSL.
- * 2. If the structure should take on values only if they are currently unset.
- * For example the values in an SSL structure will take appropriate value
- * for SSL servers or clients but only if the application has not set new
- * ones.
- *
- * The "inh_flags" field determines how this function behaves.
- *
- * Normally any values which are set in the default are not copied from the
- * destination and verify flags are ORed together.
- *
- * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
- * to the destination. Effectively the values in "to" become default values
- * which will be used only if nothing new is set in "from".
- *
- * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
- * they are set or not. Flags is still Ored though.
- *
- * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
- * of ORed.
- *
- * If X509_VP_FLAG_LOCKED is set then no values are copied.
- *
- * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
- * after the next call.
+{
+ if (param == NULL)
+ return;
+ x509_verify_param_zero(param);
+ OPENSSL_free(param->id);
+ OPENSSL_free(param);
+}
+
+/*
+ * This function determines how parameters are "inherited" from one structure
+ * to another. There are several different ways this can happen. 1. If a
+ * child structure needs to have its values initialized from a parent they are
+ * simply copied across. For example SSL_CTX copied to SSL. 2. If the
+ * structure should take on values only if they are currently unset. For
+ * example the values in an SSL structure will take appropriate value for SSL
+ * servers or clients but only if the application has not set new ones. The
+ * "inh_flags" field determines how this function behaves. Normally any
+ * values which are set in the default are not copied from the destination and
+ * verify flags are ORed together. If X509_VP_FLAG_DEFAULT is set then
+ * anything set in the source is copied to the destination. Effectively the
+ * values in "to" become default values which will be used only if nothing new
+ * is set in "from". If X509_VP_FLAG_OVERWRITE is set then all value are
+ * copied across whether they are set or not. Flags is still Ored though. If
+ * X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead of
+ * ORed. If X509_VP_FLAG_LOCKED is set then no values are copied. If
+ * X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed after
+ * the next call.
*/
/* Macro to test if a field should be copied from src to dest */
#define test_x509_verify_param_copy(field, def) \
- (to_overwrite || \
- ((src->field != def) && (to_default || (dest->field == def))))
+ (to_overwrite || \
+ ((src->field != def) && (to_default || (dest->field == def))))
/* As above but for ID fields */
#define test_x509_verify_param_copy_id(idf, def) \
- test_x509_verify_param_copy(id->idf, def)
+ test_x509_verify_param_copy(id->idf, def)
/* Macro to test and copy a field if necessary */
#define x509_verify_param_copy(field, def) \
- if (test_x509_verify_param_copy(field, def)) \
- dest->field = src->field
-
+ if (test_x509_verify_param_copy(field, def)) \
+ dest->field = src->field
int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
- const X509_VERIFY_PARAM *src)
- {
- unsigned long inh_flags;
- int to_default, to_overwrite;
- X509_VERIFY_PARAM_ID *id;
- if (!src)
- return 1;
- id = src->id;
- inh_flags = dest->inh_flags | src->inh_flags;
-
- if (inh_flags & X509_VP_FLAG_ONCE)
- dest->inh_flags = 0;
-
- if (inh_flags & X509_VP_FLAG_LOCKED)
- return 1;
-
- if (inh_flags & X509_VP_FLAG_DEFAULT)
- to_default = 1;
- else
- to_default = 0;
-
- if (inh_flags & X509_VP_FLAG_OVERWRITE)
- to_overwrite = 1;
- else
- to_overwrite = 0;
-
- x509_verify_param_copy(purpose, 0);
- x509_verify_param_copy(trust, 0);
- x509_verify_param_copy(depth, -1);
-
- /* If overwrite or check time not set, copy across */
-
- if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME))
- {
- dest->check_time = src->check_time;
- dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
- /* Don't need to copy flag: that is done below */
- }
-
- if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
- dest->flags = 0;
-
- dest->flags |= src->flags;
-
- if (test_x509_verify_param_copy(policies, NULL))
- {
- if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
- return 0;
- }
-
- /* Copy the host flags if and only if we're copying the host list */
- if (test_x509_verify_param_copy_id(hosts, NULL))
- {
- if (dest->id->hosts)
- {
- string_stack_free(dest->id->hosts);
- dest->id->hosts = NULL;
- }
- if (id->hosts)
- {
- dest->id->hosts =
- sk_OPENSSL_STRING_deep_copy(id->hosts,
- str_copy, str_free);
- if (dest->id->hosts == NULL)
- return 0;
- dest->id->hostflags = id->hostflags;
- }
- }
-
- if (test_x509_verify_param_copy_id(email, NULL))
- {
- if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
- return 0;
- }
-
- if (test_x509_verify_param_copy_id(ip, NULL))
- {
- if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
- return 0;
- }
-
- return 1;
- }
+ const X509_VERIFY_PARAM *src)
+{
+ unsigned long inh_flags;
+ int to_default, to_overwrite;
+ X509_VERIFY_PARAM_ID *id;
+ if (!src)
+ return 1;
+ id = src->id;
+ inh_flags = dest->inh_flags | src->inh_flags;
+
+ if (inh_flags & X509_VP_FLAG_ONCE)
+ dest->inh_flags = 0;
+
+ if (inh_flags & X509_VP_FLAG_LOCKED)
+ return 1;
+
+ if (inh_flags & X509_VP_FLAG_DEFAULT)
+ to_default = 1;
+ else
+ to_default = 0;
+
+ if (inh_flags & X509_VP_FLAG_OVERWRITE)
+ to_overwrite = 1;
+ else
+ to_overwrite = 0;
+
+ x509_verify_param_copy(purpose, 0);
+ x509_verify_param_copy(trust, 0);
+ x509_verify_param_copy(depth, -1);
+
+ /* If overwrite or check time not set, copy across */
+
+ if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
+ dest->check_time = src->check_time;
+ dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
+ /* Don't need to copy flag: that is done below */
+ }
+
+ if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
+ dest->flags = 0;
+
+ dest->flags |= src->flags;
+
+ if (test_x509_verify_param_copy(policies, NULL)) {
+ if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
+ return 0;
+ }
+
+ /* Copy the host flags if and only if we're copying the host list */
+ if (test_x509_verify_param_copy_id(hosts, NULL)) {
+ if (dest->id->hosts) {
+ string_stack_free(dest->id->hosts);
+ dest->id->hosts = NULL;
+ }
+ if (id->hosts) {
+ dest->id->hosts =
+ sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free);
+ if (dest->id->hosts == NULL)
+ return 0;
+ dest->id->hostflags = id->hostflags;
+ }
+ }
+
+ if (test_x509_verify_param_copy_id(email, NULL)) {
+ if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
+ return 0;
+ }
+
+ if (test_x509_verify_param_copy_id(ip, NULL)) {
+ if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
+ return 0;
+ }
+
+ return 1;
+}
int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
- const X509_VERIFY_PARAM *from)
- {
- unsigned long save_flags = to->inh_flags;
- int ret;
- to->inh_flags |= X509_VP_FLAG_DEFAULT;
- ret = X509_VERIFY_PARAM_inherit(to, from);
- to->inh_flags = save_flags;
- return ret;
- }
+ const X509_VERIFY_PARAM *from)
+{
+ unsigned long save_flags = to->inh_flags;
+ int ret;
+ to->inh_flags |= X509_VP_FLAG_DEFAULT;
+ ret = X509_VERIFY_PARAM_inherit(to, from);
+ to->inh_flags = save_flags;
+ return ret;
+}
static int int_x509_param_set1(char **pdest, size_t *pdestlen,
- const char *src, size_t srclen)
- {
- void *tmp;
- if (src)
- {
- if (srclen == 0)
- {
- tmp = BUF_strdup(src);
- srclen = strlen(src);
- }
- else
- tmp = BUF_memdup(src, srclen);
- if (!tmp)
- return 0;
- }
- else
- {
- tmp = NULL;
- srclen = 0;
- }
- if (*pdest)
- OPENSSL_free(*pdest);
- *pdest = tmp;
- if (pdestlen)
- *pdestlen = srclen;
- return 1;
- }
+ const char *src, size_t srclen)
+{
+ void *tmp;
+ if (src) {
+ if (srclen == 0) {
+ tmp = BUF_strdup(src);
+ srclen = strlen(src);
+ } else
+ tmp = BUF_memdup(src, srclen);
+ if (!tmp)
+ return 0;
+ } else {
+ tmp = NULL;
+ srclen = 0;
+ }
+ if (*pdest)
+ OPENSSL_free(*pdest);
+ *pdest = tmp;
+ if (pdestlen)
+ *pdestlen = srclen;
+ return 1;
+}
int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
- {
- if (param->name)
- OPENSSL_free(param->name);
- param->name = BUF_strdup(name);
- if (param->name)
- return 1;
- return 0;
- }
+{
+ if (param->name)
+ OPENSSL_free(param->name);
+ param->name = BUF_strdup(name);
+ if (param->name)
+ return 1;
+ return 0;
+}
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
- {
- param->flags |= flags;
- if (flags & X509_V_FLAG_POLICY_MASK)
- param->flags |= X509_V_FLAG_POLICY_CHECK;
- return 1;
- }
-
-int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
- {
- param->flags &= ~flags;
- return 1;
- }
+{
+ param->flags |= flags;
+ if (flags & X509_V_FLAG_POLICY_MASK)
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+}
+
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags)
+{
+ param->flags &= ~flags;
+ return 1;
+}
unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
- {
- return param->flags;
- }
+{
+ return param->flags;
+}
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
- {
- return X509_PURPOSE_set(&param->purpose, purpose);
- }
+{
+ return X509_PURPOSE_set(&param->purpose, purpose);
+}
int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
- {
- return X509_TRUST_set(&param->trust, trust);
- }
+{
+ return X509_TRUST_set(&param->trust, trust);
+}
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
- {
- param->depth = depth;
- }
+{
+ param->depth = depth;
+}
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
- {
- param->check_time = t;
- param->flags |= X509_V_FLAG_USE_CHECK_TIME;
- }
-
-int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
- {
- if (!param->policies)
- {
- param->policies = sk_ASN1_OBJECT_new_null();
- if (!param->policies)
- return 0;
- }
- if (!sk_ASN1_OBJECT_push(param->policies, policy))
- return 0;
- return 1;
- }
-
-int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
- STACK_OF(ASN1_OBJECT) *policies)
- {
- size_t i;
- ASN1_OBJECT *oid, *doid;
- if (!param)
- return 0;
- if (param->policies)
- sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
-
- if (!policies)
- {
- param->policies = NULL;
- return 1;
- }
-
- param->policies = sk_ASN1_OBJECT_new_null();
- if (!param->policies)
- return 0;
-
- for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++)
- {
- oid = sk_ASN1_OBJECT_value(policies, i);
- doid = OBJ_dup(oid);
- if (!doid)
- return 0;
- if (!sk_ASN1_OBJECT_push(param->policies, doid))
- {
- ASN1_OBJECT_free(doid);
- return 0;
- }
- }
- param->flags |= X509_V_FLAG_POLICY_CHECK;
- return 1;
- }
+{
+ param->check_time = t;
+ param->flags |= X509_V_FLAG_USE_CHECK_TIME;
+}
+
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+ ASN1_OBJECT *policy)
+{
+ if (!param->policies) {
+ param->policies = sk_ASN1_OBJECT_new_null();
+ if (!param->policies)
+ return 0;
+ }
+ if (!sk_ASN1_OBJECT_push(param->policies, policy))
+ return 0;
+ return 1;
+}
+
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies)
+{
+ size_t i;
+ ASN1_OBJECT *oid, *doid;
+ if (!param)
+ return 0;
+ if (param->policies)
+ sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+
+ if (!policies) {
+ param->policies = NULL;
+ return 1;
+ }
+
+ param->policies = sk_ASN1_OBJECT_new_null();
+ if (!param->policies)
+ return 0;
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
+ oid = sk_ASN1_OBJECT_value(policies, i);
+ doid = OBJ_dup(oid);
+ if (!doid)
+ return 0;
+ if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
+ ASN1_OBJECT_free(doid);
+ return 0;
+ }
+ }
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+}
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen)
- {
- return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
- }
+ const char *name, size_t namelen)
+{
+ return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
+}
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen)
- {
- return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
- }
+ const char *name, size_t namelen)
+{
+ return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
+}
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
- unsigned int flags)
- {
- param->id->hostflags = flags;
- }
+ unsigned int flags)
+{
+ param->id->hostflags = flags;
+}
char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
- {
- return param->id->peername;
- }
+{
+ return param->id->peername;
+}
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
- const char *email, size_t emaillen)
- {
- return int_x509_param_set1(&param->id->email, &param->id->emaillen,
- email, emaillen);
- }
+ const char *email, size_t emaillen)
+{
+ return int_x509_param_set1(&param->id->email, &param->id->emaillen,
+ email, emaillen);
+}
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
- const unsigned char *ip, size_t iplen)
- {
- if (iplen != 0 && iplen != 4 && iplen != 16)
- return 0;
- return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
- (char *)ip, iplen);
- }
+ const unsigned char *ip, size_t iplen)
+{
+ if (iplen != 0 && iplen != 4 && iplen != 16)
+ return 0;
+ return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
+ (char *)ip, iplen);
+}
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
- {
- unsigned char ipout[16];
- size_t iplen;
+{
+ unsigned char ipout[16];
+ size_t iplen;
- iplen = (size_t) a2i_ipadd(ipout, ipasc);
- if (iplen == 0)
- return 0;
- return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
- }
+ iplen = (size_t)a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return 0;
+ return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
+}
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
- {
- return param->depth;
- }
+{
+ return param->depth;
+}
const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
- {
- return param->name;
- }
+{
+ return param->name;
+}
-static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0U, NULL, NULL, 0, NULL, 0};
+static const X509_VERIFY_PARAM_ID _empty_id =
+ { NULL, 0U, NULL, NULL, 0, NULL, 0 };
#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
-/* Default verify parameters: these are used for various
- * applications and can be overridden by the user specified table.
- * NB: the 'name' field *must* be in alphabetical order because it
- * will be searched using OBJ_search.
+/*
+ * Default verify parameters: these are used for various applications and can
+ * be overridden by the user specified table. NB: the 'name' field *must* be
+ * in alphabetical order because it will be searched using OBJ_search.
*/
static const X509_VERIFY_PARAM default_table[] = {
- {
- (char *) "default", /* X509 default parameters */
- 0, /* Check time */
- 0, /* internal flags */
- 0, /* flags */
- 0, /* purpose */
- 0, /* trust */
- 100, /* depth */
- NULL, /* policies */
- vpm_empty_id
- },
- {
- (char *) "pkcs7", /* S/MIME sign parameters */
- 0, /* Check time */
- 0, /* internal flags */
- 0, /* flags */
- X509_PURPOSE_SMIME_SIGN, /* purpose */
- X509_TRUST_EMAIL, /* trust */
- -1, /* depth */
- NULL, /* policies */
- vpm_empty_id
- },
- {
- (char *) "smime_sign", /* S/MIME sign parameters */
- 0, /* Check time */
- 0, /* internal flags */
- 0, /* flags */
- X509_PURPOSE_SMIME_SIGN, /* purpose */
- X509_TRUST_EMAIL, /* trust */
- -1, /* depth */
- NULL, /* policies */
- vpm_empty_id
- },
- {
- (char *) "ssl_client", /* SSL/TLS client parameters */
- 0, /* Check time */
- 0, /* internal flags */
- 0, /* flags */
- X509_PURPOSE_SSL_CLIENT, /* purpose */
- X509_TRUST_SSL_CLIENT, /* trust */
- -1, /* depth */
- NULL, /* policies */
- vpm_empty_id
- },
- {
- (char *) "ssl_server", /* SSL/TLS server parameters */
- 0, /* Check time */
- 0, /* internal flags */
- 0, /* flags */
- X509_PURPOSE_SSL_SERVER, /* purpose */
- X509_TRUST_SSL_SERVER, /* trust */
- -1, /* depth */
- NULL, /* policies */
- vpm_empty_id
- }};
+ {
+ (char *)"default", /* X509 default parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ 0, /* purpose */
+ 0, /* trust */
+ 100, /* depth */
+ NULL, /* policies */
+ vpm_empty_id},
+ {
+ (char *)"pkcs7", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id},
+ {
+ (char *)"smime_sign", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id},
+ {
+ (char *)"ssl_client", /* SSL/TLS client parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_CLIENT, /* purpose */
+ X509_TRUST_SSL_CLIENT, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id},
+ {
+ (char *)"ssl_server", /* SSL/TLS server parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_SERVER, /* purpose */
+ X509_TRUST_SSL_SERVER, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id}
+};
static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
-static int param_cmp(const X509_VERIFY_PARAM **a,
- const X509_VERIFY_PARAM **b)
- {
- return strcmp((*a)->name, (*b)->name);
- }
+static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b)
+{
+ return strcmp((*a)->name, (*b)->name);
+}
int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
- {
- X509_VERIFY_PARAM *ptmp;
- if (!param_table)
- {
- param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
- if (!param_table)
- return 0;
- }
- else
- {
- size_t idx;
-
- if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param))
- {
- ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
- X509_VERIFY_PARAM_free(ptmp);
- (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
- }
- }
- if (!sk_X509_VERIFY_PARAM_push(param_table, param))
- return 0;
- return 1;
- }
+{
+ X509_VERIFY_PARAM *ptmp;
+ if (!param_table) {
+ param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
+ if (!param_table)
+ return 0;
+ } else {
+ size_t idx;
+
+ if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) {
+ ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
+ X509_VERIFY_PARAM_free(ptmp);
+ (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
+ }
+ }
+ if (!sk_X509_VERIFY_PARAM_push(param_table, param))
+ return 0;
+ return 1;
+}
int X509_VERIFY_PARAM_get_count(void)
- {
- int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
- if (param_table)
- num += sk_X509_VERIFY_PARAM_num(param_table);
- return num;
- }
+{
+ int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+ if (param_table)
+ num += sk_X509_VERIFY_PARAM_num(param_table);
+ return num;
+}
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
- {
- int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
- if (id < num)
- return default_table + id;
- return sk_X509_VERIFY_PARAM_value(param_table, id - num);
- }
+{
+ int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+ if (id < num)
+ return default_table + id;
+ return sk_X509_VERIFY_PARAM_value(param_table, id - num);
+}
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
- {
- X509_VERIFY_PARAM pm;
- unsigned i, limit;
-
- pm.name = (char *)name;
- if (param_table)
- {
- size_t idx;
- if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
- return sk_X509_VERIFY_PARAM_value(param_table, idx);
- }
-
- limit = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
- for (i = 0; i < limit; i++) {
- if (strcmp(default_table[i].name, name) == 0) {
- return &default_table[i];
- }
- }
- return NULL;
- }
+{
+ X509_VERIFY_PARAM pm;
+ unsigned i, limit;
+
+ pm.name = (char *)name;
+ if (param_table) {
+ size_t idx;
+ if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
+ return sk_X509_VERIFY_PARAM_value(param_table, idx);
+ }
+
+ limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+ for (i = 0; i < limit; i++) {
+ if (strcmp(default_table[i].name, name) == 0) {
+ return &default_table[i];
+ }
+ }
+ return NULL;
+}
void X509_VERIFY_PARAM_table_cleanup(void)
- {
- if (param_table)
- sk_X509_VERIFY_PARAM_pop_free(param_table,
- X509_VERIFY_PARAM_free);
- param_table = NULL;
- }
+{
+ if (param_table)
+ sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
+ param_table = NULL;
+}
diff --git a/src/crypto/x509/x509cset.c b/src/crypto/x509/x509cset.c
index 82d61d06..a292710e 100644
--- a/src/crypto/x509/x509cset.c
+++ b/src/crypto/x509/x509cset.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
+ */
/* ====================================================================
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -59,114 +61,109 @@
#include "../internal.h"
-
int X509_CRL_set_version(X509_CRL *x, long version)
- {
- if (x == NULL) return(0);
- if (x->crl->version == NULL)
- {
- if ((x->crl->version=M_ASN1_INTEGER_new()) == NULL)
- return(0);
- }
- return(ASN1_INTEGER_set(x->crl->version,version));
- }
+{
+ if (x == NULL)
+ return (0);
+ if (x->crl->version == NULL) {
+ if ((x->crl->version = M_ASN1_INTEGER_new()) == NULL)
+ return (0);
+ }
+ return (ASN1_INTEGER_set(x->crl->version, version));
+}
int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
- {
- if ((x == NULL) || (x->crl == NULL)) return(0);
- return(X509_NAME_set(&x->crl->issuer,name));
- }
-
+{
+ if ((x == NULL) || (x->crl == NULL))
+ return (0);
+ return (X509_NAME_set(&x->crl->issuer, name));
+}
int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm)
- {
- ASN1_TIME *in;
-
- if (x == NULL) return(0);
- in=x->crl->lastUpdate;
- if (in != tm)
- {
- in=M_ASN1_TIME_dup(tm);
- if (in != NULL)
- {
- M_ASN1_TIME_free(x->crl->lastUpdate);
- x->crl->lastUpdate=in;
- }
- }
- return(in != NULL);
- }
+{
+ ASN1_TIME *in;
+
+ if (x == NULL)
+ return (0);
+ in = x->crl->lastUpdate;
+ if (in != tm) {
+ in = M_ASN1_TIME_dup(tm);
+ if (in != NULL) {
+ M_ASN1_TIME_free(x->crl->lastUpdate);
+ x->crl->lastUpdate = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm)
- {
- ASN1_TIME *in;
-
- if (x == NULL) return(0);
- in=x->crl->nextUpdate;
- if (in != tm)
- {
- in=M_ASN1_TIME_dup(tm);
- if (in != NULL)
- {
- M_ASN1_TIME_free(x->crl->nextUpdate);
- x->crl->nextUpdate=in;
- }
- }
- return(in != NULL);
- }
+{
+ ASN1_TIME *in;
+
+ if (x == NULL)
+ return (0);
+ in = x->crl->nextUpdate;
+ if (in != tm) {
+ in = M_ASN1_TIME_dup(tm);
+ if (in != NULL) {
+ M_ASN1_TIME_free(x->crl->nextUpdate);
+ x->crl->nextUpdate = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_CRL_sort(X509_CRL *c)
- {
- size_t i;
- X509_REVOKED *r;
- /* sort the data so it will be written in serial
- * number order */
- sk_X509_REVOKED_sort(c->crl->revoked);
- for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++)
- {
- r=sk_X509_REVOKED_value(c->crl->revoked,i);
- r->sequence=i;
- }
- c->crl->enc.modified = 1;
- return 1;
- }
+{
+ size_t i;
+ X509_REVOKED *r;
+ /*
+ * sort the data so it will be written in serial number order
+ */
+ sk_X509_REVOKED_sort(c->crl->revoked);
+ for (i = 0; i < sk_X509_REVOKED_num(c->crl->revoked); i++) {
+ r = sk_X509_REVOKED_value(c->crl->revoked, i);
+ r->sequence = i;
+ }
+ c->crl->enc.modified = 1;
+ return 1;
+}
void X509_CRL_up_ref(X509_CRL *crl)
- {
- CRYPTO_refcount_inc(&crl->references);
- }
+{
+ CRYPTO_refcount_inc(&crl->references);
+}
int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm)
- {
- ASN1_TIME *in;
-
- if (x == NULL) return(0);
- in=x->revocationDate;
- if (in != tm)
- {
- in=M_ASN1_TIME_dup(tm);
- if (in != NULL)
- {
- M_ASN1_TIME_free(x->revocationDate);
- x->revocationDate=in;
- }
- }
- return(in != NULL);
- }
+{
+ ASN1_TIME *in;
+
+ if (x == NULL)
+ return (0);
+ in = x->revocationDate;
+ if (in != tm) {
+ in = M_ASN1_TIME_dup(tm);
+ if (in != NULL) {
+ M_ASN1_TIME_free(x->revocationDate);
+ x->revocationDate = in;
+ }
+ }
+ return (in != NULL);
+}
int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial)
- {
- ASN1_INTEGER *in;
-
- if (x == NULL) return(0);
- in=x->serialNumber;
- if (in != serial)
- {
- in=M_ASN1_INTEGER_dup(serial);
- if (in != NULL)
- {
- M_ASN1_INTEGER_free(x->serialNumber);
- x->serialNumber=in;
- }
- }
- return(in != NULL);
- }
+{
+ ASN1_INTEGER *in;
+
+ if (x == NULL)
+ return (0);
+ in = x->serialNumber;
+ if (in != serial) {
+ in = M_ASN1_INTEGER_dup(serial);
+ if (in != NULL) {
+ M_ASN1_INTEGER_free(x->serialNumber);
+ x->serialNumber = in;
+ }
+ }
+ return (in != NULL);
+}
diff --git a/src/crypto/x509/x509name.c b/src/crypto/x509/x509name.c
index 8b10fa27..050e16a8 100644
--- a/src/crypto/x509/x509name.c
+++ b/src/crypto/x509/x509name.c
@@ -63,313 +63,324 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
-
int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
- {
- const ASN1_OBJECT *obj;
-
- obj=OBJ_nid2obj(nid);
- if (obj == NULL) return(-1);
- return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
- }
-
-int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf,
- int len)
- {
- int i;
- ASN1_STRING *data;
-
- i=X509_NAME_get_index_by_OBJ(name,obj,-1);
- if (i < 0) return(-1);
- data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
- i=(data->length > (len-1))?(len-1):data->length;
- if (buf == NULL) return(data->length);
- memcpy(buf,data->data,i);
- buf[i]='\0';
- return(i);
- }
+{
+ const ASN1_OBJECT *obj;
+
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ return (-1);
+ return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
+}
+
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+ char *buf, int len)
+{
+ int i;
+ ASN1_STRING *data;
+
+ i = X509_NAME_get_index_by_OBJ(name, obj, -1);
+ if (i < 0)
+ return (-1);
+ data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
+ i = (data->length > (len - 1)) ? (len - 1) : data->length;
+ if (buf == NULL)
+ return (data->length);
+ memcpy(buf, data->data, i);
+ buf[i] = '\0';
+ return (i);
+}
int X509_NAME_entry_count(X509_NAME *name)
- {
- if (name == NULL) return(0);
- return(sk_X509_NAME_ENTRY_num(name->entries));
- }
+{
+ if (name == NULL)
+ return (0);
+ return (sk_X509_NAME_ENTRY_num(name->entries));
+}
int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
- {
- const ASN1_OBJECT *obj;
+{
+ const ASN1_OBJECT *obj;
- obj=OBJ_nid2obj(nid);
- if (obj == NULL) return(-2);
- return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
- }
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ return (-2);
+ return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
+}
/* NOTE: you should be passsing -1, not 0 as lastpos */
int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
- int lastpos)
- {
- int n;
- X509_NAME_ENTRY *ne;
- STACK_OF(X509_NAME_ENTRY) *sk;
-
- if (name == NULL) return(-1);
- if (lastpos < 0)
- lastpos= -1;
- sk=name->entries;
- n=sk_X509_NAME_ENTRY_num(sk);
- for (lastpos++; lastpos < n; lastpos++)
- {
- ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
- if (OBJ_cmp(ne->object,obj) == 0)
- return(lastpos);
- }
- return(-1);
- }
+ int lastpos)
+{
+ int n;
+ X509_NAME_ENTRY *ne;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL)
+ return (-1);
+ if (lastpos < 0)
+ lastpos = -1;
+ sk = name->entries;
+ n = sk_X509_NAME_ENTRY_num(sk);
+ for (lastpos++; lastpos < n; lastpos++) {
+ ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
+ if (OBJ_cmp(ne->object, obj) == 0)
+ return (lastpos);
+ }
+ return (-1);
+}
X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
- {
- if(name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
- return(NULL);
- else
- return(sk_X509_NAME_ENTRY_value(name->entries,loc));
- }
+{
+ if (name == NULL || loc < 0
+ || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc)
+ return (NULL);
+ else
+ return (sk_X509_NAME_ENTRY_value(name->entries, loc));
+}
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
- {
- X509_NAME_ENTRY *ret;
- int i,n,set_prev,set_next;
- STACK_OF(X509_NAME_ENTRY) *sk;
-
- if (name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
- return(NULL);
- sk=name->entries;
- ret=sk_X509_NAME_ENTRY_delete(sk,loc);
- n=sk_X509_NAME_ENTRY_num(sk);
- name->modified=1;
- if (loc == n) return(ret);
-
- /* else we need to fixup the set field */
- if (loc != 0)
- set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
- else
- set_prev=ret->set-1;
- set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
-
- /* set_prev is the previous set
- * set is the current set
- * set_next is the following
- * prev 1 1 1 1 1 1 1 1
- * set 1 1 2 2
- * next 1 1 2 2 2 2 3 2
- * so basically only if prev and next differ by 2, then
- * re-number down by 1 */
- if (set_prev+1 < set_next)
- for (i=loc; i<n; i++)
- sk_X509_NAME_ENTRY_value(sk,i)->set--;
- return(ret);
- }
+{
+ X509_NAME_ENTRY *ret;
+ int i, n, set_prev, set_next;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL || loc < 0
+ || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc)
+ return (NULL);
+ sk = name->entries;
+ ret = sk_X509_NAME_ENTRY_delete(sk, loc);
+ n = sk_X509_NAME_ENTRY_num(sk);
+ name->modified = 1;
+ if (loc == n)
+ return (ret);
+
+ /* else we need to fixup the set field */
+ if (loc != 0)
+ set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
+ else
+ set_prev = ret->set - 1;
+ set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
+
+ /*
+ * set_prev is the previous set set is the current set set_next is the
+ * following prev 1 1 1 1 1 1 1 1 set 1 1 2 2 next 1 1 2 2 2 2 3 2 so
+ * basically only if prev and next differ by 2, then re-number down by 1
+ */
+ if (set_prev + 1 < set_next)
+ for (i = loc; i < n; i++)
+ sk_X509_NAME_ENTRY_value(sk, i)->set--;
+ return (ret);
+}
int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
- unsigned char *bytes, int len, int loc, int set)
+ unsigned char *bytes, int len, int loc,
+ int set)
{
- X509_NAME_ENTRY *ne;
- int ret;
- ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
- if(!ne) return 0;
- ret = X509_NAME_add_entry(name, ne, loc, set);
- X509_NAME_ENTRY_free(ne);
- return ret;
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
+ if (!ne)
+ return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
}
int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
- unsigned char *bytes, int len, int loc, int set)
+ unsigned char *bytes, int len, int loc,
+ int set)
{
- X509_NAME_ENTRY *ne;
- int ret;
- ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
- if(!ne) return 0;
- ret = X509_NAME_add_entry(name, ne, loc, set);
- X509_NAME_ENTRY_free(ne);
- return ret;
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+ if (!ne)
+ return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
}
int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
- const unsigned char *bytes, int len, int loc, int set)
+ const unsigned char *bytes, int len, int loc,
+ int set)
{
- X509_NAME_ENTRY *ne;
- int ret;
- ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
- if(!ne) return 0;
- ret = X509_NAME_add_entry(name, ne, loc, set);
- X509_NAME_ENTRY_free(ne);
- return ret;
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
+ if (!ne)
+ return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
}
-/* if set is -1, append to previous set, 0 'a new one', and 1,
- * prepend to the guy we are about to stomp on. */
+/*
+ * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
+ * guy we are about to stomp on.
+ */
int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
- int set)
- {
- X509_NAME_ENTRY *new_name=NULL;
- int n,i,inc;
- STACK_OF(X509_NAME_ENTRY) *sk;
-
- if (name == NULL) return(0);
- sk=name->entries;
- n=sk_X509_NAME_ENTRY_num(sk);
- if (loc > n) loc=n;
- else if (loc < 0) loc=n;
-
- name->modified=1;
-
- if (set == -1)
- {
- if (loc == 0)
- {
- set=0;
- inc=1;
- }
- else
- {
- set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
- inc=0;
- }
- }
- else /* if (set >= 0) */
- {
- if (loc >= n)
- {
- if (loc != 0)
- set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
- else
- set=0;
- }
- else
- set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
- inc=(set == 0)?1:0;
- }
-
- if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
- goto err;
- new_name->set=set;
- if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (inc)
- {
- n=sk_X509_NAME_ENTRY_num(sk);
- for (i=loc+1; i<n; i++)
- sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
- }
- return(1);
-err:
- if (new_name != NULL)
- X509_NAME_ENTRY_free(new_name);
- return(0);
- }
+ int set)
+{
+ X509_NAME_ENTRY *new_name = NULL;
+ int n, i, inc;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL)
+ return (0);
+ sk = name->entries;
+ n = sk_X509_NAME_ENTRY_num(sk);
+ if (loc > n)
+ loc = n;
+ else if (loc < 0)
+ loc = n;
+
+ name->modified = 1;
+
+ if (set == -1) {
+ if (loc == 0) {
+ set = 0;
+ inc = 1;
+ } else {
+ set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
+ inc = 0;
+ }
+ } else { /* if (set >= 0) */
+
+ if (loc >= n) {
+ if (loc != 0)
+ set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
+ else
+ set = 0;
+ } else
+ set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
+ inc = (set == 0) ? 1 : 0;
+ }
+
+ if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
+ goto err;
+ new_name->set = set;
+ if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (inc) {
+ n = sk_X509_NAME_ENTRY_num(sk);
+ for (i = loc + 1; i < n; i++)
+ sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
+ }
+ return (1);
+ err:
+ if (new_name != NULL)
+ X509_NAME_ENTRY_free(new_name);
+ return (0);
+}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
- const char *field, int type, const unsigned char *bytes, int len)
- {
- ASN1_OBJECT *obj;
- X509_NAME_ENTRY *nentry;
-
- obj=OBJ_txt2obj(field, 0);
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
- ERR_add_error_data(2, "name=", field);
- return(NULL);
- }
- nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
- ASN1_OBJECT_free(obj);
- return nentry;
- }
+ const char *field, int type,
+ const unsigned char *bytes,
+ int len)
+{
+ ASN1_OBJECT *obj;
+ X509_NAME_ENTRY *nentry;
+
+ obj = OBJ_txt2obj(field, 0);
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", field);
+ return (NULL);
+ }
+ nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
+ ASN1_OBJECT_free(obj);
+ return nentry;
+}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
- int type, unsigned char *bytes, int len)
- {
- const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
- if (obj == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
- return NULL;
- }
- return X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
- }
+ int type, unsigned char *bytes,
+ int len)
+{
+ const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+ if (obj == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+ return NULL;
+ }
+ return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
+}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
- const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
- {
- X509_NAME_ENTRY *ret;
-
- if ((ne == NULL) || (*ne == NULL))
- {
- if ((ret=X509_NAME_ENTRY_new()) == NULL)
- return(NULL);
- }
- else
- ret= *ne;
-
- if (!X509_NAME_ENTRY_set_object(ret,obj))
- goto err;
- if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
- goto err;
-
- if ((ne != NULL) && (*ne == NULL)) *ne=ret;
- return(ret);
-err:
- if ((ne == NULL) || (ret != *ne))
- X509_NAME_ENTRY_free(ret);
- return(NULL);
- }
+ const ASN1_OBJECT *obj,
+ int type,
+ const unsigned char *bytes,
+ int len)
+{
+ X509_NAME_ENTRY *ret;
+
+ if ((ne == NULL) || (*ne == NULL)) {
+ if ((ret = X509_NAME_ENTRY_new()) == NULL)
+ return (NULL);
+ } else
+ ret = *ne;
+
+ if (!X509_NAME_ENTRY_set_object(ret, obj))
+ goto err;
+ if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
+ goto err;
+
+ if ((ne != NULL) && (*ne == NULL))
+ *ne = ret;
+ return (ret);
+ err:
+ if ((ne == NULL) || (ret != *ne))
+ X509_NAME_ENTRY_free(ret);
+ return (NULL);
+}
int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
- {
- if ((ne == NULL) || (obj == NULL))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
- return(0);
- }
- ASN1_OBJECT_free(ne->object);
- ne->object=OBJ_dup(obj);
- return((ne->object == NULL)?0:1);
- }
+{
+ if ((ne == NULL) || (obj == NULL)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ ASN1_OBJECT_free(ne->object);
+ ne->object = OBJ_dup(obj);
+ return ((ne->object == NULL) ? 0 : 1);
+}
int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
- const unsigned char *bytes, int len)
- {
- int i;
-
- if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
- if((type > 0) && (type & MBSTRING_FLAG))
- return ASN1_STRING_set_by_NID(&ne->value, bytes,
- len, type,
- OBJ_obj2nid(ne->object)) ? 1 : 0;
- if (len < 0) len=strlen((const char *)bytes);
- i=ASN1_STRING_set(ne->value,bytes,len);
- if (!i) return(0);
- if (type != V_ASN1_UNDEF)
- {
- if (type == V_ASN1_APP_CHOOSE)
- ne->value->type=ASN1_PRINTABLE_type(bytes,len);
- else
- ne->value->type=type;
- }
- return(1);
- }
+ const unsigned char *bytes, int len)
+{
+ int i;
+
+ if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
+ return (0);
+ if ((type > 0) && (type & MBSTRING_FLAG))
+ return ASN1_STRING_set_by_NID(&ne->value, bytes,
+ len, type,
+ OBJ_obj2nid(ne->object)) ? 1 : 0;
+ if (len < 0)
+ len = strlen((const char *)bytes);
+ i = ASN1_STRING_set(ne->value, bytes, len);
+ if (!i)
+ return (0);
+ if (type != V_ASN1_UNDEF) {
+ if (type == V_ASN1_APP_CHOOSE)
+ ne->value->type = ASN1_PRINTABLE_type(bytes, len);
+ else
+ ne->value->type = type;
+ }
+ return (1);
+}
ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
- {
- if (ne == NULL) return(NULL);
- return(ne->object);
- }
+{
+ if (ne == NULL)
+ return (NULL);
+ return (ne->object);
+}
ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
- {
- if (ne == NULL) return(NULL);
- return(ne->value);
- }
-
+{
+ if (ne == NULL)
+ return (NULL);
+ return (ne->value);
+}
diff --git a/src/crypto/x509/x509rset.c b/src/crypto/x509/x509rset.c
index dbab555d..c4e6683d 100644
--- a/src/crypto/x509/x509rset.c
+++ b/src/crypto/x509/x509rset.c
@@ -59,22 +59,23 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
int X509_REQ_set_version(X509_REQ *x, long version)
- {
- if (x == NULL) return(0);
- return(ASN1_INTEGER_set(x->req_info->version,version));
- }
+{
+ if (x == NULL)
+ return (0);
+ return (ASN1_INTEGER_set(x->req_info->version, version));
+}
int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
- {
- if ((x == NULL) || (x->req_info == NULL)) return(0);
- return(X509_NAME_set(&x->req_info->subject,name));
- }
+{
+ if ((x == NULL) || (x->req_info == NULL))
+ return (0);
+ return (X509_NAME_set(&x->req_info->subject, name));
+}
int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
- {
- if ((x == NULL) || (x->req_info == NULL)) return(0);
- return(X509_PUBKEY_set(&x->req_info->pubkey,pkey));
- }
-
+{
+ if ((x == NULL) || (x->req_info == NULL))
+ return (0);
+ return (X509_PUBKEY_set(&x->req_info->pubkey, pkey));
+}
diff --git a/src/crypto/x509/x509spki.c b/src/crypto/x509/x509spki.c
index ccf93e06..4a9b95e7 100644
--- a/src/crypto/x509/x509spki.c
+++ b/src/crypto/x509/x509spki.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -59,77 +61,77 @@
#include <openssl/mem.h>
#include <openssl/x509.h>
-
int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
{
- if ((x == NULL) || (x->spkac == NULL)) return(0);
- return(X509_PUBKEY_set(&(x->spkac->pubkey),pkey));
+ if ((x == NULL) || (x->spkac == NULL))
+ return (0);
+ return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey));
}
EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x)
{
- if ((x == NULL) || (x->spkac == NULL))
- return(NULL);
- return(X509_PUBKEY_get(x->spkac->pubkey));
+ if ((x == NULL) || (x->spkac == NULL))
+ return (NULL);
+ return (X509_PUBKEY_get(x->spkac->pubkey));
}
/* Load a Netscape SPKI from a base64 encoded string */
-NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len)
+NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len)
{
- unsigned char *spki_der;
- const unsigned char *p;
- size_t spki_len;
- NETSCAPE_SPKI *spki;
- if (len <= 0)
- len = strlen(str);
- if (!EVP_DecodedLength(&spki_len, len)) {
- OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
- return NULL;
- }
- if (!(spki_der = OPENSSL_malloc(spki_len))) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
- OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
- OPENSSL_free(spki_der);
- return NULL;
- }
- p = spki_der;
- spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
- OPENSSL_free(spki_der);
- return spki;
+ unsigned char *spki_der;
+ const unsigned char *p;
+ size_t spki_len;
+ NETSCAPE_SPKI *spki;
+ if (len <= 0)
+ len = strlen(str);
+ if (!EVP_DecodedLength(&spki_len, len)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
+ return NULL;
+ }
+ if (!(spki_der = OPENSSL_malloc(spki_len))) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!EVP_DecodeBase64
+ (spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
+ OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
+ OPENSSL_free(spki_der);
+ return NULL;
+ }
+ p = spki_der;
+ spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
+ OPENSSL_free(spki_der);
+ return spki;
}
/* Generate a base64 encoded string from an SPKI */
-char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
+char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
{
- unsigned char *der_spki, *p;
- char *b64_str;
- size_t b64_len;
- int der_len;
- der_len = i2d_NETSCAPE_SPKI(spki, NULL);
- if (!EVP_EncodedLength(&b64_len, der_len))
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
- return NULL;
- }
- der_spki = OPENSSL_malloc(der_len);
- if (der_spki == NULL) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- b64_str = OPENSSL_malloc(b64_len);
- if (b64_str == NULL) {
- OPENSSL_free(der_spki);
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- p = der_spki;
- i2d_NETSCAPE_SPKI(spki, &p);
- EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
- OPENSSL_free(der_spki);
- return b64_str;
+ unsigned char *der_spki, *p;
+ char *b64_str;
+ size_t b64_len;
+ int der_len;
+ der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+ if (!EVP_EncodedLength(&b64_len, der_len)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
+ return NULL;
+ }
+ der_spki = OPENSSL_malloc(der_len);
+ if (der_spki == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ b64_str = OPENSSL_malloc(b64_len);
+ if (b64_str == NULL) {
+ OPENSSL_free(der_spki);
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ p = der_spki;
+ i2d_NETSCAPE_SPKI(spki, &p);
+ EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
+ OPENSSL_free(der_spki);
+ return b64_str;
}
diff --git a/src/crypto/x509/x509type.c b/src/crypto/x509/x509type.c
index e7c79354..d4f5a4dc 100644
--- a/src/crypto/x509/x509type.c
+++ b/src/crypto/x509/x509type.c
@@ -58,71 +58,69 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
- {
- EVP_PKEY *pk;
- int ret=0,i;
-
- if (x == NULL) return(0);
+{
+ EVP_PKEY *pk;
+ int ret = 0, i;
- if (pkey == NULL)
- pk=X509_get_pubkey(x);
- else
- pk=pkey;
+ if (x == NULL)
+ return (0);
- if (pk == NULL) return(0);
+ if (pkey == NULL)
+ pk = X509_get_pubkey(x);
+ else
+ pk = pkey;
- switch (pk->type)
- {
- case EVP_PKEY_RSA:
- ret=EVP_PK_RSA|EVP_PKT_SIGN;
-/* if (!sign only extension) */
- ret|=EVP_PKT_ENC;
- break;
- case EVP_PKEY_DSA:
- ret=EVP_PK_DSA|EVP_PKT_SIGN;
- break;
- case EVP_PKEY_EC:
- ret=EVP_PK_EC|EVP_PKT_SIGN|EVP_PKT_EXCH;
- break;
- case EVP_PKEY_DH:
- ret=EVP_PK_DH|EVP_PKT_EXCH;
- break;
- case NID_id_GostR3410_94:
- case NID_id_GostR3410_2001:
- ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
- break;
- default:
- break;
- }
+ if (pk == NULL)
+ return (0);
- i=OBJ_obj2nid(x->sig_alg->algorithm);
- if (i && OBJ_find_sigid_algs(i, NULL, &i))
- {
+ switch (pk->type) {
+ case EVP_PKEY_RSA:
+ ret = EVP_PK_RSA | EVP_PKT_SIGN;
+/* if (!sign only extension) */
+ ret |= EVP_PKT_ENC;
+ break;
+ case EVP_PKEY_DSA:
+ ret = EVP_PK_DSA | EVP_PKT_SIGN;
+ break;
+ case EVP_PKEY_EC:
+ ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH;
+ break;
+ case EVP_PKEY_DH:
+ ret = EVP_PK_DH | EVP_PKT_EXCH;
+ break;
+ case NID_id_GostR3410_94:
+ case NID_id_GostR3410_2001:
+ ret = EVP_PKT_EXCH | EVP_PKT_SIGN;
+ break;
+ default:
+ break;
+ }
- switch (i)
- {
- case NID_rsaEncryption:
- case NID_rsa:
- ret|=EVP_PKS_RSA;
- break;
- case NID_dsa:
- case NID_dsa_2:
- ret|=EVP_PKS_DSA;
- break;
- case NID_X9_62_id_ecPublicKey:
- ret|=EVP_PKS_EC;
- break;
- default:
- break;
- }
- }
+ i = OBJ_obj2nid(x->sig_alg->algorithm);
+ if (i && OBJ_find_sigid_algs(i, NULL, &i)) {
- if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look
- for, not bytes */
- ret|=EVP_PKT_EXP;
- if(pkey==NULL) EVP_PKEY_free(pk);
- return(ret);
- }
+ switch (i) {
+ case NID_rsaEncryption:
+ case NID_rsa:
+ ret |= EVP_PKS_RSA;
+ break;
+ case NID_dsa:
+ case NID_dsa_2:
+ ret |= EVP_PKS_DSA;
+ break;
+ case NID_X9_62_id_ecPublicKey:
+ ret |= EVP_PKS_EC;
+ break;
+ default:
+ break;
+ }
+ }
+ if (EVP_PKEY_size(pk) <= 1024 / 8) /* /8 because it's 1024 bits we look
+ * for, not bytes */
+ ret |= EVP_PKT_EXP;
+ if (pkey == NULL)
+ EVP_PKEY_free(pk);
+ return (ret);
+}
diff --git a/src/crypto/x509/x_algor.c b/src/crypto/x509/x_algor.c
index ae694e3d..abacd061 100644
--- a/src/crypto/x509/x_algor.c
+++ b/src/crypto/x509/x_algor.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2000. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2000.
+ */
/* ====================================================================
* Copyright (c) 2000 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -61,12 +63,12 @@
ASN1_SEQUENCE(X509_ALGOR) = {
- ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
- ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
+ ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
+ 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(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)
@@ -75,80 +77,75 @@ IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
-int X509_ALGOR_set0(X509_ALGOR *alg, const 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 = (ASN1_OBJECT*) 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;
- }
+int X509_ALGOR_set0(X509_ALGOR *alg, const 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 = (ASN1_OBJECT *)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;
- }
- }
+ 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;
+ }
+}
/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
- {
- int param_type;
+{
+ int param_type;
- if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
- param_type = V_ASN1_UNDEF;
- else
- param_type = V_ASN1_NULL;
+ if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
+ param_type = V_ASN1_UNDEF;
+ else
+ param_type = V_ASN1_NULL;
- X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+ X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
- }
+}
-/* X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */
+/*
+ * X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise.
+ */
int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
- {
- int rv;
- rv = OBJ_cmp(a->algorithm, b->algorithm);
- if (rv)
- return rv;
- if (!a->parameter && !b->parameter)
- return 0;
- return ASN1_TYPE_cmp(a->parameter, b->parameter);
- }
+{
+ int rv;
+ rv = OBJ_cmp(a->algorithm, b->algorithm);
+ if (rv)
+ return rv;
+ if (!a->parameter && !b->parameter)
+ return 0;
+ return ASN1_TYPE_cmp(a->parameter, b->parameter);
+}
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
index 62b3f402..c430a7d3 100644
--- a/src/crypto/x509/x_all.c
+++ b/src/crypto/x509/x_all.c
@@ -63,435 +63,439 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
-
int X509_verify(X509 *a, EVP_PKEY *r)
- {
- if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
- return 0;
- return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
- a->signature,a->cert_info,r));
- }
+{
+ if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
+ return 0;
+ return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), a->sig_alg,
+ a->signature, a->cert_info, r));
+}
int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
- {
- return( ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
- a->sig_alg,a->signature,a->req_info,r));
- }
+{
+ return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
+ a->sig_alg, a->signature, a->req_info, r));
+}
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
- {
- x->cert_info->enc.modified = 1;
- return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
- x->sig_alg, x->signature, x->cert_info,pkey,md));
- }
+{
+ x->cert_info->enc.modified = 1;
+ return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info, pkey, md));
+}
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
- {
- x->cert_info->enc.modified = 1;
- return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
- x->cert_info->signature,
- x->sig_alg, x->signature, x->cert_info, ctx);
- }
+{
+ x->cert_info->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
+ x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info, ctx);
+}
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
- {
- return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL,
- x->signature, x->req_info,pkey,md));
- }
+{
+ return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL,
+ x->signature, x->req_info, pkey, md));
+}
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
- {
- return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
- x->sig_alg, NULL, x->signature, x->req_info, ctx);
- }
+{
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
+ x->sig_alg, NULL, x->signature, x->req_info,
+ ctx);
+}
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
- {
- x->crl->enc.modified = 1;
- return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO),x->crl->sig_alg,
- x->sig_alg, x->signature, x->crl,pkey,md));
- }
+{
+ x->crl->enc.modified = 1;
+ return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg,
+ x->sig_alg, x->signature, x->crl, pkey, md));
+}
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
- {
- x->crl->enc.modified = 1;
- return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
- x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx);
- }
+{
+ x->crl->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
+ x->crl->sig_alg, x->sig_alg, x->signature,
+ x->crl, ctx);
+}
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
- {
- return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL,
- x->signature, x->spkac,pkey,md));
- }
+{
+ return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL,
+ x->signature, x->spkac, pkey, md));
+}
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
- {
- return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,
- x->signature, x->spkac, pkey));
- }
+{
+ return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,
+ x->signature, x->spkac, pkey));
+}
#ifndef OPENSSL_NO_FP_API
X509 *d2i_X509_fp(FILE *fp, X509 **x509)
- {
- return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
- }
+{
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
+}
int i2d_X509_fp(FILE *fp, X509 *x509)
- {
- return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
- }
+{
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
+}
#endif
X509 *d2i_X509_bio(BIO *bp, X509 **x509)
- {
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
- }
+{
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
+}
int i2d_X509_bio(BIO *bp, X509 *x509)
- {
- return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
- }
+{
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
+}
#ifndef OPENSSL_NO_FP_API
X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
- {
- return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
- }
+{
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+}
int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
- {
- return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
- }
+{
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+}
#endif
X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
- {
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
- }
+{
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+}
int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
- {
- return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
- }
+{
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+}
#ifndef OPENSSL_NO_FP_API
X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
- {
- return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
- }
+{
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+}
int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
- {
- return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
- }
+{
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+}
#endif
X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
- {
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
- }
+{
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+}
int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
- {
- return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
- }
-
+{
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+}
#ifndef OPENSSL_NO_FP_API
RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
- {
- return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
- }
+{
+ return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
+}
int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
- {
- return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
- }
+{
+ return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
+}
RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
- {
- return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
- }
+{
+ return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
+}
RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
- {
- return ASN1_d2i_fp((void *(*)(void))
- RSA_new,(D2I_OF(void))d2i_RSA_PUBKEY, fp,
- (void **)rsa);
- }
+{
+ return ASN1_d2i_fp((void *(*)(void))
+ RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
+ (void **)rsa);
+}
int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
- {
- return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
- }
+{
+ return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
+}
int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
- {
- return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY,fp,rsa);
- }
+{
+ return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa);
+}
#endif
RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
- {
- return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
- }
+{
+ return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
+}
int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
- {
- return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
- }
+{
+ return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
+}
RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
- {
- return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
- }
-
+{
+ return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
+}
RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
- {
- return ASN1_d2i_bio_of(RSA,RSA_new,d2i_RSA_PUBKEY,bp,rsa);
- }
+{
+ return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
+}
int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
- {
- return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
- }
+{
+ return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
+}
int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
- {
- return ASN1_i2d_bio_of_const(RSA,i2d_RSA_PUBKEY,bp,rsa);
- }
+{
+ return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa);
+}
#ifndef OPENSSL_NO_DSA
-#ifndef OPENSSL_NO_FP_API
+# ifndef OPENSSL_NO_FP_API
DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
- {
- return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSAPrivateKey,fp,dsa);
- }
+{
+ return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
+}
int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
- {
- return ASN1_i2d_fp_of_const(DSA,i2d_DSAPrivateKey,fp,dsa);
- }
+{
+ return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
+}
DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
- {
- return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSA_PUBKEY,fp,dsa);
- }
+{
+ return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
+}
int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
- {
- return ASN1_i2d_fp_of_const(DSA,i2d_DSA_PUBKEY,fp,dsa);
- }
-#endif
+{
+ return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa);
+}
+# endif
DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
- {
- return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAPrivateKey,bp,dsa
-);
- }
+{
+ return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
+}
int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
- {
- return ASN1_i2d_bio_of_const(DSA,i2d_DSAPrivateKey,bp,dsa);
- }
+{
+ return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
+}
DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
- {
- return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSA_PUBKEY,bp,dsa);
- }
+{
+ return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
+}
int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
- {
- return ASN1_i2d_bio_of_const(DSA,i2d_DSA_PUBKEY,bp,dsa);
- }
+{
+ return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa);
+}
#endif
#ifndef OPENSSL_NO_FP_API
EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
- {
- return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,fp,eckey);
- }
-
+{
+ return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
+}
+
int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
- {
- return ASN1_i2d_fp_of_const(EC_KEY,i2d_EC_PUBKEY,fp,eckey);
- }
+{
+ return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
+}
EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
- {
- return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,fp,eckey);
- }
-
+{
+ return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
+}
+
int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
- {
- return ASN1_i2d_fp_of_const(EC_KEY,i2d_ECPrivateKey,fp,eckey);
- }
+{
+ return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey);
+}
#endif
EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
- {
- return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,bp,eckey);
- }
-
+{
+ return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
+}
+
int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
- {
- return ASN1_i2d_bio_of_const(EC_KEY,i2d_EC_PUBKEY,bp,ecdsa);
- }
+{
+ return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
+}
EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
- {
- return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,bp,eckey);
- }
-
-int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
- {
- return ASN1_i2d_bio_of_const(EC_KEY,i2d_ECPrivateKey,bp,eckey);
- }
+{
+ return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
+}
+int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
+{
+ return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey);
+}
-int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
- unsigned int *len)
- {
- ASN1_BIT_STRING *key;
- key = X509_get0_pubkey_bitstr(data);
- if(!key) return 0;
- return EVP_Digest(key->data, key->length, md, len, type, NULL);
- }
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+{
+ ASN1_BIT_STRING *key;
+ key = X509_get0_pubkey_bitstr(data);
+ if (!key)
+ return 0;
+ return EVP_Digest(key->data, key->length, md, len, type, NULL);
+}
int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
- unsigned int *len)
- {
- return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len));
- }
-
-int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md,
- unsigned int *len)
- {
- return(ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL),type,(char *)data,md,len));
- }
-
-int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md,
- unsigned int *len)
- {
- return(ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ),type,(char *)data,md,len));
- }
-
-int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md,
- unsigned int *len)
- {
- return(ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME),type,(char *)data,md,len));
- }
+ unsigned int *len)
+{
+ return (ASN1_item_digest
+ (ASN1_ITEM_rptr(X509), type, (char *)data, md, len));
+}
+
+int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+{
+ return (ASN1_item_digest
+ (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len));
+}
+
+int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+{
+ return (ASN1_item_digest
+ (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len));
+}
+
+int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+{
+ return (ASN1_item_digest
+ (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len));
+}
#ifndef OPENSSL_NO_FP_API
X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
- {
- return ASN1_d2i_fp_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,fp,p8);
- }
+{
+ return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
+}
int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
- {
- return ASN1_i2d_fp_of(X509_SIG,i2d_X509_SIG,fp,p8);
- }
+{
+ return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
+}
#endif
X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
- {
- return ASN1_d2i_bio_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,bp,p8);
- }
+{
+ return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
+}
int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
- {
- return ASN1_i2d_bio_of(X509_SIG,i2d_X509_SIG,bp,p8);
- }
+{
+ return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
+}
#ifndef OPENSSL_NO_FP_API
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
- PKCS8_PRIV_KEY_INFO **p8inf)
- {
- return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
- d2i_PKCS8_PRIV_KEY_INFO,fp,p8inf);
- }
+ PKCS8_PRIV_KEY_INFO **p8inf)
+{
+ return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
+}
int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
- {
- return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,fp,
- p8inf);
- }
+{
+ return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
+ p8inf);
+}
int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
- {
- PKCS8_PRIV_KEY_INFO *p8inf;
- int ret;
- p8inf = EVP_PKEY2PKCS8(key);
- if(!p8inf) return 0;
- ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- return ret;
- }
+{
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ int ret;
+ p8inf = EVP_PKEY2PKCS8(key);
+ if (!p8inf)
+ return 0;
+ ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+}
int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
- {
- return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PrivateKey,fp,pkey);
- }
+{
+ return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey);
+}
EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
{
- return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,fp,a);
+ return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
}
int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
- {
- return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PUBKEY,fp,pkey);
- }
+{
+ return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey);
+}
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
{
- return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,fp,a);
+ return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
}
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
- PKCS8_PRIV_KEY_INFO **p8inf)
- {
- return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
- d2i_PKCS8_PRIV_KEY_INFO,bp,p8inf);
- }
+ PKCS8_PRIV_KEY_INFO **p8inf)
+{
+ return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
+}
int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
- {
- return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,bp,
- p8inf);
- }
+{
+ return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
+ p8inf);
+}
int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
- {
- PKCS8_PRIV_KEY_INFO *p8inf;
- int ret;
- p8inf = EVP_PKEY2PKCS8(key);
- if(!p8inf) return 0;
- ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- return ret;
- }
+{
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ int ret;
+ p8inf = EVP_PKEY2PKCS8(key);
+ if (!p8inf)
+ return 0;
+ ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+}
#endif
int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
- {
- return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PrivateKey,bp,pkey);
- }
+{
+ return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey);
+}
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
- {
- return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,bp,a);
- }
+{
+ return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
+}
int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
- {
- return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PUBKEY,bp,pkey);
- }
+{
+ return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey);
+}
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
- {
- return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,bp,a);
- }
+{
+ return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
+}
diff --git a/src/crypto/x509/x_attrib.c b/src/crypto/x509/x_attrib.c
index c460a702..de8c95cc 100644
--- a/src/crypto/x509/x_attrib.c
+++ b/src/crypto/x509/x_attrib.c
@@ -59,59 +59,53 @@
#include <openssl/x509.h>
#include <openssl/obj.h>
-
-/* X509_ATTRIBUTE: this has the following form:
- *
- * typedef struct x509_attributes_st
- * {
- * ASN1_OBJECT *object;
- * int single;
- * union {
- * char *ptr;
- * STACK_OF(ASN1_TYPE) *set;
- * ASN1_TYPE *single;
- * } value;
- * } X509_ATTRIBUTE;
- *
- * this needs some extra thought because the CHOICE type is
- * merged with the main structure and because the value can
- * be anything at all we *must* try the SET OF first because
- * the ASN1_ANY type will swallow anything including the whole
- * SET OF structure.
+/*
+ * X509_ATTRIBUTE: this has the following form: typedef struct
+ * x509_attributes_st { ASN1_OBJECT *object; int single; union { char *ptr;
+ * STACK_OF(ASN1_TYPE) *set; ASN1_TYPE *single; } value; } X509_ATTRIBUTE;
+ * this needs some extra thought because the CHOICE type is merged with the
+ * main structure and because the value can be anything at all we *must* try
+ * the SET OF first because the ASN1_ANY type will swallow anything including
+ * the whole SET OF structure.
*/
ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
- ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
- ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
+ ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
+ ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
ASN1_SEQUENCE(X509_ATTRIBUTE) = {
- ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
- /* CHOICE type merged with parent */
- ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
+ ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
+ /* CHOICE type merged with parent */
+ ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
- {
- X509_ATTRIBUTE *ret=NULL;
- ASN1_TYPE *val=NULL;
+{
+ X509_ATTRIBUTE *ret = NULL;
+ ASN1_TYPE *val = NULL;
- if ((ret=X509_ATTRIBUTE_new()) == NULL)
- return(NULL);
- /* TODO(fork): const correctness. */
- ret->object=(ASN1_OBJECT*) OBJ_nid2obj(nid);
- ret->single=0;
- if ((ret->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err;
- if ((val=ASN1_TYPE_new()) == NULL) goto err;
- if (!sk_ASN1_TYPE_push(ret->value.set,val)) goto err;
+ if ((ret = X509_ATTRIBUTE_new()) == NULL)
+ return (NULL);
+ /* TODO(fork): const correctness. */
+ ret->object = (ASN1_OBJECT *)OBJ_nid2obj(nid);
+ ret->single = 0;
+ if ((ret->value.set = sk_ASN1_TYPE_new_null()) == NULL)
+ goto err;
+ if ((val = ASN1_TYPE_new()) == NULL)
+ goto err;
+ if (!sk_ASN1_TYPE_push(ret->value.set, val))
+ goto err;
- ASN1_TYPE_set(val,atrtype,value);
- return(ret);
-err:
- if (ret != NULL) X509_ATTRIBUTE_free(ret);
- if (val != NULL) ASN1_TYPE_free(val);
- return(NULL);
- }
+ ASN1_TYPE_set(val, atrtype, value);
+ return (ret);
+ err:
+ if (ret != NULL)
+ X509_ATTRIBUTE_free(ret);
+ if (val != NULL)
+ ASN1_TYPE_free(val);
+ return (NULL);
+}
diff --git a/src/crypto/x509/x_crl.c b/src/crypto/x509/x_crl.c
index d5168727..cd648901 100644
--- a/src/crypto/x509/x_crl.c
+++ b/src/crypto/x509/x_crl.c
@@ -67,494 +67,473 @@
#include "../internal.h"
-
-/* Method to handle CRL access.
- * In general a CRL could be very large (several Mb) and can consume large
- * amounts of resources if stored in memory by multiple processes.
- * This method allows general CRL operations to be redirected to more
- * efficient callbacks: for example a CRL entry database.
+/*
+ * Method to handle CRL access. In general a CRL could be very large (several
+ * Mb) and can consume large amounts of resources if stored in memory by
+ * multiple processes. This method allows general CRL operations to be
+ * redirected to more efficient callbacks: for example a CRL entry database.
*/
-#define X509_CRL_METHOD_DYNAMIC 1
+#define X509_CRL_METHOD_DYNAMIC 1
-struct x509_crl_method_st
- {
- int flags;
- int (*crl_init)(X509_CRL *crl);
- int (*crl_free)(X509_CRL *crl);
- int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
- ASN1_INTEGER *ser, X509_NAME *issuer);
- int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
- };
+struct x509_crl_method_st {
+ int flags;
+ int (*crl_init) (X509_CRL *crl);
+ int (*crl_free) (X509_CRL *crl);
+ int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
+ ASN1_INTEGER *ser, X509_NAME *issuer);
+ int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
+};
-static int X509_REVOKED_cmp(const X509_REVOKED **a,
- const X509_REVOKED **b);
+static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b);
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
ASN1_SEQUENCE(X509_REVOKED) = {
- ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
- ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
- ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
+ ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
} ASN1_SEQUENCE_END(X509_REVOKED)
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
static int def_crl_lookup(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer);
+ X509_REVOKED **ret, ASN1_INTEGER *serial,
+ X509_NAME *issuer);
-static const X509_CRL_METHOD int_crl_meth =
- {
- 0,
- 0,0,
- def_crl_lookup,
- def_crl_verify
- };
+static const X509_CRL_METHOD int_crl_meth = {
+ 0,
+ 0, 0,
+ def_crl_lookup,
+ def_crl_verify
+};
static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
-/* The X509_CRL_INFO structure needs a bit of customisation.
- * Since we cache the original encoding the signature wont be affected by
- * reordering of the revoked field.
+/*
+ * The X509_CRL_INFO structure needs a bit of customisation. Since we cache
+ * the original encoding the signature wont be affected by reordering of the
+ * revoked field.
*/
static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
+ void *exarg)
{
- X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
-
- if(!a || !a->revoked) return 1;
- switch(operation) {
- /* Just set cmp function here. We don't sort because that
- * would affect the output of X509_CRL_print().
- */
- case ASN1_OP_D2I_POST:
- (void)sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
- break;
- }
- return 1;
+ X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
+
+ if (!a || !a->revoked)
+ return 1;
+ switch (operation) {
+ /*
+ * Just set cmp function here. We don't sort because that would
+ * affect the output of X509_CRL_print().
+ */
+ case ASN1_OP_D2I_POST:
+ (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
+ break;
+ }
+ return 1;
}
ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
- ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
- ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
- ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
- ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
- ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
- ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
- ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
+ ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
+ ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
-/* Set CRL entry issuer according to CRL certificate issuer extension.
- * Check for unhandled critical CRL entry extensions.
+/*
+ * Set CRL entry issuer according to CRL certificate issuer extension. Check
+ * for unhandled critical CRL entry extensions.
*/
static int crl_set_issuers(X509_CRL *crl)
- {
-
- size_t i, k;
- int j;
- GENERAL_NAMES *gens, *gtmp;
- STACK_OF(X509_REVOKED) *revoked;
-
- revoked = X509_CRL_get_REVOKED(crl);
-
- gens = NULL;
- for (i = 0; i < sk_X509_REVOKED_num(revoked); i++)
- {
- X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
- STACK_OF(X509_EXTENSION) *exts;
- ASN1_ENUMERATED *reason;
- X509_EXTENSION *ext;
- gtmp = X509_REVOKED_get_ext_d2i(rev,
- NID_certificate_issuer,
- &j, NULL);
- if (!gtmp && (j != -1))
- {
- crl->flags |= EXFLAG_INVALID;
- return 1;
- }
-
- if (gtmp)
- {
- gens = gtmp;
- if (!crl->issuers)
- {
- crl->issuers = sk_GENERAL_NAMES_new_null();
- if (!crl->issuers)
- return 0;
- }
- if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
- return 0;
- }
- rev->issuer = gens;
-
- reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
- &j, NULL);
- if (!reason && (j != -1))
- {
- crl->flags |= EXFLAG_INVALID;
- return 1;
- }
-
- if (reason)
- {
- rev->reason = ASN1_ENUMERATED_get(reason);
- ASN1_ENUMERATED_free(reason);
- }
- else
- rev->reason = CRL_REASON_NONE;
-
- /* Check for critical CRL entry extensions */
-
- exts = rev->extensions;
-
- for (k = 0; k < sk_X509_EXTENSION_num(exts); k++)
- {
- ext = sk_X509_EXTENSION_value(exts, k);
- if (ext->critical > 0)
- {
- if (OBJ_obj2nid(ext->object) ==
- NID_certificate_issuer)
- continue;
- crl->flags |= EXFLAG_CRITICAL;
- break;
- }
- }
-
-
- }
-
- return 1;
-
- }
-
-/* The X509_CRL structure needs a bit of customisation. Cache some extensions
+{
+
+ size_t i, k;
+ int j;
+ GENERAL_NAMES *gens, *gtmp;
+ STACK_OF(X509_REVOKED) *revoked;
+
+ revoked = X509_CRL_get_REVOKED(crl);
+
+ gens = NULL;
+ for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
+ X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
+ STACK_OF(X509_EXTENSION) *exts;
+ ASN1_ENUMERATED *reason;
+ X509_EXTENSION *ext;
+ gtmp = X509_REVOKED_get_ext_d2i(rev,
+ NID_certificate_issuer, &j, NULL);
+ if (!gtmp && (j != -1)) {
+ crl->flags |= EXFLAG_INVALID;
+ return 1;
+ }
+
+ if (gtmp) {
+ gens = gtmp;
+ if (!crl->issuers) {
+ crl->issuers = sk_GENERAL_NAMES_new_null();
+ if (!crl->issuers)
+ return 0;
+ }
+ if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
+ return 0;
+ }
+ rev->issuer = gens;
+
+ reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL);
+ if (!reason && (j != -1)) {
+ crl->flags |= EXFLAG_INVALID;
+ return 1;
+ }
+
+ if (reason) {
+ rev->reason = ASN1_ENUMERATED_get(reason);
+ ASN1_ENUMERATED_free(reason);
+ } else
+ rev->reason = CRL_REASON_NONE;
+
+ /* Check for critical CRL entry extensions */
+
+ exts = rev->extensions;
+
+ for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) {
+ ext = sk_X509_EXTENSION_value(exts, k);
+ if (ext->critical > 0) {
+ if (OBJ_obj2nid(ext->object) == NID_certificate_issuer)
+ continue;
+ crl->flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
+
+ }
+
+ return 1;
+
+}
+
+/*
+ * The X509_CRL structure needs a bit of customisation. Cache some extensions
* and hash of the whole CRL.
*/
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
- {
- X509_CRL *crl = (X509_CRL *)*pval;
- STACK_OF(X509_EXTENSION) *exts;
- X509_EXTENSION *ext;
- size_t idx;
-
- switch(operation)
- {
- case ASN1_OP_NEW_POST:
- crl->idp = NULL;
- crl->akid = NULL;
- crl->flags = 0;
- crl->idp_flags = 0;
- crl->idp_reasons = CRLDP_ALL_REASONS;
- crl->meth = default_crl_method;
- crl->meth_data = NULL;
- crl->issuers = NULL;
- crl->crl_number = NULL;
- crl->base_crl_number = NULL;
- break;
-
- case ASN1_OP_D2I_POST:
- X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
- crl->idp = X509_CRL_get_ext_d2i(crl,
- NID_issuing_distribution_point, NULL, NULL);
- if (crl->idp)
- setup_idp(crl, crl->idp);
-
- crl->akid = X509_CRL_get_ext_d2i(crl,
- NID_authority_key_identifier, NULL, NULL);
-
- crl->crl_number = X509_CRL_get_ext_d2i(crl,
- NID_crl_number, NULL, NULL);
-
- crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
- NID_delta_crl, NULL, NULL);
- /* Delta CRLs must have CRL number */
- if (crl->base_crl_number && !crl->crl_number)
- crl->flags |= EXFLAG_INVALID;
-
- /* See if we have any unhandled critical CRL extensions and
- * indicate this in a flag. We only currently handle IDP so
- * anything else critical sets the flag.
- *
- * This code accesses the X509_CRL structure directly:
- * applications shouldn't do this.
- */
-
- exts = crl->crl->extensions;
-
- for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
- {
- int nid;
- ext = sk_X509_EXTENSION_value(exts, idx);
- nid = OBJ_obj2nid(ext->object);
- if (nid == NID_freshest_crl)
- crl->flags |= EXFLAG_FRESHEST;
- if (ext->critical > 0)
- {
- /* We handle IDP and deltas */
- if ((nid == NID_issuing_distribution_point)
- || (nid == NID_authority_key_identifier)
- || (nid == NID_delta_crl))
- break;;
- crl->flags |= EXFLAG_CRITICAL;
- break;
- }
- }
-
-
- if (!crl_set_issuers(crl))
- return 0;
-
- if (crl->meth->crl_init)
- {
- if (crl->meth->crl_init(crl) == 0)
- return 0;
- }
- break;
-
- case ASN1_OP_FREE_POST:
- if (crl->meth->crl_free)
- {
- if (!crl->meth->crl_free(crl))
- return 0;
- }
- if (crl->akid)
- AUTHORITY_KEYID_free(crl->akid);
- if (crl->idp)
- ISSUING_DIST_POINT_free(crl->idp);
- ASN1_INTEGER_free(crl->crl_number);
- ASN1_INTEGER_free(crl->base_crl_number);
- sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
- break;
- }
- return 1;
- }
+ void *exarg)
+{
+ X509_CRL *crl = (X509_CRL *)*pval;
+ STACK_OF(X509_EXTENSION) *exts;
+ X509_EXTENSION *ext;
+ size_t idx;
+
+ switch (operation) {
+ case ASN1_OP_NEW_POST:
+ crl->idp = NULL;
+ crl->akid = NULL;
+ crl->flags = 0;
+ crl->idp_flags = 0;
+ crl->idp_reasons = CRLDP_ALL_REASONS;
+ crl->meth = default_crl_method;
+ crl->meth_data = NULL;
+ crl->issuers = NULL;
+ crl->crl_number = NULL;
+ crl->base_crl_number = NULL;
+ break;
+
+ case ASN1_OP_D2I_POST:
+ X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
+ crl->idp = X509_CRL_get_ext_d2i(crl,
+ NID_issuing_distribution_point, NULL,
+ NULL);
+ if (crl->idp)
+ setup_idp(crl, crl->idp);
+
+ crl->akid = X509_CRL_get_ext_d2i(crl,
+ NID_authority_key_identifier, NULL,
+ NULL);
+
+ crl->crl_number = X509_CRL_get_ext_d2i(crl,
+ NID_crl_number, NULL, NULL);
+
+ crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
+ NID_delta_crl, NULL,
+ NULL);
+ /* Delta CRLs must have CRL number */
+ if (crl->base_crl_number && !crl->crl_number)
+ crl->flags |= EXFLAG_INVALID;
+
+ /*
+ * See if we have any unhandled critical CRL extensions and indicate
+ * this in a flag. We only currently handle IDP so anything else
+ * critical sets the flag. This code accesses the X509_CRL structure
+ * directly: applications shouldn't do this.
+ */
+
+ exts = crl->crl->extensions;
+
+ for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
+ int nid;
+ ext = sk_X509_EXTENSION_value(exts, idx);
+ nid = OBJ_obj2nid(ext->object);
+ if (nid == NID_freshest_crl)
+ crl->flags |= EXFLAG_FRESHEST;
+ if (ext->critical > 0) {
+ /* We handle IDP and deltas */
+ if ((nid == NID_issuing_distribution_point)
+ || (nid == NID_authority_key_identifier)
+ || (nid == NID_delta_crl))
+ break;;
+ crl->flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
+
+ if (!crl_set_issuers(crl))
+ return 0;
+
+ if (crl->meth->crl_init) {
+ if (crl->meth->crl_init(crl) == 0)
+ return 0;
+ }
+ break;
+
+ case ASN1_OP_FREE_POST:
+ if (crl->meth->crl_free) {
+ if (!crl->meth->crl_free(crl))
+ return 0;
+ }
+ if (crl->akid)
+ AUTHORITY_KEYID_free(crl->akid);
+ if (crl->idp)
+ ISSUING_DIST_POINT_free(crl->idp);
+ ASN1_INTEGER_free(crl->crl_number);
+ ASN1_INTEGER_free(crl->base_crl_number);
+ sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
+ break;
+ }
+ return 1;
+}
/* Convert IDP into a more convenient form */
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
- {
- int idp_only = 0;
- /* Set various flags according to IDP */
- crl->idp_flags |= IDP_PRESENT;
- if (idp->onlyuser > 0)
- {
- idp_only++;
- crl->idp_flags |= IDP_ONLYUSER;
- }
- if (idp->onlyCA > 0)
- {
- idp_only++;
- crl->idp_flags |= IDP_ONLYCA;
- }
- if (idp->onlyattr > 0)
- {
- idp_only++;
- crl->idp_flags |= IDP_ONLYATTR;
- }
-
- if (idp_only > 1)
- crl->idp_flags |= IDP_INVALID;
-
- if (idp->indirectCRL > 0)
- crl->idp_flags |= IDP_INDIRECT;
-
- if (idp->onlysomereasons)
- {
- crl->idp_flags |= IDP_REASONS;
- if (idp->onlysomereasons->length > 0)
- crl->idp_reasons = idp->onlysomereasons->data[0];
- if (idp->onlysomereasons->length > 1)
- crl->idp_reasons |=
- (idp->onlysomereasons->data[1] << 8);
- crl->idp_reasons &= CRLDP_ALL_REASONS;
- }
-
- DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
- }
+{
+ int idp_only = 0;
+ /* Set various flags according to IDP */
+ crl->idp_flags |= IDP_PRESENT;
+ if (idp->onlyuser > 0) {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYUSER;
+ }
+ if (idp->onlyCA > 0) {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYCA;
+ }
+ if (idp->onlyattr > 0) {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYATTR;
+ }
+
+ if (idp_only > 1)
+ crl->idp_flags |= IDP_INVALID;
+
+ if (idp->indirectCRL > 0)
+ crl->idp_flags |= IDP_INDIRECT;
+
+ if (idp->onlysomereasons) {
+ crl->idp_flags |= IDP_REASONS;
+ if (idp->onlysomereasons->length > 0)
+ crl->idp_reasons = idp->onlysomereasons->data[0];
+ if (idp->onlysomereasons->length > 1)
+ crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8);
+ crl->idp_reasons &= CRLDP_ALL_REASONS;
+ }
+
+ DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
+}
ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
- ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
- ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
- ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
+ ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
+ ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
+
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
+
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
-static int X509_REVOKED_cmp(const X509_REVOKED **a,
- const X509_REVOKED **b)
- {
- return(ASN1_STRING_cmp(
- (ASN1_STRING *)(*a)->serialNumber,
- (ASN1_STRING *)(*b)->serialNumber));
- }
+static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b)
+{
+ return (ASN1_STRING_cmp((ASN1_STRING *)(*a)->serialNumber,
+ (ASN1_STRING *)(*b)->serialNumber));
+}
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
{
- X509_CRL_INFO *inf;
- inf = crl->crl;
- if(!inf->revoked)
- inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
- if(!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- inf->enc.modified = 1;
- return 1;
+ X509_CRL_INFO *inf;
+ inf = crl->crl;
+ if (!inf->revoked)
+ inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
+ if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ inf->enc.modified = 1;
+ return 1;
}
int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
- {
- if (crl->meth->crl_verify)
- return crl->meth->crl_verify(crl, r);
- return 0;
- }
+{
+ if (crl->meth->crl_verify)
+ return crl->meth->crl_verify(crl, r);
+ return 0;
+}
int X509_CRL_get0_by_serial(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial)
- {
- if (crl->meth->crl_lookup)
- return crl->meth->crl_lookup(crl, ret, serial, NULL);
- return 0;
- }
+ X509_REVOKED **ret, ASN1_INTEGER *serial)
+{
+ if (crl->meth->crl_lookup)
+ return crl->meth->crl_lookup(crl, ret, serial, NULL);
+ return 0;
+}
int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
- {
- if (crl->meth->crl_lookup)
- return crl->meth->crl_lookup(crl, ret,
- X509_get_serialNumber(x),
- X509_get_issuer_name(x));
- return 0;
- }
+{
+ if (crl->meth->crl_lookup)
+ return crl->meth->crl_lookup(crl, ret,
+ X509_get_serialNumber(x),
+ X509_get_issuer_name(x));
+ return 0;
+}
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
- {
- return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
- crl->sig_alg, crl->signature,crl->crl,r));
- }
+{
+ return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
+ crl->sig_alg, crl->signature, crl->crl, r));
+}
static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
- X509_REVOKED *rev)
- {
- size_t i;
-
- if (!rev->issuer)
- {
- if (!nm)
- return 1;
- if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
- return 1;
- return 0;
- }
-
- if (!nm)
- nm = X509_CRL_get_issuer(crl);
-
- for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++)
- {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
- if (gen->type != GEN_DIRNAME)
- continue;
- if (!X509_NAME_cmp(nm, gen->d.directoryName))
- return 1;
- }
- return 0;
-
- }
+ X509_REVOKED *rev)
+{
+ size_t i;
+
+ if (!rev->issuer) {
+ if (!nm)
+ return 1;
+ if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
+ return 1;
+ return 0;
+ }
+
+ if (!nm)
+ nm = X509_CRL_get_issuer(crl);
+
+ for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
+ if (gen->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(nm, gen->d.directoryName))
+ return 1;
+ }
+ return 0;
+
+}
static struct CRYPTO_STATIC_MUTEX g_crl_sort_lock = CRYPTO_STATIC_MUTEX_INIT;
static int def_crl_lookup(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer)
- {
- X509_REVOKED rtmp, *rev;
- size_t idx;
- rtmp.serialNumber = serial;
- /* Sort revoked into serial number order if not already sorted.
- * Do this under a lock to avoid race condition.
- */
-
- CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
- const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
- CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
-
- if (!is_sorted)
- {
- CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
- if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
- {
- sk_X509_REVOKED_sort(crl->crl->revoked);
- }
- CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
- }
-
- if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
- return 0;
- /* Need to look for matching name */
- for(;idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++)
- {
- rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
- if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
- return 0;
- if (crl_revoked_issuer_match(crl, issuer, rev))
- {
- if (ret)
- *ret = rev;
- if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
- return 2;
- return 1;
- }
- }
- return 0;
- }
+ X509_REVOKED **ret, ASN1_INTEGER *serial,
+ X509_NAME *issuer)
+{
+ X509_REVOKED rtmp, *rev;
+ size_t idx;
+ rtmp.serialNumber = serial;
+ /*
+ * Sort revoked into serial number order if not already sorted. Do this
+ * under a lock to avoid race condition.
+ */
+
+ CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
+ const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
+ CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+
+ if (!is_sorted) {
+ CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
+ if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
+ sk_X509_REVOKED_sort(crl->crl->revoked);
+ }
+ CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+ }
+
+ if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
+ return 0;
+ /* Need to look for matching name */
+ for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
+ rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
+ if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
+ return 0;
+ if (crl_revoked_issuer_match(crl, issuer, rev)) {
+ if (ret)
+ *ret = rev;
+ if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+ return 2;
+ return 1;
+ }
+ }
+ return 0;
+}
void X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
- {
- if (meth == NULL)
- default_crl_method = &int_crl_meth;
- else
- default_crl_method = meth;
- }
-
-X509_CRL_METHOD *X509_CRL_METHOD_new(
- int (*crl_init)(X509_CRL *crl),
- int (*crl_free)(X509_CRL *crl),
- int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
- ASN1_INTEGER *ser, X509_NAME *issuer),
- int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk))
- {
- X509_CRL_METHOD *m;
- m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
- if (!m)
- return NULL;
- m->crl_init = crl_init;
- m->crl_free = crl_free;
- m->crl_lookup = crl_lookup;
- m->crl_verify = crl_verify;
- m->flags = X509_CRL_METHOD_DYNAMIC;
- return m;
- }
+{
+ if (meth == NULL)
+ default_crl_method = &int_crl_meth;
+ else
+ default_crl_method = meth;
+}
+
+X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
+ int (*crl_free) (X509_CRL *crl),
+ int (*crl_lookup) (X509_CRL *crl,
+ X509_REVOKED **ret,
+ ASN1_INTEGER *ser,
+ X509_NAME *issuer),
+ int (*crl_verify) (X509_CRL *crl,
+ EVP_PKEY *pk))
+{
+ X509_CRL_METHOD *m;
+ m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
+ if (!m)
+ return NULL;
+ m->crl_init = crl_init;
+ m->crl_free = crl_free;
+ m->crl_lookup = crl_lookup;
+ m->crl_verify = crl_verify;
+ m->flags = X509_CRL_METHOD_DYNAMIC;
+ return m;
+}
void X509_CRL_METHOD_free(X509_CRL_METHOD *m)
- {
- if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
- return;
- OPENSSL_free(m);
- }
+{
+ if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
+ return;
+ OPENSSL_free(m);
+}
void X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
- {
- crl->meth_data = dat;
- }
+{
+ crl->meth_data = dat;
+}
void *X509_CRL_get_meth_data(X509_CRL *crl)
- {
- return crl->meth_data;
- }
+{
+ return crl->meth_data;
+}
IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
+
IMPLEMENT_ASN1_SET_OF(X509_CRL)
diff --git a/src/crypto/x509/x_exten.c b/src/crypto/x509/x_exten.c
index cf64c844..36403e48 100644
--- a/src/crypto/x509/x_exten.c
+++ b/src/crypto/x509/x_exten.c
@@ -61,13 +61,13 @@
ASN1_SEQUENCE(X509_EXTENSION) = {
- ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
- ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
- ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
+ ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
+ ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
+ 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(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)
diff --git a/src/crypto/x509/x_info.c b/src/crypto/x509/x_info.c
index be579d79..177cd0eb 100644
--- a/src/crypto/x509/x_info.c
+++ b/src/crypto/x509/x_info.c
@@ -61,35 +61,38 @@
#include <openssl/mem.h>
#include <openssl/thread.h>
-
X509_INFO *X509_INFO_new(void)
- {
- X509_INFO *ret=NULL;
+{
+ X509_INFO *ret = NULL;
+
+ ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return (NULL);
+ }
+
+ ret->enc_cipher.cipher = NULL;
+ ret->enc_len = 0;
+ ret->enc_data = NULL;
- ret=(X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return(NULL);
- }
-
- ret->enc_cipher.cipher=NULL;
- ret->enc_len=0;
- ret->enc_data=NULL;
-
- ret->x509=NULL;
- ret->crl=NULL;
- ret->x_pkey=NULL;
- return(ret);
- }
+ ret->x509 = NULL;
+ ret->crl = NULL;
+ ret->x_pkey = NULL;
+ return (ret);
+}
void X509_INFO_free(X509_INFO *x)
- {
- if (x == NULL) return;
+{
+ if (x == NULL)
+ return;
- if (x->x509 != NULL) X509_free(x->x509);
- if (x->crl != NULL) X509_CRL_free(x->crl);
- if (x->x_pkey != NULL) X509_PKEY_free(x->x_pkey);
- if (x->enc_data != NULL) OPENSSL_free(x->enc_data);
- OPENSSL_free(x);
- }
+ if (x->x509 != NULL)
+ X509_free(x->x509);
+ if (x->crl != NULL)
+ X509_CRL_free(x->crl);
+ if (x->x_pkey != NULL)
+ X509_PKEY_free(x->x_pkey);
+ if (x->enc_data != NULL)
+ OPENSSL_free(x->enc_data);
+ OPENSSL_free(x);
+}
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
index a1dcd167..226e76dc 100644
--- a/src/crypto/x509/x_name.c
+++ b/src/crypto/x509/x_name.c
@@ -68,471 +68,470 @@
#include "../asn1/asn1_locl.h"
-
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
static int x509_name_ex_d2i(ASN1_VALUE **val,
- const unsigned char **in, long len,
- const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx);
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
- const ASN1_ITEM *it, int tag, int aclass);
+ const ASN1_ITEM *it, int tag, int aclass);
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
static int x509_name_encode(X509_NAME *a);
static int x509_name_canon(X509_NAME *a);
static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
- unsigned char **in);
-
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
+ unsigned char **in);
static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
- int indent,
- const char *fname,
- const ASN1_PCTX *pctx);
+ int indent,
+ const char *fname, const ASN1_PCTX *pctx);
ASN1_SEQUENCE(X509_NAME_ENTRY) = {
- ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
- ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
+ ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
+ ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
} ASN1_SEQUENCE_END(X509_NAME_ENTRY)
IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
-/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
- * so declare two template wrappers for this
+/*
+ * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
+ * declare two template wrappers for this
*/
ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES)
ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
-/* Normally that's where it would end: we'd have two nested STACK structures
+/*
+ * Normally that's where it would end: we'd have two nested STACK structures
* representing the ASN1. Unfortunately X509_NAME uses a completely different
- * form and caches encodings so we have to process the internal form and convert
- * to the external form.
+ * form and caches encodings so we have to process the internal form and
+ * convert to the external form.
*/
static const ASN1_EXTERN_FUNCS x509_name_ff = {
- NULL,
- x509_name_ex_new,
- x509_name_ex_free,
- 0, /* Default clear behaviour is OK */
- x509_name_ex_d2i,
- x509_name_ex_i2d,
- x509_name_ex_print
+ NULL,
+ x509_name_ex_new,
+ x509_name_ex_free,
+ 0, /* Default clear behaviour is OK */
+ x509_name_ex_d2i,
+ x509_name_ex_i2d,
+ x509_name_ex_print
};
-IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
+IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
IMPLEMENT_ASN1_FUNCTIONS(X509_NAME)
+
IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME)
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
{
- X509_NAME *ret = NULL;
- ret = OPENSSL_malloc(sizeof(X509_NAME));
- if(!ret) goto memerr;
- if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL)
- goto memerr;
- if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr;
- ret->canon_enc = NULL;
- ret->canon_enclen = 0;
- ret->modified=1;
- *val = (ASN1_VALUE *)ret;
- return 1;
+ X509_NAME *ret = NULL;
+ ret = OPENSSL_malloc(sizeof(X509_NAME));
+ if (!ret)
+ goto memerr;
+ if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
+ goto memerr;
+ if ((ret->bytes = BUF_MEM_new()) == NULL)
+ goto memerr;
+ ret->canon_enc = NULL;
+ ret->canon_enclen = 0;
+ ret->modified = 1;
+ *val = (ASN1_VALUE *)ret;
+ return 1;
memerr:
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- if (ret)
- {
- if (ret->entries)
- sk_X509_NAME_ENTRY_free(ret->entries);
- OPENSSL_free(ret);
- }
- return 0;
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ if (ret) {
+ if (ret->entries)
+ sk_X509_NAME_ENTRY_free(ret->entries);
+ OPENSSL_free(ret);
+ }
+ return 0;
}
static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- X509_NAME *a;
- if(!pval || !*pval)
- return;
- a = (X509_NAME *)*pval;
-
- BUF_MEM_free(a->bytes);
- sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free);
- if (a->canon_enc)
- OPENSSL_free(a->canon_enc);
- OPENSSL_free(a);
- *pval = NULL;
+ X509_NAME *a;
+ if (!pval || !*pval)
+ return;
+ a = (X509_NAME *)*pval;
+
+ BUF_MEM_free(a->bytes);
+ sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
+ if (a->canon_enc)
+ OPENSSL_free(a->canon_enc);
+ OPENSSL_free(a);
+ *pval = NULL;
}
static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
- sk_X509_NAME_ENTRY_free(ne);
+ sk_X509_NAME_ENTRY_free(ne);
}
static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
- sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+ sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
}
static int x509_name_ex_d2i(ASN1_VALUE **val,
- const unsigned char **in, long len, const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx)
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass,
+ char opt, ASN1_TLC *ctx)
{
- const unsigned char *p = *in, *q;
- union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
- ASN1_VALUE *a; } intname = {NULL};
- union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL};
- size_t i, j;
- int ret;
- STACK_OF(X509_NAME_ENTRY) *entries;
- X509_NAME_ENTRY *entry;
- q = p;
-
- /* Get internal representation of Name */
- 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);
- /* We've decoded it: now cache encoding */
- if (!x509_name_ex_new(&nm.a, NULL) ||
- !BUF_MEM_grow(nm.x->bytes, p - q))
- {
- sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
- local_sk_X509_NAME_ENTRY_pop_free);
- goto err;
- }
- memcpy(nm.x->bytes->data, q, p - q);
-
- /* Convert internal representation to X509_NAME structure */
- for(i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
- entries = sk_STACK_OF_X509_NAME_ENTRY_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.x->entries, entry))
- goto err;
- }
- sk_X509_NAME_ENTRY_free(entries);
- }
- sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
- ret = x509_name_canon(nm.x);
- if (!ret)
- goto err;
- nm.x->modified = 0;
- *val = nm.a;
- *in = p;
- return ret;
-err:
- if (nm.x != NULL)
- X509_NAME_free(nm.x);
- OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
- return 0;
+ const unsigned char *p = *in, *q;
+ union {
+ STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+ ASN1_VALUE *a;
+ } intname = {
+ NULL
+ };
+ union {
+ X509_NAME *x;
+ ASN1_VALUE *a;
+ } nm = {
+ NULL
+ };
+ size_t i, j;
+ int ret;
+ STACK_OF(X509_NAME_ENTRY) *entries;
+ X509_NAME_ENTRY *entry;
+ q = p;
+
+ /* Get internal representation of Name */
+ 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);
+ /* We've decoded it: now cache encoding */
+ if (!x509_name_ex_new(&nm.a, NULL) || !BUF_MEM_grow(nm.x->bytes, p - q)) {
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_pop_free);
+ goto err;
+ }
+ memcpy(nm.x->bytes->data, q, p - q);
+
+ /* Convert internal representation to X509_NAME structure */
+ for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
+ entries = sk_STACK_OF_X509_NAME_ENTRY_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.x->entries, entry))
+ goto err;
+ }
+ sk_X509_NAME_ENTRY_free(entries);
+ }
+ sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
+ ret = x509_name_canon(nm.x);
+ if (!ret)
+ goto err;
+ nm.x->modified = 0;
+ *val = nm.a;
+ *in = p;
+ return ret;
+ err:
+ if (nm.x != NULL)
+ X509_NAME_free(nm.x);
+ OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+ return 0;
}
-static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
+static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass)
{
- int ret;
- X509_NAME *a = (X509_NAME *)*val;
- if(a->modified) {
- ret = x509_name_encode(a);
- if(ret < 0)
- return ret;
- ret = x509_name_canon(a);
- if(ret < 0)
- return ret;
- }
- ret = a->bytes->length;
- if(out != NULL) {
- memcpy(*out,a->bytes->data,ret);
- *out+=ret;
- }
- return ret;
+ int ret;
+ X509_NAME *a = (X509_NAME *)*val;
+ if (a->modified) {
+ ret = x509_name_encode(a);
+ if (ret < 0)
+ return ret;
+ ret = x509_name_canon(a);
+ if (ret < 0)
+ return ret;
+ }
+ ret = a->bytes->length;
+ if (out != NULL) {
+ memcpy(*out, a->bytes->data, ret);
+ *out += ret;
+ }
+ return ret;
}
static int x509_name_encode(X509_NAME *a)
{
- union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
- ASN1_VALUE *a; } intname = {NULL};
- int len;
- unsigned char *p;
- STACK_OF(X509_NAME_ENTRY) *entries = NULL;
- X509_NAME_ENTRY *entry;
- int set = -1;
- size_t i;
- intname.s = sk_STACK_OF_X509_NAME_ENTRY_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_STACK_OF_X509_NAME_ENTRY_push(intname.s,
- entries))
- goto memerr;
- set = entry->set;
- }
- if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr;
- }
- 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(&intname.a,
- &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
- sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
- local_sk_X509_NAME_ENTRY_free);
- a->modified = 0;
- return len;
-memerr:
- sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
- local_sk_X509_NAME_ENTRY_free);
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return -1;
+ union {
+ STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+ ASN1_VALUE *a;
+ } intname = {
+ NULL
+ };
+ int len;
+ unsigned char *p;
+ STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+ X509_NAME_ENTRY *entry;
+ int set = -1;
+ size_t i;
+ intname.s = sk_STACK_OF_X509_NAME_ENTRY_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_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries))
+ goto memerr;
+ set = entry->set;
+ }
+ if (!sk_X509_NAME_ENTRY_push(entries, entry))
+ goto memerr;
+ }
+ 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(&intname.a,
+ &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_free);
+ a->modified = 0;
+ return len;
+ memerr:
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_free);
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return -1;
}
static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
- int indent,
- const char *fname,
- const ASN1_PCTX *pctx)
- {
- if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
- indent, pctx->nm_flags) <= 0)
- return 0;
- return 2;
- }
-
-/* This function generates the canonical encoding of the Name structure.
- * In it all strings are converted to UTF8, leading, trailing and
- * multiple spaces collapsed, converted to lower case and the leading
- * SEQUENCE header removed.
- *
- * In future we could also normalize the UTF8 too.
- *
- * By doing this comparison of Name structures can be rapidly
- * perfomed by just using memcmp() of the canonical encoding.
- * By omitting the leading SEQUENCE name constraints of type
- * dirName can also be checked with a simple memcmp().
+ int indent,
+ const char *fname, const ASN1_PCTX *pctx)
+{
+ if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
+ indent, pctx->nm_flags) <= 0)
+ return 0;
+ return 2;
+}
+
+/*
+ * This function generates the canonical encoding of the Name structure. In
+ * it all strings are converted to UTF8, leading, trailing and multiple
+ * spaces collapsed, converted to lower case and the leading SEQUENCE header
+ * removed. In future we could also normalize the UTF8 too. By doing this
+ * comparison of Name structures can be rapidly perfomed by just using
+ * memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
+ * constraints of type dirName can also be checked with a simple memcmp().
*/
static int x509_name_canon(X509_NAME *a)
- {
- unsigned char *p;
- STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
- STACK_OF(X509_NAME_ENTRY) *entries = NULL;
- X509_NAME_ENTRY *entry, *tmpentry = NULL;
- int set = -1, ret = 0;
- size_t i;
-
- if (a->canon_enc)
- {
- OPENSSL_free(a->canon_enc);
- a->canon_enc = NULL;
- }
- /* Special case: empty X509_NAME => null encoding */
- if (sk_X509_NAME_ENTRY_num(a->entries) == 0)
- {
- a->canon_enclen = 0;
- return 1;
- }
- intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
- if(!intname)
- goto err;
- 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 err;
- if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
- {
- sk_X509_NAME_ENTRY_free(entries);
- goto err;
- }
- set = entry->set;
- }
- tmpentry = X509_NAME_ENTRY_new();
- if (tmpentry == NULL)
- goto err;
- tmpentry->object = OBJ_dup(entry->object);
- if (!asn1_string_canon(tmpentry->value, entry->value))
- goto err;
- if(!sk_X509_NAME_ENTRY_push(entries, tmpentry))
- goto err;
- tmpentry = NULL;
- }
-
- /* Finally generate encoding */
-
- a->canon_enclen = i2d_name_canon(intname, NULL);
-
- p = OPENSSL_malloc(a->canon_enclen);
-
- if (!p)
- goto err;
-
- a->canon_enc = p;
-
- i2d_name_canon(intname, &p);
-
- ret = 1;
-
- err:
-
- if (tmpentry)
- X509_NAME_ENTRY_free(tmpentry);
- if (intname)
- sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
- local_sk_X509_NAME_ENTRY_pop_free);
- return ret;
- }
+{
+ unsigned char *p;
+ STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+ STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+ X509_NAME_ENTRY *entry, *tmpentry = NULL;
+ int set = -1, ret = 0;
+ size_t i;
+
+ if (a->canon_enc) {
+ OPENSSL_free(a->canon_enc);
+ a->canon_enc = NULL;
+ }
+ /* Special case: empty X509_NAME => null encoding */
+ if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
+ a->canon_enclen = 0;
+ return 1;
+ }
+ intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+ if (!intname)
+ goto err;
+ 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 err;
+ if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
+ sk_X509_NAME_ENTRY_free(entries);
+ goto err;
+ }
+ set = entry->set;
+ }
+ tmpentry = X509_NAME_ENTRY_new();
+ if (tmpentry == NULL)
+ goto err;
+ tmpentry->object = OBJ_dup(entry->object);
+ if (!asn1_string_canon(tmpentry->value, entry->value))
+ goto err;
+ if (!sk_X509_NAME_ENTRY_push(entries, tmpentry))
+ goto err;
+ tmpentry = NULL;
+ }
+
+ /* Finally generate encoding */
+
+ a->canon_enclen = i2d_name_canon(intname, NULL);
+
+ p = OPENSSL_malloc(a->canon_enclen);
+
+ if (!p)
+ goto err;
+
+ a->canon_enc = p;
+
+ i2d_name_canon(intname, &p);
+
+ ret = 1;
+
+ err:
+
+ if (tmpentry)
+ X509_NAME_ENTRY_free(tmpentry);
+ if (intname)
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
+ local_sk_X509_NAME_ENTRY_pop_free);
+ return ret;
+}
/* Bitmap of all the types of string that will be canonicalized. */
-#define ASN1_MASK_CANON \
- (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
- | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
- | B_ASN1_VISIBLESTRING)
-
+#define ASN1_MASK_CANON \
+ (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
+ | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
+ | B_ASN1_VISIBLESTRING)
static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
- {
- unsigned char *to, *from;
- int len, i;
-
- /* If type not in bitmask just copy string across */
- if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON))
- {
- if (!ASN1_STRING_copy(out, in))
- return 0;
- return 1;
- }
-
- out->type = V_ASN1_UTF8STRING;
- out->length = ASN1_STRING_to_UTF8(&out->data, in);
- if (out->length == -1)
- return 0;
-
- to = out->data;
- from = to;
-
- len = out->length;
-
- /* Convert string in place to canonical form.
- * Ultimately we may need to handle a wider range of characters
- * but for now ignore anything with MSB set and rely on the
- * isspace() and tolower() functions.
- */
-
- /* Ignore leading spaces */
- while((len > 0) && !(*from & 0x80) && isspace(*from))
- {
- from++;
- len--;
- }
-
- to = from + len - 1;
-
- /* Ignore trailing spaces */
- while ((len > 0) && !(*to & 0x80) && isspace(*to))
- {
- to--;
- len--;
- }
-
- to = out->data;
-
- i = 0;
- while(i < len)
- {
- /* If MSB set just copy across */
- if (*from & 0x80)
- {
- *to++ = *from++;
- i++;
- }
- /* Collapse multiple spaces */
- else if (isspace(*from))
- {
- /* Copy one space across */
- *to++ = ' ';
- /* Ignore subsequent spaces. Note: don't need to
- * check len here because we know the last
- * character is a non-space so we can't overflow.
- */
- do
- {
- from++;
- i++;
- }
- while(!(*from & 0x80) && isspace(*from));
- }
- else
- {
- *to++ = tolower(*from);
- from++;
- i++;
- }
- }
-
- out->length = to - out->data;
-
- return 1;
-
- }
-
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname,
- unsigned char **in)
- {
- int len, ltmp;
- size_t i;
- ASN1_VALUE *v;
- STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
-
- len = 0;
- for (i = 0; i < sk_ASN1_VALUE_num(intname); i++)
- {
- v = sk_ASN1_VALUE_value(intname, i);
- ltmp = ASN1_item_ex_i2d(&v, in,
- ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
- if (ltmp < 0)
- return ltmp;
- len += ltmp;
- }
- return len;
- }
+{
+ unsigned char *to, *from;
+ int len, i;
+
+ /* If type not in bitmask just copy string across */
+ if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
+ if (!ASN1_STRING_copy(out, in))
+ return 0;
+ return 1;
+ }
+
+ out->type = V_ASN1_UTF8STRING;
+ out->length = ASN1_STRING_to_UTF8(&out->data, in);
+ if (out->length == -1)
+ return 0;
+
+ to = out->data;
+ from = to;
+
+ len = out->length;
+
+ /*
+ * Convert string in place to canonical form. Ultimately we may need to
+ * handle a wider range of characters but for now ignore anything with
+ * MSB set and rely on the isspace() and tolower() functions.
+ */
+
+ /* Ignore leading spaces */
+ while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
+ from++;
+ len--;
+ }
+
+ to = from + len - 1;
+
+ /* Ignore trailing spaces */
+ while ((len > 0) && !(*to & 0x80) && isspace(*to)) {
+ to--;
+ len--;
+ }
+
+ to = out->data;
+
+ i = 0;
+ while (i < len) {
+ /* If MSB set just copy across */
+ if (*from & 0x80) {
+ *to++ = *from++;
+ i++;
+ }
+ /* Collapse multiple spaces */
+ else if (isspace(*from)) {
+ /* Copy one space across */
+ *to++ = ' ';
+ /*
+ * Ignore subsequent spaces. Note: don't need to check len here
+ * because we know the last character is a non-space so we can't
+ * overflow.
+ */
+ do {
+ from++;
+ i++;
+ }
+ while (!(*from & 0x80) && isspace(*from));
+ } else {
+ *to++ = tolower(*from);
+ from++;
+ i++;
+ }
+ }
+
+ out->length = to - out->data;
+
+ return 1;
+
+}
+
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
+ unsigned char **in)
+{
+ int len, ltmp;
+ size_t i;
+ ASN1_VALUE *v;
+ STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
+
+ len = 0;
+ for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
+ v = sk_ASN1_VALUE_value(intname, i);
+ ltmp = ASN1_item_ex_i2d(&v, in,
+ ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
+ if (ltmp < 0)
+ return ltmp;
+ len += ltmp;
+ }
+ return len;
+}
int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
- {
- X509_NAME *in;
-
- if (!xn || !name) return(0);
-
- if (*xn != name)
- {
- in=X509_NAME_dup(name);
- if (in != NULL)
- {
- X509_NAME_free(*xn);
- *xn=in;
- }
- }
- return(*xn != NULL);
- }
-
+{
+ X509_NAME *in;
+
+ if (!xn || !name)
+ return (0);
+
+ if (*xn != name) {
+ in = X509_NAME_dup(name);
+ if (in != NULL) {
+ X509_NAME_free(*xn);
+ *xn = in;
+ }
+ }
+ return (*xn != NULL);
+}
+
IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
diff --git a/src/crypto/x509/x_pkey.c b/src/crypto/x509/x_pkey.c
index f5e98b82..fc445954 100644
--- a/src/crypto/x509/x_pkey.c
+++ b/src/crypto/x509/x_pkey.c
@@ -63,38 +63,41 @@
#include <openssl/mem.h>
#include <openssl/thread.h>
-
X509_PKEY *X509_PKEY_new(void)
- {
- X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
- if (ret == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(ret, 0, sizeof(X509_PKEY));
+{
+ X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(ret, 0, sizeof(X509_PKEY));
- ret->enc_algor = X509_ALGOR_new();
- if (ret->enc_algor == NULL)
- goto err;
- ret->enc_pkey = M_ASN1_OCTET_STRING_new();
- if (ret->enc_pkey == NULL)
- goto err;
- return ret;
+ ret->enc_algor = X509_ALGOR_new();
+ if (ret->enc_algor == NULL)
+ goto err;
+ ret->enc_pkey = M_ASN1_OCTET_STRING_new();
+ if (ret->enc_pkey == NULL)
+ goto err;
+ return ret;
-err:
- if (ret != NULL)
- X509_PKEY_free(ret);
- return NULL;
- }
+ err:
+ if (ret != NULL)
+ X509_PKEY_free(ret);
+ return NULL;
+}
void X509_PKEY_free(X509_PKEY *x)
- {
- if (x == NULL) return;
+{
+ if (x == NULL)
+ return;
- if (x->enc_algor != NULL) X509_ALGOR_free(x->enc_algor);
- if (x->enc_pkey != NULL) M_ASN1_OCTET_STRING_free(x->enc_pkey);
- if (x->dec_pkey != NULL)EVP_PKEY_free(x->dec_pkey);
- if ((x->key_data != NULL) && (x->key_free)) OPENSSL_free(x->key_data);
- OPENSSL_free(x);
- }
+ if (x->enc_algor != NULL)
+ X509_ALGOR_free(x->enc_algor);
+ if (x->enc_pkey != NULL)
+ M_ASN1_OCTET_STRING_free(x->enc_pkey);
+ if (x->dec_pkey != NULL)
+ EVP_PKEY_free(x->dec_pkey);
+ if ((x->key_data != NULL) && (x->key_free))
+ OPENSSL_free(x->key_data);
+ OPENSSL_free(x);
+}
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
index a16edcab..1549195e 100644
--- a/src/crypto/x509/x_pubkey.c
+++ b/src/crypto/x509/x_pubkey.c
@@ -54,78 +54,75 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <openssl/x509.h>
+
+#include <limits.h>
+
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/thread.h>
-#include <openssl/x509.h>
-#include "../evp/internal.h"
#include "../internal.h"
-
/* Minor tweak to operation: free up EVP_PKEY */
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
- {
- if (operation == ASN1_OP_FREE_POST)
- {
- X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
- EVP_PKEY_free(pubkey->pkey);
- }
- return 1;
- }
+ void *exarg)
+{
+ if (operation == ASN1_OP_FREE_POST) {
+ X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
+ EVP_PKEY_free(pubkey->pkey);
+ }
+ return 1;
+}
ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
- ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
- ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
+ ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
- {
- X509_PUBKEY *pk=NULL;
-
- if (x == NULL) return(0);
-
- if ((pk=X509_PUBKEY_new()) == NULL) goto error;
-
- if (pkey->ameth)
- {
- if (pkey->ameth->pub_encode)
- {
- if (!pkey->ameth->pub_encode(pk, pkey))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
- goto error;
- }
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNSUPPORTED_ALGORITHM);
- goto error;
- }
-
- if (*x != NULL)
- X509_PUBKEY_free(*x);
-
- *x=pk;
-
- return 1;
-error:
- if (pk != NULL) X509_PUBKEY_free(pk);
- return 0;
- }
+{
+ X509_PUBKEY *pk = NULL;
+ uint8_t *spki = NULL;
+ size_t spki_len;
+
+ if (x == NULL)
+ return (0);
+
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !EVP_marshal_public_key(&cbb, pkey) ||
+ !CBB_finish(&cbb, &spki, &spki_len) ||
+ spki_len > LONG_MAX) {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ goto error;
+ }
+
+ const uint8_t *p = spki;
+ pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len);
+ if (pk == NULL || p != spki + spki_len) {
+ OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
+ }
+
+ OPENSSL_free(spki);
+ X509_PUBKEY_free(*x);
+ *x = pk;
+
+ return 1;
+ error:
+ X509_PUBKEY_free(pk);
+ OPENSSL_free(spki);
+ return 0;
+}
/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of
* |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t|
@@ -134,251 +131,236 @@ error:
static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT;
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
- {
- EVP_PKEY *ret=NULL;
-
- if (key == NULL) goto error;
-
- CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
- if (key->pkey != NULL)
- {
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
- return EVP_PKEY_up_ref(key->pkey);
- }
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
-
- if (key->public_key == NULL) goto error;
-
- if ((ret = EVP_PKEY_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- goto error;
- }
-
- if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_UNSUPPORTED_ALGORITHM);
- goto error;
- }
-
- if (ret->ameth->pub_decode)
- {
- if (!ret->ameth->pub_decode(ret, key))
- {
- OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
- goto error;
- }
- }
- else
- {
- OPENSSL_PUT_ERROR(X509, X509_R_METHOD_NOT_SUPPORTED);
- goto error;
- }
-
- /* Check to see if another thread set key->pkey first */
- CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
- if (key->pkey)
- {
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
- EVP_PKEY_free(ret);
- ret = key->pkey;
- }
- else
- {
- key->pkey = ret;
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
- }
-
- return EVP_PKEY_up_ref(ret);
-
- error:
- if (ret != NULL)
- EVP_PKEY_free(ret);
- return(NULL);
- }
-
-/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
- * and encode or decode as X509_PUBKEY
+{
+ EVP_PKEY *ret = NULL;
+ uint8_t *spki = NULL;
+
+ if (key == NULL)
+ goto error;
+
+ CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
+ if (key->pkey != NULL) {
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ return EVP_PKEY_up_ref(key->pkey);
+ }
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+
+ /* Re-encode the |X509_PUBKEY| to DER and parse it. */
+ int spki_len = i2d_X509_PUBKEY(key, &spki);
+ if (spki_len < 0) {
+ goto error;
+ }
+ CBS cbs;
+ CBS_init(&cbs, spki, (size_t)spki_len);
+ ret = EVP_parse_public_key(&cbs);
+ if (ret == NULL || CBS_len(&cbs) != 0) {
+ OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
+ }
+
+ /* Check to see if another thread set key->pkey first */
+ CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
+ if (key->pkey) {
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ EVP_PKEY_free(ret);
+ ret = key->pkey;
+ } else {
+ key->pkey = ret;
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ }
+
+ OPENSSL_free(spki);
+ return EVP_PKEY_up_ref(ret);
+
+ error:
+ OPENSSL_free(spki);
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+/*
+ * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
+ * decode as X509_PUBKEY
*/
-EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
- long length)
- {
- X509_PUBKEY *xpk;
- EVP_PKEY *pktmp;
- xpk = d2i_X509_PUBKEY(NULL, pp, length);
- if(!xpk) return NULL;
- pktmp = X509_PUBKEY_get(xpk);
- X509_PUBKEY_free(xpk);
- if(!pktmp) return NULL;
- if(a)
- {
- EVP_PKEY_free(*a);
- *a = pktmp;
- }
- return pktmp;
- }
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
+{
+ X509_PUBKEY *xpk;
+ EVP_PKEY *pktmp;
+ xpk = d2i_X509_PUBKEY(NULL, pp, length);
+ if (!xpk)
+ return NULL;
+ pktmp = X509_PUBKEY_get(xpk);
+ X509_PUBKEY_free(xpk);
+ if (!pktmp)
+ return NULL;
+ if (a) {
+ EVP_PKEY_free(*a);
+ *a = pktmp;
+ }
+ return pktmp;
+}
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
- {
- X509_PUBKEY *xpk=NULL;
- int ret;
- if(!a) return 0;
- if(!X509_PUBKEY_set(&xpk, (EVP_PKEY*) a)) return 0;
- ret = i2d_X509_PUBKEY(xpk, pp);
- X509_PUBKEY_free(xpk);
- return ret;
- }
-
-/* The following are equivalents but which return RSA and DSA
- * keys
+{
+ X509_PUBKEY *xpk = NULL;
+ int ret;
+ if (!a)
+ return 0;
+ if (!X509_PUBKEY_set(&xpk, (EVP_PKEY *)a))
+ return 0;
+ ret = i2d_X509_PUBKEY(xpk, pp);
+ X509_PUBKEY_free(xpk);
+ return ret;
+}
+
+/*
+ * The following are equivalents but which return RSA and DSA keys
*/
-RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
- long length)
- {
- EVP_PKEY *pkey;
- RSA *key;
- const unsigned char *q;
- q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey) return NULL;
- key = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
- if (!key) return NULL;
- *pp = q;
- if (a)
- {
- RSA_free(*a);
- *a = key;
- }
- return key;
- }
+RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ RSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey)
+ return NULL;
+ key = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key)
+ return NULL;
+ *pp = q;
+ if (a) {
+ RSA_free(*a);
+ *a = key;
+ }
+ return key;
+}
int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
- {
- EVP_PKEY *pktmp;
- int ret;
- if (!a) return 0;
- pktmp = EVP_PKEY_new();
- if (!pktmp)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- EVP_PKEY_set1_RSA(pktmp, (RSA*) a);
- ret = i2d_PUBKEY(pktmp, pp);
- EVP_PKEY_free(pktmp);
- return ret;
- }
+{
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a)
+ return 0;
+ pktmp = EVP_PKEY_new();
+ if (!pktmp) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_RSA(pktmp, (RSA *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
#ifndef OPENSSL_NO_DSA
-DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
- long length)
- {
- EVP_PKEY *pkey;
- DSA *key;
- const unsigned char *q;
- q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey) return NULL;
- key = EVP_PKEY_get1_DSA(pkey);
- EVP_PKEY_free(pkey);
- if (!key) return NULL;
- *pp = q;
- if (a)
- {
- DSA_free(*a);
- *a = key;
- }
- return key;
- }
+DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ DSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey)
+ return NULL;
+ key = EVP_PKEY_get1_DSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key)
+ return NULL;
+ *pp = q;
+ if (a) {
+ DSA_free(*a);
+ *a = key;
+ }
+ return key;
+}
int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
- {
- EVP_PKEY *pktmp;
- int ret;
- if(!a) return 0;
- pktmp = EVP_PKEY_new();
- if(!pktmp)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- EVP_PKEY_set1_DSA(pktmp, (DSA*) a);
- ret = i2d_PUBKEY(pktmp, pp);
- EVP_PKEY_free(pktmp);
- return ret;
- }
+{
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a)
+ return 0;
+ pktmp = EVP_PKEY_new();
+ if (!pktmp) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_DSA(pktmp, (DSA *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
#endif
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
- {
- EVP_PKEY *pkey;
- EC_KEY *key;
- const unsigned char *q;
- q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey) return(NULL);
- key = EVP_PKEY_get1_EC_KEY(pkey);
- EVP_PKEY_free(pkey);
- if (!key) return(NULL);
- *pp = q;
- if (a)
- {
- EC_KEY_free(*a);
- *a = key;
- }
- return(key);
- }
+{
+ EVP_PKEY *pkey;
+ EC_KEY *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey)
+ return (NULL);
+ key = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key)
+ return (NULL);
+ *pp = q;
+ if (a) {
+ EC_KEY_free(*a);
+ *a = key;
+ }
+ return (key);
+}
int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
- {
- EVP_PKEY *pktmp;
- int ret;
- if (!a) return(0);
- if ((pktmp = EVP_PKEY_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- return(0);
- }
- EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY*) a);
- ret = i2d_PUBKEY(pktmp, pp);
- EVP_PKEY_free(pktmp);
- return(ret);
- }
+{
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a)
+ return (0);
+ if ((pktmp = EVP_PKEY_new()) == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return (ret);
+}
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
- int ptype, void *pval,
- unsigned char *penc, int penclen)
- {
- if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
- return 0;
- if (penc)
- {
- if (pub->public_key->data)
- OPENSSL_free(pub->public_key->data);
- pub->public_key->data = penc;
- pub->public_key->length = penclen;
- /* Set number of unused bits to zero */
- pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
- pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
- }
- return 1;
- }
+ int ptype, void *pval,
+ unsigned char *penc, int penclen)
+{
+ if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
+ return 0;
+ if (penc) {
+ if (pub->public_key->data)
+ OPENSSL_free(pub->public_key->data);
+ pub->public_key->data = penc;
+ pub->public_key->length = penclen;
+ /* Set number of unused bits to zero */
+ pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ }
+ return 1;
+}
int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
- const unsigned char **pk, int *ppklen,
- X509_ALGOR **pa,
- X509_PUBKEY *pub)
- {
- if (ppkalg)
- *ppkalg = pub->algor->algorithm;
- if (pk)
- {
- *pk = pub->public_key->data;
- *ppklen = pub->public_key->length;
- }
- if (pa)
- *pa = pub->algor;
- return 1;
- }
+ const unsigned char **pk, int *ppklen,
+ X509_ALGOR **pa, X509_PUBKEY *pub)
+{
+ if (ppkalg)
+ *ppkalg = pub->algor->algorithm;
+ if (pk) {
+ *pk = pub->public_key->data;
+ *ppklen = pub->public_key->length;
+ }
+ if (pa)
+ *pa = pub->algor;
+ return 1;
+}
diff --git a/src/crypto/x509/x_req.c b/src/crypto/x509/x_req.c
index 3d301297..5dfe19e5 100644
--- a/src/crypto/x509/x_req.c
+++ b/src/crypto/x509/x_req.c
@@ -60,53 +60,50 @@
#include <openssl/thread.h>
#include <openssl/x509.h>
-/* X509_REQ_INFO is handled in an unusual way to get round
- * invalid encodings. Some broken certificate requests don't
- * encode the attributes field if it is empty. This is in
- * violation of PKCS#10 but we need to tolerate it. We do
- * this by making the attributes field OPTIONAL then using
- * the callback to initialise it to an empty STACK.
- *
- * This means that the field will be correctly encoded unless
- * we NULL out the field.
- *
- * As a result we no longer need the req_kludge field because
- * the information is now contained in the attributes field:
- * 1. If it is NULL then it's the invalid omission.
- * 2. If it is empty it is the correct encoding.
- * 3. If it is not empty then some attributes are present.
- *
+/*
+ * X509_REQ_INFO is handled in an unusual way to get round invalid encodings.
+ * Some broken certificate requests don't encode the attributes field if it
+ * is empty. This is in violation of PKCS#10 but we need to tolerate it. We
+ * do this by making the attributes field OPTIONAL then using the callback to
+ * initialise it to an empty STACK. This means that the field will be
+ * correctly encoded unless we NULL out the field. As a result we no longer
+ * need the req_kludge field because the information is now contained in the
+ * attributes field: 1. If it is NULL then it's the invalid omission. 2. If
+ * it is empty it is the correct encoding. 3. If it is not empty then some
+ * attributes are present.
*/
static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
+ void *exarg)
{
- X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
+ X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
- if(operation == ASN1_OP_NEW_POST) {
- rinf->attributes = sk_X509_ATTRIBUTE_new_null();
- if(!rinf->attributes) return 0;
- }
- return 1;
+ if (operation == ASN1_OP_NEW_POST) {
+ rinf->attributes = sk_X509_ATTRIBUTE_new_null();
+ if (!rinf->attributes)
+ return 0;
+ }
+ return 1;
}
ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
- ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
- ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
- ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
- /* This isn't really OPTIONAL but it gets round invalid
- * encodings
- */
- ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
+ ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
+ ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
+ /* This isn't really OPTIONAL but it gets round invalid
+ * encodings
+ */
+ ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
ASN1_SEQUENCE_ref(X509_REQ, 0) = {
- ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
- ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
- ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
+ ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
+ ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
+
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
diff --git a/src/crypto/x509/x_sig.c b/src/crypto/x509/x_sig.c
index fabdb676..e18024a7 100644
--- a/src/crypto/x509/x_sig.c
+++ b/src/crypto/x509/x_sig.c
@@ -62,8 +62,8 @@
ASN1_SEQUENCE(X509_SIG) = {
- ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
- ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
+ ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(X509_SIG)
IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
diff --git a/src/crypto/x509/x_spki.c b/src/crypto/x509/x_spki.c
index 35bf2465..86da6ddf 100644
--- a/src/crypto/x509/x_spki.c
+++ b/src/crypto/x509/x_spki.c
@@ -55,24 +55,26 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
- /* This module was send to me my Pat Richards <patr@x509.com> who
- * wrote it. It is under my Copyright with his permission. */
+ /*
+ * This module was send to me my Pat Richards <patr@x509.com> who wrote it.
+ * It is under my Copyright with his permission.
+ */
#include <openssl/x509.h>
#include <openssl/asn1t.h>
ASN1_SEQUENCE(NETSCAPE_SPKAC) = {
- ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
- ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
+ ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
+ ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
} ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
ASN1_SEQUENCE(NETSCAPE_SPKI) = {
- ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
- ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
- ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
+ ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
+ ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
+ ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END(NETSCAPE_SPKI)
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
diff --git a/src/crypto/x509/x_val.c b/src/crypto/x509/x_val.c
index 26200ee4..ad4f7e14 100644
--- a/src/crypto/x509/x_val.c
+++ b/src/crypto/x509/x_val.c
@@ -62,8 +62,8 @@
ASN1_SEQUENCE(X509_VAL) = {
- ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
- ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
+ ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
+ ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
} ASN1_SEQUENCE_END(X509_VAL)
IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 7bbe4f36..f12140fb 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -67,20 +67,19 @@
#include "../internal.h"
-
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
- ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
- ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
- ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
- ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
- ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
- ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
- ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
- ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
- ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
- ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
+ ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
+ ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
+ ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
+ ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
+ ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
+ ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
@@ -89,139 +88,149 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
extern void policy_cache_free(X509_POLICY_CACHE *cache);
static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
+ void *exarg)
{
- X509 *ret = (X509 *)*pval;
-
- switch(operation) {
-
- case ASN1_OP_NEW_POST:
- ret->valid=0;
- ret->name = NULL;
- ret->ex_flags = 0;
- ret->ex_pathlen = -1;
- ret->skid = NULL;
- ret->akid = NULL;
- ret->aux = NULL;
- ret->crldp = NULL;
- CRYPTO_new_ex_data(&ret->ex_data);
- break;
-
- case ASN1_OP_D2I_POST:
- if (ret->name != NULL) OPENSSL_free(ret->name);
- ret->name=X509_NAME_oneline(ret->cert_info->subject,NULL,0);
- break;
-
- case ASN1_OP_FREE_POST:
- CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
- X509_CERT_AUX_free(ret->aux);
- ASN1_OCTET_STRING_free(ret->skid);
- AUTHORITY_KEYID_free(ret->akid);
- CRL_DIST_POINTS_free(ret->crldp);
- policy_cache_free(ret->policy_cache);
- GENERAL_NAMES_free(ret->altname);
- NAME_CONSTRAINTS_free(ret->nc);
-
- if (ret->name != NULL) OPENSSL_free(ret->name);
- break;
-
- }
-
- return 1;
+ X509 *ret = (X509 *)*pval;
+
+ switch (operation) {
+
+ case ASN1_OP_NEW_POST:
+ ret->valid = 0;
+ ret->name = NULL;
+ ret->ex_flags = 0;
+ ret->ex_pathlen = -1;
+ ret->skid = NULL;
+ ret->akid = NULL;
+ ret->aux = NULL;
+ ret->crldp = NULL;
+ CRYPTO_new_ex_data(&ret->ex_data);
+ break;
+
+ case ASN1_OP_D2I_POST:
+ if (ret->name != NULL)
+ OPENSSL_free(ret->name);
+ ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
+ break;
+
+ case ASN1_OP_FREE_POST:
+ CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
+ X509_CERT_AUX_free(ret->aux);
+ ASN1_OCTET_STRING_free(ret->skid);
+ AUTHORITY_KEYID_free(ret->akid);
+ CRL_DIST_POINTS_free(ret->crldp);
+ policy_cache_free(ret->policy_cache);
+ GENERAL_NAMES_free(ret->altname);
+ NAME_CONSTRAINTS_free(ret->nc);
+
+ if (ret->name != NULL)
+ OPENSSL_free(ret->name);
+ break;
+
+ }
+
+ return 1;
}
ASN1_SEQUENCE_ref(X509, x509_cb) = {
- ASN1_SIMPLE(X509, cert_info, X509_CINF),
- ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
- ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
+ ASN1_SIMPLE(X509, cert_info, X509_CINF),
+ ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509, X509)
IMPLEMENT_ASN1_FUNCTIONS(X509)
+
IMPLEMENT_ASN1_DUP_FUNCTION(X509)
X509 *X509_up_ref(X509 *x)
- {
- CRYPTO_refcount_inc(&x->references);
- return x;
- }
-
-int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
- CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
- {
- int index;
- if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
- dup_func, free_func))
- {
- return -1;
- }
- return index;
- }
+{
+ CRYPTO_refcount_inc(&x->references);
+ return x;
+}
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused * unused,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
+}
int X509_set_ex_data(X509 *r, int idx, void *arg)
- {
- return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
- }
+{
+ return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
+}
void *X509_get_ex_data(X509 *r, int idx)
- {
- return(CRYPTO_get_ex_data(&r->ex_data,idx));
- }
-
-/* X509_AUX ASN1 routines. X509_AUX is the name given to
- * a certificate with extra info tagged on the end. Since these
- * functions set how a certificate is trusted they should only
- * be used when the certificate comes from a reliable source
- * such as local storage.
- *
+{
+ return (CRYPTO_get_ex_data(&r->ex_data, idx));
+}
+
+/*
+ * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
+ * extra info tagged on the end. Since these functions set how a certificate
+ * is trusted they should only be used when the certificate comes from a
+ * reliable source such as local storage.
*/
X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
{
- const unsigned char *q = *pp;
- X509 *ret;
- int freeret = 0;
-
- if (!a || *a == NULL)
- freeret = 1;
- ret = d2i_X509(a, &q, length);
- /* If certificate unreadable then forget it */
- if(!ret) return NULL;
- /* update length */
- length -= q - *pp;
- /* Parse auxiliary information if there is any. */
- if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
- goto err;
- *pp = q;
- return ret;
- err:
- if (freeret)
- {
- X509_free(ret);
- if (a)
- *a = NULL;
- }
- return NULL;
+ const unsigned char *q = *pp;
+ X509 *ret;
+ int freeret = 0;
+
+ if (!a || *a == NULL)
+ freeret = 1;
+ ret = d2i_X509(a, &q, length);
+ /* If certificate unreadable then forget it */
+ if (!ret)
+ return NULL;
+ /* update length */
+ length -= q - *pp;
+ /* Parse auxiliary information if there is any. */
+ if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
+ goto err;
+ *pp = q;
+ return ret;
+ err:
+ if (freeret) {
+ X509_free(ret);
+ if (a)
+ *a = NULL;
+ }
+ return NULL;
}
int i2d_X509_AUX(X509 *a, unsigned char **pp)
{
- int length;
- length = i2d_X509(a, pp);
- if(a) length += i2d_X509_CERT_AUX(a->aux, pp);
- return length;
+ int length, tmplen;
+ length = i2d_X509(a, pp);
+ if (length < 0 || a == NULL) {
+ return length;
+ }
+
+ tmplen = i2d_X509_CERT_AUX(a->aux, pp);
+ if (tmplen < 0) {
+ return tmplen;
+ }
+ length += tmplen;
+
+ return length;
}
void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
- const X509 *x)
- {
- if (psig)
- *psig = x->signature;
- if (palg)
- *palg = x->sig_alg;
- }
+ const X509 *x)
+{
+ if (psig)
+ *psig = x->signature;
+ if (palg)
+ *palg = x->sig_alg;
+}
int X509_get_signature_nid(const X509 *x)
- {
- return OBJ_obj2nid(x->sig_alg->algorithm);
- }
+{
+ return OBJ_obj2nid(x->sig_alg->algorithm);
+}
diff --git a/src/crypto/x509/x_x509a.c b/src/crypto/x509/x_x509a.c
index fb7172b4..a63ee422 100644
--- a/src/crypto/x509/x_x509a.c
+++ b/src/crypto/x509/x_x509a.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -59,139 +61,145 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-
-/* X509_CERT_AUX routines. These are used to encode additional
- * user modifiable data about a certificate. This data is
- * appended to the X509 encoding when the *_X509_AUX routines
- * are used. This means that the "traditional" X509 routines
- * will simply ignore the extra data. */
+/*
+ * X509_CERT_AUX routines. These are used to encode additional user
+ * modifiable data about a certificate. This data is appended to the X509
+ * encoding when the *_X509_AUX routines are used. This means that the
+ * "traditional" X509 routines will simply ignore the extra data.
+ */
static X509_CERT_AUX *aux_get(X509 *x);
ASN1_SEQUENCE(X509_CERT_AUX) = {
- ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
- ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
- ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
- ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
- ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
+ ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
+ ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
+ ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
} ASN1_SEQUENCE_END(X509_CERT_AUX)
IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
static X509_CERT_AUX *aux_get(X509 *x)
{
- if(!x) return NULL;
- if(!x->aux && !(x->aux = X509_CERT_AUX_new())) return NULL;
- return x->aux;
+ if (!x)
+ return NULL;
+ if (!x->aux && !(x->aux = X509_CERT_AUX_new()))
+ return NULL;
+ return x->aux;
}
int X509_alias_set1(X509 *x, unsigned char *name, int len)
{
- X509_CERT_AUX *aux;
- if (!name)
- {
- if (!x || !x->aux || !x->aux->alias)
- return 1;
- ASN1_UTF8STRING_free(x->aux->alias);
- x->aux->alias = NULL;
- return 1;
- }
- if(!(aux = aux_get(x))) return 0;
- if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0;
- return ASN1_STRING_set(aux->alias, name, len);
+ X509_CERT_AUX *aux;
+ if (!name) {
+ if (!x || !x->aux || !x->aux->alias)
+ return 1;
+ ASN1_UTF8STRING_free(x->aux->alias);
+ x->aux->alias = NULL;
+ return 1;
+ }
+ if (!(aux = aux_get(x)))
+ return 0;
+ if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new()))
+ return 0;
+ return ASN1_STRING_set(aux->alias, name, len);
}
int X509_keyid_set1(X509 *x, unsigned char *id, int len)
{
- X509_CERT_AUX *aux;
- if (!id)
- {
- if (!x || !x->aux || !x->aux->keyid)
- return 1;
- ASN1_OCTET_STRING_free(x->aux->keyid);
- x->aux->keyid = NULL;
- return 1;
- }
- if(!(aux = aux_get(x))) return 0;
- if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
- return ASN1_STRING_set(aux->keyid, id, len);
+ X509_CERT_AUX *aux;
+ if (!id) {
+ if (!x || !x->aux || !x->aux->keyid)
+ return 1;
+ ASN1_OCTET_STRING_free(x->aux->keyid);
+ x->aux->keyid = NULL;
+ return 1;
+ }
+ if (!(aux = aux_get(x)))
+ return 0;
+ if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new()))
+ return 0;
+ return ASN1_STRING_set(aux->keyid, id, len);
}
unsigned char *X509_alias_get0(X509 *x, int *len)
{
- if(!x->aux || !x->aux->alias) return NULL;
- if(len) *len = x->aux->alias->length;
- return x->aux->alias->data;
+ if (!x->aux || !x->aux->alias)
+ return NULL;
+ if (len)
+ *len = x->aux->alias->length;
+ return x->aux->alias->data;
}
unsigned char *X509_keyid_get0(X509 *x, int *len)
{
- if(!x->aux || !x->aux->keyid) return NULL;
- if(len) *len = x->aux->keyid->length;
- return x->aux->keyid->data;
+ if (!x->aux || !x->aux->keyid)
+ return NULL;
+ if (len)
+ *len = x->aux->keyid->length;
+ return x->aux->keyid->data;
}
int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj)
{
- ASN1_OBJECT *objtmp = OBJ_dup(obj);
- if (objtmp == NULL)
- goto err;
- X509_CERT_AUX *aux = aux_get(x);
- if (aux->trust == NULL)
- {
- aux->trust = sk_ASN1_OBJECT_new_null();
- if (aux->trust == NULL)
- goto err;
- }
- if (!sk_ASN1_OBJECT_push(aux->trust, objtmp))
- goto err;
- return 1;
-
-err:
- ASN1_OBJECT_free(objtmp);
- return 0;
+ ASN1_OBJECT *objtmp = OBJ_dup(obj);
+ if (objtmp == NULL)
+ goto err;
+ X509_CERT_AUX *aux = aux_get(x);
+ if (aux->trust == NULL) {
+ aux->trust = sk_ASN1_OBJECT_new_null();
+ if (aux->trust == NULL)
+ goto err;
+ }
+ if (!sk_ASN1_OBJECT_push(aux->trust, objtmp))
+ goto err;
+ return 1;
+
+ err:
+ ASN1_OBJECT_free(objtmp);
+ return 0;
}
int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj)
{
- ASN1_OBJECT *objtmp = OBJ_dup(obj);
- if (objtmp == NULL)
- goto err;
- X509_CERT_AUX *aux = aux_get(x);
- if (aux->reject == NULL)
- {
- aux->reject = sk_ASN1_OBJECT_new_null();
- if (aux->reject == NULL)
- goto err;
- }
- if (!sk_ASN1_OBJECT_push(aux->reject, objtmp))
- goto err;
- return 1;
-
-err:
- ASN1_OBJECT_free(objtmp);
- return 0;
+ ASN1_OBJECT *objtmp = OBJ_dup(obj);
+ if (objtmp == NULL)
+ goto err;
+ X509_CERT_AUX *aux = aux_get(x);
+ if (aux->reject == NULL) {
+ aux->reject = sk_ASN1_OBJECT_new_null();
+ if (aux->reject == NULL)
+ goto err;
+ }
+ if (!sk_ASN1_OBJECT_push(aux->reject, objtmp))
+ goto err;
+ return 1;
+
+ err:
+ ASN1_OBJECT_free(objtmp);
+ return 0;
}
void X509_trust_clear(X509 *x)
{
- if(x->aux && x->aux->trust) {
- sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
- x->aux->trust = NULL;
- }
+ if (x->aux && x->aux->trust) {
+ sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
+ x->aux->trust = NULL;
+ }
}
void X509_reject_clear(X509 *x)
{
- if(x->aux && x->aux->reject) {
- sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
- x->aux->reject = NULL;
- }
+ if (x->aux && x->aux->reject) {
+ sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
+ x->aux->reject = NULL;
+ }
}
ASN1_SEQUENCE(X509_CERT_PAIR) = {
- ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
- ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
+ ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
+ ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
} ASN1_SEQUENCE_END(X509_CERT_PAIR)
IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_PAIR)
diff --git a/src/crypto/x509v3/ext_dat.h b/src/crypto/x509v3/ext_dat.h
index f1fb8ef3..9ece19c5 100644
--- a/src/crypto/x509v3/ext_dat.h
+++ b/src/crypto/x509v3/ext_dat.h
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
@@ -9,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -56,74 +57,79 @@
/* This file contains a table of "standard" extensions */
extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku;
-extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo;
-extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id;
+extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info,
+ v3_sinfo;
+extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id,
+ v3_akey_id;
extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate;
-extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl;
-extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff;
-extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc;
+extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld,
+ v3_freshest_crl;
+extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp,
+ v3_ocsp_acutoff;
+extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck,
+ v3_ocsp_serviceloc;
extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci;
extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp;
extern const X509V3_EXT_METHOD v3_addr, v3_asid;
-/* This table will be searched using OBJ_bsearch so it *must* kept in
- * order of the ext_nid values.
+/*
+ * This table will be searched using OBJ_bsearch so it *must* kept in order
+ * of the ext_nid values.
*/
/* TODO(fork): OCSP support */
#define OPENSSL_NO_OCSP
static const X509V3_EXT_METHOD *const standard_exts[] = {
-&v3_nscert,
-&v3_ns_ia5_list[0],
-&v3_ns_ia5_list[1],
-&v3_ns_ia5_list[2],
-&v3_ns_ia5_list[3],
-&v3_ns_ia5_list[4],
-&v3_ns_ia5_list[5],
-&v3_ns_ia5_list[6],
-&v3_skey_id,
-&v3_key_usage,
-&v3_pkey_usage_period,
-&v3_alt[0],
-&v3_alt[1],
-&v3_bcons,
-&v3_crl_num,
-&v3_cpols,
-&v3_akey_id,
-&v3_crld,
-&v3_ext_ku,
-&v3_delta_crl,
-&v3_crl_reason,
+ &v3_nscert,
+ &v3_ns_ia5_list[0],
+ &v3_ns_ia5_list[1],
+ &v3_ns_ia5_list[2],
+ &v3_ns_ia5_list[3],
+ &v3_ns_ia5_list[4],
+ &v3_ns_ia5_list[5],
+ &v3_ns_ia5_list[6],
+ &v3_skey_id,
+ &v3_key_usage,
+ &v3_pkey_usage_period,
+ &v3_alt[0],
+ &v3_alt[1],
+ &v3_bcons,
+ &v3_crl_num,
+ &v3_cpols,
+ &v3_akey_id,
+ &v3_crld,
+ &v3_ext_ku,
+ &v3_delta_crl,
+ &v3_crl_reason,
#ifndef OPENSSL_NO_OCSP
-&v3_crl_invdate,
+ &v3_crl_invdate,
#endif
-&v3_sxnet,
-&v3_info,
+ &v3_sxnet,
+ &v3_info,
#ifndef OPENSSL_NO_OCSP
-&v3_ocsp_nonce,
-&v3_ocsp_crlid,
-&v3_ocsp_accresp,
-&v3_ocsp_nocheck,
-&v3_ocsp_acutoff,
-&v3_ocsp_serviceloc,
+ &v3_ocsp_nonce,
+ &v3_ocsp_crlid,
+ &v3_ocsp_accresp,
+ &v3_ocsp_nocheck,
+ &v3_ocsp_acutoff,
+ &v3_ocsp_serviceloc,
#endif
-&v3_sinfo,
-&v3_policy_constraints,
+ &v3_sinfo,
+ &v3_policy_constraints,
#ifndef OPENSSL_NO_OCSP
-&v3_crl_hold,
+ &v3_crl_hold,
#endif
-&v3_pci,
-&v3_name_constraints,
-&v3_policy_mappings,
-&v3_inhibit_anyp,
-&v3_idp,
-&v3_alt[2],
-&v3_freshest_crl,
+ &v3_pci,
+ &v3_name_constraints,
+ &v3_policy_mappings,
+ &v3_inhibit_anyp,
+ &v3_idp,
+ &v3_alt[2],
+ &v3_freshest_crl,
};
/* Number of standard extensions */
#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *))
-
diff --git a/src/crypto/x509v3/pcy_cache.c b/src/crypto/x509v3/pcy_cache.c
index 08f20aa2..f1e512ea 100644
--- a/src/crypto/x509v3/pcy_cache.c
+++ b/src/crypto/x509v3/pcy_cache.c
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -9,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,238 +63,222 @@
#include "pcy_int.h"
#include "../internal.h"
-
static int policy_data_cmp(const X509_POLICY_DATA **a,
- const X509_POLICY_DATA **b);
+ const X509_POLICY_DATA **b);
static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
-/* Set cache entry according to CertificatePolicies extension.
- * Note: this destroys the passed CERTIFICATEPOLICIES structure.
+/*
+ * Set cache entry according to CertificatePolicies extension. Note: this
+ * destroys the passed CERTIFICATEPOLICIES structure.
*/
static int policy_cache_create(X509 *x,
- CERTIFICATEPOLICIES *policies, int crit)
- {
- size_t i;
- int ret = 0;
- X509_POLICY_CACHE *cache = x->policy_cache;
- X509_POLICY_DATA *data = NULL;
- POLICYINFO *policy;
- if (sk_POLICYINFO_num(policies) == 0)
- goto bad_policy;
- cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
- if (!cache->data)
- goto bad_policy;
- for (i = 0; i < sk_POLICYINFO_num(policies); i++)
- {
- policy = sk_POLICYINFO_value(policies, i);
- data = policy_data_new(policy, NULL, crit);
- if (!data)
- goto bad_policy;
- /* Duplicate policy OIDs are illegal: reject if matches
- * found.
- */
- if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
- {
- if (cache->anyPolicy)
- {
- ret = -1;
- goto bad_policy;
- }
- cache->anyPolicy = data;
- }
- else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data))
- {
- ret = -1;
- goto bad_policy;
- }
- else if (!sk_X509_POLICY_DATA_push(cache->data, data))
- goto bad_policy;
- data = NULL;
- }
- ret = 1;
- bad_policy:
- if (ret == -1)
- x->ex_flags |= EXFLAG_INVALID_POLICY;
- if (data)
- policy_data_free(data);
- sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
- if (ret <= 0)
- {
- sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
- cache->data = NULL;
- }
- return ret;
- }
-
-
+ CERTIFICATEPOLICIES *policies, int crit)
+{
+ size_t i;
+ int ret = 0;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ X509_POLICY_DATA *data = NULL;
+ POLICYINFO *policy;
+ if (sk_POLICYINFO_num(policies) == 0)
+ goto bad_policy;
+ cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
+ if (!cache->data)
+ goto bad_policy;
+ for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
+ policy = sk_POLICYINFO_value(policies, i);
+ data = policy_data_new(policy, NULL, crit);
+ if (!data)
+ goto bad_policy;
+ /*
+ * Duplicate policy OIDs are illegal: reject if matches found.
+ */
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+ if (cache->anyPolicy) {
+ ret = -1;
+ goto bad_policy;
+ }
+ cache->anyPolicy = data;
+ } else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data)) {
+ ret = -1;
+ goto bad_policy;
+ } else if (!sk_X509_POLICY_DATA_push(cache->data, data))
+ goto bad_policy;
+ data = NULL;
+ }
+ ret = 1;
+ bad_policy:
+ if (ret == -1)
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ if (data)
+ policy_data_free(data);
+ sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
+ if (ret <= 0) {
+ sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+ cache->data = NULL;
+ }
+ return ret;
+}
+
static int policy_cache_new(X509 *x)
- {
- X509_POLICY_CACHE *cache;
- ASN1_INTEGER *ext_any = NULL;
- POLICY_CONSTRAINTS *ext_pcons = NULL;
- CERTIFICATEPOLICIES *ext_cpols = NULL;
- POLICY_MAPPINGS *ext_pmaps = NULL;
- int i;
- cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
- if (!cache)
- return 0;
- cache->anyPolicy = NULL;
- cache->data = NULL;
- cache->any_skip = -1;
- cache->explicit_skip = -1;
- cache->map_skip = -1;
-
- x->policy_cache = cache;
-
- /* Handle requireExplicitPolicy *first*. Need to process this
- * even if we don't have any policies.
- */
- ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
-
- if (!ext_pcons)
- {
- if (i != -1)
- goto bad_cache;
- }
- else
- {
- if (!ext_pcons->requireExplicitPolicy
- && !ext_pcons->inhibitPolicyMapping)
- goto bad_cache;
- if (!policy_cache_set_int(&cache->explicit_skip,
- ext_pcons->requireExplicitPolicy))
- goto bad_cache;
- if (!policy_cache_set_int(&cache->map_skip,
- ext_pcons->inhibitPolicyMapping))
- goto bad_cache;
- }
-
- /* Process CertificatePolicies */
-
- ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
- /* If no CertificatePolicies extension or problem decoding then
- * there is no point continuing because the valid policies will be
- * NULL.
- */
- if (!ext_cpols)
- {
- /* If not absent some problem with extension */
- if (i != -1)
- goto bad_cache;
- return 1;
- }
-
- i = policy_cache_create(x, ext_cpols, i);
-
- /* NB: ext_cpols freed by policy_cache_set_policies */
-
- if (i <= 0)
- return i;
-
- ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
-
- if (!ext_pmaps)
- {
- /* If not absent some problem with extension */
- if (i != -1)
- goto bad_cache;
- }
- else
- {
- i = policy_cache_set_mapping(x, ext_pmaps);
- if (i <= 0)
- goto bad_cache;
- }
-
- ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
-
- if (!ext_any)
- {
- if (i != -1)
- goto bad_cache;
- }
- else if (!policy_cache_set_int(&cache->any_skip, ext_any))
- goto bad_cache;
-
- if (0)
- {
- bad_cache:
- x->ex_flags |= EXFLAG_INVALID_POLICY;
- }
-
- if(ext_pcons)
- POLICY_CONSTRAINTS_free(ext_pcons);
-
- if (ext_any)
- ASN1_INTEGER_free(ext_any);
-
- return 1;
-
-
+{
+ X509_POLICY_CACHE *cache;
+ ASN1_INTEGER *ext_any = NULL;
+ POLICY_CONSTRAINTS *ext_pcons = NULL;
+ CERTIFICATEPOLICIES *ext_cpols = NULL;
+ POLICY_MAPPINGS *ext_pmaps = NULL;
+ int i;
+ cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
+ if (!cache)
+ return 0;
+ cache->anyPolicy = NULL;
+ cache->data = NULL;
+ cache->any_skip = -1;
+ cache->explicit_skip = -1;
+ cache->map_skip = -1;
+
+ x->policy_cache = cache;
+
+ /*
+ * Handle requireExplicitPolicy *first*. Need to process this even if we
+ * don't have any policies.
+ */
+ ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
+
+ if (!ext_pcons) {
+ if (i != -1)
+ goto bad_cache;
+ } else {
+ if (!ext_pcons->requireExplicitPolicy
+ && !ext_pcons->inhibitPolicyMapping)
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->explicit_skip,
+ ext_pcons->requireExplicitPolicy))
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->map_skip,
+ ext_pcons->inhibitPolicyMapping))
+ goto bad_cache;
+ }
+
+ /* Process CertificatePolicies */
+
+ ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
+ /*
+ * If no CertificatePolicies extension or problem decoding then there is
+ * no point continuing because the valid policies will be NULL.
+ */
+ if (!ext_cpols) {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ return 1;
+ }
+
+ i = policy_cache_create(x, ext_cpols, i);
+
+ /* NB: ext_cpols freed by policy_cache_set_policies */
+
+ if (i <= 0)
+ return i;
+
+ ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
+
+ if (!ext_pmaps) {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ } else {
+ i = policy_cache_set_mapping(x, ext_pmaps);
+ if (i <= 0)
+ goto bad_cache;
+ }
+
+ ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
+
+ if (!ext_any) {
+ if (i != -1)
+ goto bad_cache;
+ } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
+ goto bad_cache;
+
+ if (0) {
+ bad_cache:
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ }
+
+ if (ext_pcons)
+ POLICY_CONSTRAINTS_free(ext_pcons);
+
+ if (ext_any)
+ ASN1_INTEGER_free(ext_any);
+
+ return 1;
+
}
void policy_cache_free(X509_POLICY_CACHE *cache)
- {
- if (!cache)
- return;
- if (cache->anyPolicy)
- policy_data_free(cache->anyPolicy);
- if (cache->data)
- sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
- OPENSSL_free(cache);
- }
-
-/* g_x509_policy_cache_lock is used to protect against concurrent calls to
- * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t|
- * in the |X509| structure, but |CRYPTO_once_t| isn't public. */
+{
+ if (!cache)
+ return;
+ if (cache->anyPolicy)
+ policy_data_free(cache->anyPolicy);
+ if (cache->data)
+ sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+ OPENSSL_free(cache);
+}
+
+/*
+ * g_x509_policy_cache_lock is used to protect against concurrent calls to
+ * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in
+ * the |X509| structure, but |CRYPTO_once_t| isn't public.
+ */
static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock =
CRYPTO_STATIC_MUTEX_INIT;
const X509_POLICY_CACHE *policy_cache_set(X509 *x)
- {
- X509_POLICY_CACHE *cache;
+{
+ X509_POLICY_CACHE *cache;
- CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
- cache = x->policy_cache;
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+ CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
+ cache = x->policy_cache;
+ CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
- if (cache != NULL)
- return cache;
+ if (cache != NULL)
+ return cache;
- CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
- if (x->policy_cache == NULL)
- policy_cache_new(x);
- cache = x->policy_cache;
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+ CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
+ if (x->policy_cache == NULL)
+ policy_cache_new(x);
+ cache = x->policy_cache;
+ CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
- return cache;
- }
+ return cache;
+}
X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id)
- {
- size_t idx;
- X509_POLICY_DATA tmp;
-
- tmp.valid_policy = (ASN1_OBJECT *)id;
- if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
- return NULL;
- return sk_X509_POLICY_DATA_value(cache->data, idx);
- }
+ const ASN1_OBJECT *id)
+{
+ size_t idx;
+ X509_POLICY_DATA tmp;
+
+ tmp.valid_policy = (ASN1_OBJECT *)id;
+ if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
+ return NULL;
+ return sk_X509_POLICY_DATA_value(cache->data, idx);
+}
static int policy_data_cmp(const X509_POLICY_DATA **a,
- const X509_POLICY_DATA **b)
- {
- return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
- }
+ const X509_POLICY_DATA **b)
+{
+ return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
+}
static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
- {
- if (value == NULL)
- return 1;
- if (value->type == V_ASN1_NEG_INTEGER)
- return 0;
- *out = ASN1_INTEGER_get(value);
- return 1;
- }
+{
+ if (value == NULL)
+ return 1;
+ if (value->type == V_ASN1_NEG_INTEGER)
+ return 0;
+ *out = ASN1_INTEGER_get(value);
+ return 1;
+}
diff --git a/src/crypto/x509v3/pcy_data.c b/src/crypto/x509v3/pcy_data.c
index cd45dcaa..498de4dd 100644
--- a/src/crypto/x509v3/pcy_data.c
+++ b/src/crypto/x509v3/pcy_data.c
@@ -1,6 +1,7 @@
/* pcy_data.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,75 +64,67 @@
#include "pcy_int.h"
-
/* Policy Node routines */
void policy_data_free(X509_POLICY_DATA *data)
- {
- ASN1_OBJECT_free(data->valid_policy);
- /* Don't free qualifiers if shared */
- if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
- sk_POLICYQUALINFO_pop_free(data->qualifier_set,
- POLICYQUALINFO_free);
- sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
- OPENSSL_free(data);
- }
+{
+ ASN1_OBJECT_free(data->valid_policy);
+ /* Don't free qualifiers if shared */
+ if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
+ sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free);
+ sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
+ OPENSSL_free(data);
+}
-/* Create a data based on an existing policy. If 'id' is NULL use the
- * oid in the policy, otherwise use 'id'. This behaviour covers the two
- * types of data in RFC3280: data with from a CertificatePolcies extension
- * and additional data with just the qualifiers of anyPolicy and ID from
- * another source.
+/*
+ * Create a data based on an existing policy. If 'id' is NULL use the oid in
+ * the policy, otherwise use 'id'. This behaviour covers the two types of
+ * data in RFC3280: data with from a CertificatePolcies extension and
+ * additional data with just the qualifiers of anyPolicy and ID from another
+ * source.
*/
X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
- const ASN1_OBJECT *cid, int crit)
- {
- X509_POLICY_DATA *ret;
- ASN1_OBJECT *id;
- if (!policy && !cid)
- return NULL;
- if (cid)
- {
- id = OBJ_dup(cid);
- if (!id)
- return NULL;
- }
- else
- id = NULL;
- ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
- if (!ret)
- return NULL;
- ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
- if (!ret->expected_policy_set)
- {
- OPENSSL_free(ret);
- if (id)
- ASN1_OBJECT_free(id);
- return NULL;
- }
-
- if (crit)
- ret->flags = POLICY_DATA_FLAG_CRITICAL;
- else
- ret->flags = 0;
+ const ASN1_OBJECT *cid, int crit)
+{
+ X509_POLICY_DATA *ret;
+ ASN1_OBJECT *id;
+ if (!policy && !cid)
+ return NULL;
+ if (cid) {
+ id = OBJ_dup(cid);
+ if (!id)
+ return NULL;
+ } else
+ id = NULL;
+ ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
+ if (!ret)
+ return NULL;
+ ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
+ if (!ret->expected_policy_set) {
+ OPENSSL_free(ret);
+ if (id)
+ ASN1_OBJECT_free(id);
+ return NULL;
+ }
- if (id)
- ret->valid_policy = id;
- else
- {
- ret->valid_policy = policy->policyid;
- policy->policyid = NULL;
- }
+ if (crit)
+ ret->flags = POLICY_DATA_FLAG_CRITICAL;
+ else
+ ret->flags = 0;
- if (policy)
- {
- ret->qualifier_set = policy->qualifiers;
- policy->qualifiers = NULL;
- }
- else
- ret->qualifier_set = NULL;
+ if (id)
+ ret->valid_policy = id;
+ else {
+ ret->valid_policy = policy->policyid;
+ policy->policyid = NULL;
+ }
- return ret;
- }
+ if (policy) {
+ ret->qualifier_set = policy->qualifiers;
+ policy->qualifiers = NULL;
+ } else
+ ret->qualifier_set = NULL;
+ return ret;
+}
diff --git a/src/crypto/x509v3/pcy_int.h b/src/crypto/x509v3/pcy_int.h
index ccff9284..b5075f9e 100644
--- a/src/crypto/x509v3/pcy_int.h
+++ b/src/crypto/x509v3/pcy_int.h
@@ -1,6 +1,7 @@
/* pcy_int.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -56,121 +57,126 @@
*
*/
-
typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
DECLARE_STACK_OF(X509_POLICY_DATA)
/* Internal structures */
-/* This structure and the field names correspond to the Policy 'node' of
- * RFC3280. NB this structure contains no pointers to parent or child
- * data: X509_POLICY_NODE contains that. This means that the main policy data
- * can be kept static and cached with the certificate.
+/*
+ * This structure and the field names correspond to the Policy 'node' of
+ * RFC3280. NB this structure contains no pointers to parent or child data:
+ * X509_POLICY_NODE contains that. This means that the main policy data can
+ * be kept static and cached with the certificate.
*/
-struct X509_POLICY_DATA_st
- {
- unsigned int flags;
- /* Policy OID and qualifiers for this data */
- ASN1_OBJECT *valid_policy;
- STACK_OF(POLICYQUALINFO) *qualifier_set;
- STACK_OF(ASN1_OBJECT) *expected_policy_set;
- };
+struct X509_POLICY_DATA_st {
+ unsigned int flags;
+ /* Policy OID and qualifiers for this data */
+ ASN1_OBJECT *valid_policy;
+ STACK_OF(POLICYQUALINFO) *qualifier_set;
+ STACK_OF(ASN1_OBJECT) *expected_policy_set;
+};
/* X509_POLICY_DATA flags values */
-/* This flag indicates the structure has been mapped using a policy mapping
- * extension. If policy mapping is not active its references get deleted.
+/*
+ * This flag indicates the structure has been mapped using a policy mapping
+ * extension. If policy mapping is not active its references get deleted.
*/
-#define POLICY_DATA_FLAG_MAPPED 0x1
+#define POLICY_DATA_FLAG_MAPPED 0x1
-/* This flag indicates the data doesn't correspond to a policy in Certificate
+/*
+ * This flag indicates the data doesn't correspond to a policy in Certificate
* Policies: it has been mapped to any policy.
*/
-#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
+#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
/* AND with flags to see if any mapping has occurred */
-#define POLICY_DATA_FLAG_MAP_MASK 0x3
+#define POLICY_DATA_FLAG_MAP_MASK 0x3
/* qualifiers are shared and shouldn't be freed */
-#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
+#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
/* Parent node is an extra node and should be freed */
-#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
+#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
/* Corresponding CertificatePolicies is critical */
-#define POLICY_DATA_FLAG_CRITICAL 0x10
+#define POLICY_DATA_FLAG_CRITICAL 0x10
/* This structure is cached with a certificate */
struct X509_POLICY_CACHE_st {
- /* anyPolicy data or NULL if no anyPolicy */
- X509_POLICY_DATA *anyPolicy;
- /* other policy data */
- STACK_OF(X509_POLICY_DATA) *data;
- /* If InhibitAnyPolicy present this is its value or -1 if absent. */
- long any_skip;
- /* If policyConstraints and requireExplicitPolicy present this is its
- * value or -1 if absent.
- */
- long explicit_skip;
- /* If policyConstraints and policyMapping present this is its
- * value or -1 if absent.
- */
- long map_skip;
- };
-
-/*#define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL*/
+ /* anyPolicy data or NULL if no anyPolicy */
+ X509_POLICY_DATA *anyPolicy;
+ /* other policy data */
+ STACK_OF(X509_POLICY_DATA) *data;
+ /* If InhibitAnyPolicy present this is its value or -1 if absent. */
+ long any_skip;
+ /*
+ * If policyConstraints and requireExplicitPolicy present this is its
+ * value or -1 if absent.
+ */
+ long explicit_skip;
+ /*
+ * If policyConstraints and policyMapping present this is its value or -1
+ * if absent.
+ */
+ long map_skip;
+};
+
+/*
+ * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
+ */
/* This structure represents the relationship between nodes */
-struct X509_POLICY_NODE_st
- {
- /* node data this refers to */
- const X509_POLICY_DATA *data;
- /* Parent node */
- X509_POLICY_NODE *parent;
- /* Number of child nodes */
- int nchild;
- };
-
-struct X509_POLICY_LEVEL_st
- {
- /* Cert for this level */
- X509 *cert;
- /* nodes at this level */
- STACK_OF(X509_POLICY_NODE) *nodes;
- /* anyPolicy node */
- X509_POLICY_NODE *anyPolicy;
- /* Extra data */
- /*STACK_OF(X509_POLICY_DATA) *extra_data;*/
- unsigned int flags;
- };
-
-struct X509_POLICY_TREE_st
- {
- /* This is the tree 'level' data */
- X509_POLICY_LEVEL *levels;
- int nlevel;
- /* Extra policy data when additional nodes (not from the certificate)
- * are required.
- */
- STACK_OF(X509_POLICY_DATA) *extra_data;
- /* This is the authority constained policy set */
- STACK_OF(X509_POLICY_NODE) *auth_policies;
- STACK_OF(X509_POLICY_NODE) *user_policies;
- unsigned int flags;
- };
+struct X509_POLICY_NODE_st {
+ /* node data this refers to */
+ const X509_POLICY_DATA *data;
+ /* Parent node */
+ X509_POLICY_NODE *parent;
+ /* Number of child nodes */
+ int nchild;
+};
+
+struct X509_POLICY_LEVEL_st {
+ /* Cert for this level */
+ X509 *cert;
+ /* nodes at this level */
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ /* anyPolicy node */
+ X509_POLICY_NODE *anyPolicy;
+ /* Extra data */
+ /*
+ * STACK_OF(X509_POLICY_DATA) *extra_data;
+ */
+ unsigned int flags;
+};
+
+struct X509_POLICY_TREE_st {
+ /* This is the tree 'level' data */
+ X509_POLICY_LEVEL *levels;
+ int nlevel;
+ /*
+ * Extra policy data when additional nodes (not from the certificate) are
+ * required.
+ */
+ STACK_OF(X509_POLICY_DATA) *extra_data;
+ /* This is the authority constained policy set */
+ STACK_OF(X509_POLICY_NODE) *auth_policies;
+ STACK_OF(X509_POLICY_NODE) *user_policies;
+ unsigned int flags;
+};
/* Set if anyPolicy present in user policies */
-#define POLICY_FLAG_ANY_POLICY 0x2
+#define POLICY_FLAG_ANY_POLICY 0x2
/* Useful macros */
@@ -180,14 +186,13 @@ struct X509_POLICY_TREE_st
/* Internal functions */
X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
- int crit);
+ int crit);
void policy_data_free(X509_POLICY_DATA *data);
X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id);
+ const ASN1_OBJECT *id);
int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
-
STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
void policy_cache_init(void);
@@ -195,18 +200,18 @@ void policy_cache_init(void);
void policy_cache_free(X509_POLICY_CACHE *cache);
X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
- const X509_POLICY_NODE *parent,
- const ASN1_OBJECT *id);
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id);
X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
- const ASN1_OBJECT *id);
+ const ASN1_OBJECT *id);
X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
- const X509_POLICY_DATA *data,
- X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree);
+ const X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree);
void policy_node_free(X509_POLICY_NODE *node);
int policy_node_match(const X509_POLICY_LEVEL *lvl,
- const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
const X509_POLICY_CACHE *policy_cache_set(X509 *x);
diff --git a/src/crypto/x509v3/pcy_lib.c b/src/crypto/x509v3/pcy_lib.c
index 16be2f00..764f38f9 100644
--- a/src/crypto/x509v3/pcy_lib.c
+++ b/src/crypto/x509v3/pcy_lib.c
@@ -1,6 +1,7 @@
/* pcy_lib.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,112 +55,110 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "pcy_int.h"
-
/* accessor functions */
/* X509_POLICY_TREE stuff */
int X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
- {
- if (!tree)
- return 0;
- return tree->nlevel;
- }
-
-X509_POLICY_LEVEL *
- X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i)
- {
- if (!tree || (i < 0) || (i >= tree->nlevel))
- return NULL;
- return tree->levels + i;
- }
-
-STACK_OF(X509_POLICY_NODE) *
- X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree)
- {
- if (!tree)
- return NULL;
- return tree->auth_policies;
- }
-
-STACK_OF(X509_POLICY_NODE) *
- X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree)
- {
- if (!tree)
- return NULL;
- if (tree->flags & POLICY_FLAG_ANY_POLICY)
- return tree->auth_policies;
- else
- return tree->user_policies;
- }
+{
+ if (!tree)
+ return 0;
+ return tree->nlevel;
+}
+
+X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
+ int i)
+{
+ if (!tree || (i < 0) || (i >= tree->nlevel))
+ return NULL;
+ return tree->levels + i;
+}
+
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const
+ X509_POLICY_TREE
+ *tree)
+{
+ if (!tree)
+ return NULL;
+ return tree->auth_policies;
+}
+
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const
+ X509_POLICY_TREE
+ *tree)
+{
+ if (!tree)
+ return NULL;
+ if (tree->flags & POLICY_FLAG_ANY_POLICY)
+ return tree->auth_policies;
+ else
+ return tree->user_policies;
+}
/* X509_POLICY_LEVEL stuff */
int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
- {
- int n;
- if (!level)
- return 0;
- if (level->anyPolicy)
- n = 1;
- else
- n = 0;
- if (level->nodes)
- n += sk_X509_POLICY_NODE_num(level->nodes);
- return n;
- }
+{
+ int n;
+ if (!level)
+ return 0;
+ if (level->anyPolicy)
+ n = 1;
+ else
+ n = 0;
+ if (level->nodes)
+ n += sk_X509_POLICY_NODE_num(level->nodes);
+ return n;
+}
X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
- {
- if (!level)
- return NULL;
- if (level->anyPolicy)
- {
- if (i == 0)
- return level->anyPolicy;
- i--;
- }
- return sk_X509_POLICY_NODE_value(level->nodes, i);
- }
+{
+ if (!level)
+ return NULL;
+ if (level->anyPolicy) {
+ if (i == 0)
+ return level->anyPolicy;
+ i--;
+ }
+ return sk_X509_POLICY_NODE_value(level->nodes, i);
+}
/* X509_POLICY_NODE stuff */
const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
- {
- if (!node)
- return NULL;
- return node->data->valid_policy;
- }
+{
+ if (!node)
+ return NULL;
+ return node->data->valid_policy;
+}
#if 0
int X509_policy_node_get_critical(const X509_POLICY_NODE *node)
- {
- if (node_critical(node))
- return 1;
- return 0;
- }
+{
+ if (node_critical(node))
+ return 1;
+ return 0;
+}
#endif
-STACK_OF(POLICYQUALINFO) *
- X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node)
- {
- if (!node)
- return NULL;
- return node->data->qualifier_set;
- }
-
-const X509_POLICY_NODE *
- X509_policy_node_get0_parent(const X509_POLICY_NODE *node)
- {
- if (!node)
- return NULL;
- return node->parent;
- }
-
-
+STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const
+ X509_POLICY_NODE
+ *node)
+{
+ if (!node)
+ return NULL;
+ return node->data->qualifier_set;
+}
+
+const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE
+ *node)
+{
+ if (!node)
+ return NULL;
+ return node->parent;
+}
diff --git a/src/crypto/x509v3/pcy_map.c b/src/crypto/x509v3/pcy_map.c
index 2b8307b1..7263c692 100644
--- a/src/crypto/x509v3/pcy_map.c
+++ b/src/crypto/x509v3/pcy_map.c
@@ -1,6 +1,7 @@
/* pcy_map.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,72 +63,68 @@
#include "pcy_int.h"
-
-/* Set policy mapping entries in cache.
- * Note: this modifies the passed POLICY_MAPPINGS structure
+/*
+ * Set policy mapping entries in cache. Note: this modifies the passed
+ * POLICY_MAPPINGS structure
*/
int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
- {
- POLICY_MAPPING *map;
- X509_POLICY_DATA *data;
- X509_POLICY_CACHE *cache = x->policy_cache;
- size_t i;
- int ret = 0;
- if (sk_POLICY_MAPPING_num(maps) == 0)
- {
- ret = -1;
- goto bad_mapping;
- }
- for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++)
- {
- map = sk_POLICY_MAPPING_value(maps, i);
- /* Reject if map to or from anyPolicy */
- if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
- || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy))
- {
- ret = -1;
- goto bad_mapping;
- }
+{
+ POLICY_MAPPING *map;
+ X509_POLICY_DATA *data;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ size_t i;
+ int ret = 0;
+ if (sk_POLICY_MAPPING_num(maps) == 0) {
+ ret = -1;
+ goto bad_mapping;
+ }
+ for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
+ map = sk_POLICY_MAPPING_value(maps, i);
+ /* Reject if map to or from anyPolicy */
+ if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
+ || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
+ ret = -1;
+ goto bad_mapping;
+ }
- /* Attempt to find matching policy data */
- data = policy_cache_find_data(cache, map->issuerDomainPolicy);
- /* If we don't have anyPolicy can't map */
- if (!data && !cache->anyPolicy)
- continue;
+ /* Attempt to find matching policy data */
+ data = policy_cache_find_data(cache, map->issuerDomainPolicy);
+ /* If we don't have anyPolicy can't map */
+ if (!data && !cache->anyPolicy)
+ continue;
- /* Create a NODE from anyPolicy */
- if (!data)
- {
- data = policy_data_new(NULL, map->issuerDomainPolicy,
- cache->anyPolicy->flags
- & POLICY_DATA_FLAG_CRITICAL);
- if (!data)
- goto bad_mapping;
- data->qualifier_set = cache->anyPolicy->qualifier_set;
- /*map->issuerDomainPolicy = NULL;*/
- data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
- data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (!sk_X509_POLICY_DATA_push(cache->data, data))
- {
- policy_data_free(data);
- goto bad_mapping;
- }
- }
- else
- data->flags |= POLICY_DATA_FLAG_MAPPED;
- if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
- map->subjectDomainPolicy))
- goto bad_mapping;
- map->subjectDomainPolicy = NULL;
+ /* Create a NODE from anyPolicy */
+ if (!data) {
+ data = policy_data_new(NULL, map->issuerDomainPolicy,
+ cache->anyPolicy->flags
+ & POLICY_DATA_FLAG_CRITICAL);
+ if (!data)
+ goto bad_mapping;
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ /*
+ * map->issuerDomainPolicy = NULL;
+ */
+ data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
+ policy_data_free(data);
+ goto bad_mapping;
+ }
+ } else
+ data->flags |= POLICY_DATA_FLAG_MAPPED;
+ if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
+ map->subjectDomainPolicy))
+ goto bad_mapping;
+ map->subjectDomainPolicy = NULL;
- }
+ }
- ret = 1;
- bad_mapping:
- if (ret == -1)
- x->ex_flags |= EXFLAG_INVALID_POLICY;
- sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
- return ret;
+ ret = 1;
+ bad_mapping:
+ if (ret == -1)
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
+ return ret;
- }
+}
diff --git a/src/crypto/x509v3/pcy_node.c b/src/crypto/x509v3/pcy_node.c
index 55cc2039..cf4e79d8 100644
--- a/src/crypto/x509v3/pcy_node.c
+++ b/src/crypto/x509v3/pcy_node.c
@@ -1,6 +1,7 @@
/* pcy_node.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,136 +63,126 @@
#include "pcy_int.h"
-
-static int node_cmp(const X509_POLICY_NODE **a,
- const X509_POLICY_NODE **b)
- {
- return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
- }
+static int node_cmp(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b)
+{
+ return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
+}
STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void)
- {
- return sk_X509_POLICY_NODE_new(node_cmp);
- }
+{
+ return sk_X509_POLICY_NODE_new(node_cmp);
+}
X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
- const ASN1_OBJECT *id)
- {
- X509_POLICY_DATA n;
- X509_POLICY_NODE l;
- size_t idx;
+ const ASN1_OBJECT *id)
+{
+ X509_POLICY_DATA n;
+ X509_POLICY_NODE l;
+ size_t idx;
- n.valid_policy = (ASN1_OBJECT *)id;
- l.data = &n;
+ n.valid_policy = (ASN1_OBJECT *)id;
+ l.data = &n;
- if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l))
- return NULL;
+ if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l))
+ return NULL;
- return sk_X509_POLICY_NODE_value(nodes, idx);
+ return sk_X509_POLICY_NODE_value(nodes, idx);
- }
+}
X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
- const X509_POLICY_NODE *parent,
- const ASN1_OBJECT *id)
- {
- X509_POLICY_NODE *node;
- size_t i;
- for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++)
- {
- node = sk_X509_POLICY_NODE_value(level->nodes, i);
- if (node->parent == parent)
- {
- if (!OBJ_cmp(node->data->valid_policy, id))
- return node;
- }
- }
- return NULL;
- }
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id)
+{
+ X509_POLICY_NODE *node;
+ size_t i;
+ for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(level->nodes, i);
+ if (node->parent == parent) {
+ if (!OBJ_cmp(node->data->valid_policy, id))
+ return node;
+ }
+ }
+ return NULL;
+}
X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
- const X509_POLICY_DATA *data,
- X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree)
- {
- X509_POLICY_NODE *node;
- node = OPENSSL_malloc(sizeof(X509_POLICY_NODE));
- if (!node)
- return NULL;
- node->data = data;
- node->parent = parent;
- node->nchild = 0;
- if (level)
- {
- if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
- {
- if (level->anyPolicy)
- goto node_error;
- level->anyPolicy = node;
- }
- else
- {
-
- if (!level->nodes)
- level->nodes = policy_node_cmp_new();
- if (!level->nodes)
- goto node_error;
- if (!sk_X509_POLICY_NODE_push(level->nodes, node))
- goto node_error;
- }
- }
-
- if (tree)
- {
- if (!tree->extra_data)
- tree->extra_data = sk_X509_POLICY_DATA_new_null();
- if (!tree->extra_data)
- goto node_error;
- if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
- goto node_error;
- }
-
- if (parent)
- parent->nchild++;
-
- return node;
-
- node_error:
- policy_node_free(node);
- return 0;
-
- }
+ const X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree)
+{
+ X509_POLICY_NODE *node;
+ node = OPENSSL_malloc(sizeof(X509_POLICY_NODE));
+ if (!node)
+ return NULL;
+ node->data = data;
+ node->parent = parent;
+ node->nchild = 0;
+ if (level) {
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+ if (level->anyPolicy)
+ goto node_error;
+ level->anyPolicy = node;
+ } else {
+
+ if (!level->nodes)
+ level->nodes = policy_node_cmp_new();
+ if (!level->nodes)
+ goto node_error;
+ if (!sk_X509_POLICY_NODE_push(level->nodes, node))
+ goto node_error;
+ }
+ }
+
+ if (tree) {
+ if (!tree->extra_data)
+ tree->extra_data = sk_X509_POLICY_DATA_new_null();
+ if (!tree->extra_data)
+ goto node_error;
+ if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
+ goto node_error;
+ }
+
+ if (parent)
+ parent->nchild++;
+
+ return node;
+
+ node_error:
+ policy_node_free(node);
+ return 0;
+
+}
void policy_node_free(X509_POLICY_NODE *node)
- {
- OPENSSL_free(node);
- }
+{
+ OPENSSL_free(node);
+}
-/* See if a policy node matches a policy OID. If mapping enabled look through
+/*
+ * See if a policy node matches a policy OID. If mapping enabled look through
* expected policy set otherwise just valid policy.
*/
int policy_node_match(const X509_POLICY_LEVEL *lvl,
- const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
- {
- size_t i;
- ASN1_OBJECT *policy_oid;
- const X509_POLICY_DATA *x = node->data;
-
- if ( (lvl->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(x->flags & POLICY_DATA_FLAG_MAP_MASK))
- {
- if (!OBJ_cmp(x->valid_policy, oid))
- return 1;
- return 0;
- }
-
- for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++)
- {
- policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
- if (!OBJ_cmp(policy_oid, oid))
- return 1;
- }
- return 0;
-
- }
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
+{
+ size_t i;
+ ASN1_OBJECT *policy_oid;
+ const X509_POLICY_DATA *x = node->data;
+
+ if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
+ if (!OBJ_cmp(x->valid_policy, oid))
+ return 1;
+ return 0;
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
+ policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
+ if (!OBJ_cmp(policy_oid, oid))
+ return 1;
+ }
+ return 0;
+
+}
diff --git a/src/crypto/x509v3/pcy_tree.c b/src/crypto/x509v3/pcy_tree.c
index 8e9ef25d..e7484e52 100644
--- a/src/crypto/x509v3/pcy_tree.c
+++ b/src/crypto/x509v3/pcy_tree.c
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
*/
/* ====================================================================
* Copyright (c) 2004 The OpenSSL Project. All rights reserved.
@@ -9,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -66,811 +67,762 @@
#include "pcy_int.h"
-
-/* Enable this to print out the complete policy tree at various point during
+/*
+ * Enable this to print out the complete policy tree at various point during
* evaluation.
*/
-/*#define OPENSSL_POLICY_DEBUG*/
+/*
+ * #define OPENSSL_POLICY_DEBUG
+ */
#ifdef OPENSSL_POLICY_DEBUG
static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
- X509_POLICY_NODE *node, int indent)
- {
- if ( (lev->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
- BIO_puts(err, " Not Mapped\n");
- else
- {
- int i;
- STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
- ASN1_OBJECT *oid;
- BIO_puts(err, " Expected: ");
- for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
- {
- oid = sk_ASN1_OBJECT_value(pset, i);
- if (i)
- BIO_puts(err, ", ");
- i2a_ASN1_OBJECT(err, oid);
- }
- BIO_puts(err, "\n");
- }
- }
+ X509_POLICY_NODE *node, int indent)
+{
+ if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
+ BIO_puts(err, " Not Mapped\n");
+ else {
+ int i;
+ STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
+ ASN1_OBJECT *oid;
+ BIO_puts(err, " Expected: ");
+ for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
+ oid = sk_ASN1_OBJECT_value(pset, i);
+ if (i)
+ BIO_puts(err, ", ");
+ i2a_ASN1_OBJECT(err, oid);
+ }
+ BIO_puts(err, "\n");
+ }
+}
static void tree_print(char *str, X509_POLICY_TREE *tree,
- X509_POLICY_LEVEL *curr)
- {
- X509_POLICY_LEVEL *plev;
- X509_POLICY_NODE *node;
- int i;
- BIO *err;
- err = BIO_new_fp(stderr, BIO_NOCLOSE);
- if (!curr)
- curr = tree->levels + tree->nlevel;
- else
- curr++;
- BIO_printf(err, "Level print after %s\n", str);
- BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
- for (plev = tree->levels; plev != curr; plev++)
- {
- BIO_printf(err, "Level %ld, flags = %x\n",
- plev - tree->levels, plev->flags);
- for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
- {
- node = sk_X509_POLICY_NODE_value(plev->nodes, i);
- X509_POLICY_NODE_print(err, node, 2);
- expected_print(err, plev, node, 2);
- BIO_printf(err, " Flags: %x\n", node->data->flags);
- }
- if (plev->anyPolicy)
- X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
- }
-
- BIO_free(err);
-
- }
+ X509_POLICY_LEVEL *curr)
+{
+ X509_POLICY_LEVEL *plev;
+ X509_POLICY_NODE *node;
+ int i;
+ BIO *err;
+ err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ if (!curr)
+ curr = tree->levels + tree->nlevel;
+ else
+ curr++;
+ BIO_printf(err, "Level print after %s\n", str);
+ BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
+ for (plev = tree->levels; plev != curr; plev++) {
+ BIO_printf(err, "Level %ld, flags = %x\n",
+ plev - tree->levels, plev->flags);
+ for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(plev->nodes, i);
+ X509_POLICY_NODE_print(err, node, 2);
+ expected_print(err, plev, node, 2);
+ BIO_printf(err, " Flags: %x\n", node->data->flags);
+ }
+ if (plev->anyPolicy)
+ X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
+ }
+
+ BIO_free(err);
+
+}
#else
-#define tree_print(a,b,c) /* */
+# define tree_print(a,b,c) /* */
#endif
-/* Initialize policy tree. Return values:
- * 0 Some internal error occured.
- * -1 Inconsistent or invalid extensions in certificates.
- * 1 Tree initialized OK.
- * 2 Policy tree is empty.
- * 5 Tree OK and requireExplicitPolicy true.
- * 6 Tree empty and requireExplicitPolicy true.
+/*
+ * Initialize policy tree. Return values: 0 Some internal error occured. -1
+ * Inconsistent or invalid extensions in certificates. 1 Tree initialized
+ * OK. 2 Policy tree is empty. 5 Tree OK and requireExplicitPolicy true. 6
+ * Tree empty and requireExplicitPolicy true.
*/
static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
- unsigned int flags)
- {
- X509_POLICY_TREE *tree;
- X509_POLICY_LEVEL *level;
- const X509_POLICY_CACHE *cache;
- X509_POLICY_DATA *data = NULL;
- X509 *x;
- int ret = 1;
- int i, n;
- int explicit_policy;
- int any_skip;
- int map_skip;
- *ptree = NULL;
- n = sk_X509_num(certs);
+ unsigned int flags)
+{
+ X509_POLICY_TREE *tree;
+ X509_POLICY_LEVEL *level;
+ const X509_POLICY_CACHE *cache;
+ X509_POLICY_DATA *data = NULL;
+ X509 *x;
+ int ret = 1;
+ int i, n;
+ int explicit_policy;
+ int any_skip;
+ int map_skip;
+ *ptree = NULL;
+ n = sk_X509_num(certs);
#if 0
- /* Disable policy mapping for now... */
- flags |= X509_V_FLAG_INHIBIT_MAP;
+ /* Disable policy mapping for now... */
+ flags |= X509_V_FLAG_INHIBIT_MAP;
#endif
- if (flags & X509_V_FLAG_EXPLICIT_POLICY)
- explicit_policy = 0;
- else
- explicit_policy = n + 1;
-
- if (flags & X509_V_FLAG_INHIBIT_ANY)
- any_skip = 0;
- else
- any_skip = n + 1;
-
- if (flags & X509_V_FLAG_INHIBIT_MAP)
- map_skip = 0;
- else
- map_skip = n + 1;
-
- /* Can't do anything with just a trust anchor */
- if (n == 1)
- return 1;
- /* First setup policy cache in all certificates apart from the
- * trust anchor. Note any bad cache results on the way. Also can
- * calculate explicit_policy value at this point.
- */
- for (i = n - 2; i >= 0; i--)
- {
- x = sk_X509_value(certs, i);
- X509_check_purpose(x, -1, -1);
- cache = policy_cache_set(x);
- /* If cache NULL something bad happened: return immediately */
- if (cache == NULL)
- return 0;
- /* If inconsistent extensions keep a note of it but continue */
- if (x->ex_flags & EXFLAG_INVALID_POLICY)
- ret = -1;
- /* Otherwise if we have no data (hence no CertificatePolicies)
- * and haven't already set an inconsistent code note it.
- */
- else if ((ret == 1) && !cache->data)
- ret = 2;
- if (explicit_policy > 0)
- {
- if (!(x->ex_flags & EXFLAG_SI))
- explicit_policy--;
- if ((cache->explicit_skip != -1)
- && (cache->explicit_skip < explicit_policy))
- explicit_policy = cache->explicit_skip;
- }
- }
-
- if (ret != 1)
- {
- if (ret == 2 && !explicit_policy)
- return 6;
- return ret;
- }
-
-
- /* If we get this far initialize the tree */
-
- tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
-
- if (!tree)
- return 0;
-
- tree->flags = 0;
- tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
- tree->nlevel = 0;
- tree->extra_data = NULL;
- tree->auth_policies = NULL;
- tree->user_policies = NULL;
-
- if (!tree->levels)
- {
- OPENSSL_free(tree);
- return 0;
- }
-
- memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
-
- tree->nlevel = n;
-
- level = tree->levels;
-
- /* Root data: initialize to anyPolicy */
-
- data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
-
- if (!data || !level_add_node(level, data, NULL, tree))
- goto bad_tree;
-
- for (i = n - 2; i >= 0; i--)
- {
- level++;
- x = sk_X509_value(certs, i);
- cache = policy_cache_set(x);
- level->cert = X509_up_ref(x);
-
- if (!cache->anyPolicy)
- level->flags |= X509_V_FLAG_INHIBIT_ANY;
-
- /* Determine inhibit any and inhibit map flags */
- if (any_skip == 0)
- {
- /* Any matching allowed if certificate is self
- * issued and not the last in the chain.
- */
- if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
- level->flags |= X509_V_FLAG_INHIBIT_ANY;
- }
- else
- {
- if (!(x->ex_flags & EXFLAG_SI))
- any_skip--;
- if ((cache->any_skip >= 0)
- && (cache->any_skip < any_skip))
- any_skip = cache->any_skip;
- }
-
- if (map_skip == 0)
- level->flags |= X509_V_FLAG_INHIBIT_MAP;
- else
- {
- if (!(x->ex_flags & EXFLAG_SI))
- map_skip--;
- if ((cache->map_skip >= 0)
- && (cache->map_skip < map_skip))
- map_skip = cache->map_skip;
- }
-
- }
-
- *ptree = tree;
-
- if (explicit_policy)
- return 1;
- else
- return 5;
-
- bad_tree:
-
- X509_policy_tree_free(tree);
-
- return 0;
-
- }
+ if (flags & X509_V_FLAG_EXPLICIT_POLICY)
+ explicit_policy = 0;
+ else
+ explicit_policy = n + 1;
+
+ if (flags & X509_V_FLAG_INHIBIT_ANY)
+ any_skip = 0;
+ else
+ any_skip = n + 1;
+
+ if (flags & X509_V_FLAG_INHIBIT_MAP)
+ map_skip = 0;
+ else
+ map_skip = n + 1;
+
+ /* Can't do anything with just a trust anchor */
+ if (n == 1)
+ return 1;
+ /*
+ * First setup policy cache in all certificates apart from the trust
+ * anchor. Note any bad cache results on the way. Also can calculate
+ * explicit_policy value at this point.
+ */
+ for (i = n - 2; i >= 0; i--) {
+ x = sk_X509_value(certs, i);
+ X509_check_purpose(x, -1, -1);
+ cache = policy_cache_set(x);
+ /* If cache NULL something bad happened: return immediately */
+ if (cache == NULL)
+ return 0;
+ /*
+ * If inconsistent extensions keep a note of it but continue
+ */
+ if (x->ex_flags & EXFLAG_INVALID_POLICY)
+ ret = -1;
+ /*
+ * Otherwise if we have no data (hence no CertificatePolicies) and
+ * haven't already set an inconsistent code note it.
+ */
+ else if ((ret == 1) && !cache->data)
+ ret = 2;
+ if (explicit_policy > 0) {
+ if (!(x->ex_flags & EXFLAG_SI))
+ explicit_policy--;
+ if ((cache->explicit_skip != -1)
+ && (cache->explicit_skip < explicit_policy))
+ explicit_policy = cache->explicit_skip;
+ }
+ }
+
+ if (ret != 1) {
+ if (ret == 2 && !explicit_policy)
+ return 6;
+ return ret;
+ }
+
+ /* If we get this far initialize the tree */
+
+ tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
+
+ if (!tree)
+ return 0;
+
+ tree->flags = 0;
+ tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
+ tree->nlevel = 0;
+ tree->extra_data = NULL;
+ tree->auth_policies = NULL;
+ tree->user_policies = NULL;
+
+ if (!tree->levels) {
+ OPENSSL_free(tree);
+ return 0;
+ }
+
+ memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
+
+ tree->nlevel = n;
+
+ level = tree->levels;
+
+ /* Root data: initialize to anyPolicy */
+
+ data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
+
+ if (!data || !level_add_node(level, data, NULL, tree))
+ goto bad_tree;
+
+ for (i = n - 2; i >= 0; i--) {
+ level++;
+ x = sk_X509_value(certs, i);
+ cache = policy_cache_set(x);
+ level->cert = X509_up_ref(x);
+
+ if (!cache->anyPolicy)
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+
+ /* Determine inhibit any and inhibit map flags */
+ if (any_skip == 0) {
+ /*
+ * Any matching allowed if certificate is self issued and not the
+ * last in the chain.
+ */
+ if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+ } else {
+ if (!(x->ex_flags & EXFLAG_SI))
+ any_skip--;
+ if ((cache->any_skip >= 0)
+ && (cache->any_skip < any_skip))
+ any_skip = cache->any_skip;
+ }
+
+ if (map_skip == 0)
+ level->flags |= X509_V_FLAG_INHIBIT_MAP;
+ else {
+ if (!(x->ex_flags & EXFLAG_SI))
+ map_skip--;
+ if ((cache->map_skip >= 0)
+ && (cache->map_skip < map_skip))
+ map_skip = cache->map_skip;
+ }
+
+ }
+
+ *ptree = tree;
+
+ if (explicit_policy)
+ return 1;
+ else
+ return 5;
+
+ bad_tree:
+
+ X509_policy_tree_free(tree);
+
+ return 0;
+
+}
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
- const X509_POLICY_DATA *data)
- {
- X509_POLICY_LEVEL *last = curr - 1;
- X509_POLICY_NODE *node;
- int matched = 0;
- size_t i;
- /* Iterate through all in nodes linking matches */
- for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
- {
- node = sk_X509_POLICY_NODE_value(last->nodes, i);
- if (policy_node_match(last, node, data->valid_policy))
- {
- if (!level_add_node(curr, data, node, NULL))
- return 0;
- matched = 1;
- }
- }
- if (!matched && last->anyPolicy)
- {
- if (!level_add_node(curr, data, last->anyPolicy, NULL))
- return 0;
- }
- return 1;
- }
-
-/* This corresponds to RFC3280 6.1.3(d)(1):
- * link any data from CertificatePolicies onto matching parent
- * or anyPolicy if no match.
+ const X509_POLICY_DATA *data)
+{
+ X509_POLICY_LEVEL *last = curr - 1;
+ X509_POLICY_NODE *node;
+ int matched = 0;
+ size_t i;
+ /* Iterate through all in nodes linking matches */
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(last->nodes, i);
+ if (policy_node_match(last, node, data->valid_policy)) {
+ if (!level_add_node(curr, data, node, NULL))
+ return 0;
+ matched = 1;
+ }
+ }
+ if (!matched && last->anyPolicy) {
+ if (!level_add_node(curr, data, last->anyPolicy, NULL))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This corresponds to RFC3280 6.1.3(d)(1): link any data from
+ * CertificatePolicies onto matching parent or anyPolicy if no match.
*/
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache)
- {
- size_t i;
- X509_POLICY_DATA *data;
-
- for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
- {
- data = sk_X509_POLICY_DATA_value(cache->data, i);
- /* If a node is mapped any it doesn't have a corresponding
- * CertificatePolicies entry.
- * However such an identical node would be created
- * if anyPolicy matching is enabled because there would be
- * no match with the parent valid_policy_set. So we create
- * link because then it will have the mapping flags
- * right and we can prune it later.
- */
+ const X509_POLICY_CACHE *cache)
+{
+ size_t i;
+ X509_POLICY_DATA *data;
+
+ for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
+ data = sk_X509_POLICY_DATA_value(cache->data, i);
+ /*
+ * If a node is mapped any it doesn't have a corresponding
+ * CertificatePolicies entry. However such an identical node would
+ * be created if anyPolicy matching is enabled because there would be
+ * no match with the parent valid_policy_set. So we create link
+ * because then it will have the mapping flags right and we can prune
+ * it later.
+ */
#if 0
- if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
- && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
- continue;
+ if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
+ && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
+ continue;
#endif
- /* Look for matching nodes in previous level */
- if (!tree_link_matching_nodes(curr, data))
- return 0;
- }
- return 1;
- }
-
-/* This corresponds to RFC3280 6.1.3(d)(2):
- * Create new data for any unmatched policies in the parent and link
- * to anyPolicy.
+ /* Look for matching nodes in previous level */
+ if (!tree_link_matching_nodes(curr, data))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
+ * policies in the parent and link to anyPolicy.
*/
static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id,
- X509_POLICY_NODE *node,
- X509_POLICY_TREE *tree)
- {
- X509_POLICY_DATA *data;
- if (id == NULL)
- id = node->data->valid_policy;
- /* Create a new node with qualifiers from anyPolicy and
- * id from unmatched node.
- */
- data = policy_data_new(NULL, id, node_critical(node));
-
- if (data == NULL)
- return 0;
- /* Curr may not have anyPolicy */
- data->qualifier_set = cache->anyPolicy->qualifier_set;
- data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (!level_add_node(curr, data, node, tree))
- {
- policy_data_free(data);
- return 0;
- }
-
- return 1;
- }
+ const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id,
+ X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+ X509_POLICY_DATA *data;
+ if (id == NULL)
+ id = node->data->valid_policy;
+ /*
+ * Create a new node with qualifiers from anyPolicy and id from unmatched
+ * node.
+ */
+ data = policy_data_new(NULL, id, node_critical(node));
+
+ if (data == NULL)
+ return 0;
+ /* Curr may not have anyPolicy */
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!level_add_node(curr, data, node, tree)) {
+ policy_data_free(data);
+ return 0;
+ }
+
+ return 1;
+}
static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- X509_POLICY_NODE *node,
- X509_POLICY_TREE *tree)
- {
- const X509_POLICY_LEVEL *last = curr - 1;
- size_t i;
-
- if ( (last->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
- {
- /* If no policy mapping: matched if one child present */
- if (node->nchild)
- return 1;
- if (!tree_add_unmatched(curr, cache, NULL, node, tree))
- return 0;
- /* Add it */
- }
- else
- {
- /* If mapping: matched if one child per expected policy set */
- STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
- if ((size_t) node->nchild == sk_ASN1_OBJECT_num(expset))
- return 1;
- /* Locate unmatched nodes */
- for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
- {
- ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
- if (level_find_node(curr, node, oid))
- continue;
- if (!tree_add_unmatched(curr, cache, oid, node, tree))
- return 0;
- }
-
- }
-
- return 1;
-
- }
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+ const X509_POLICY_LEVEL *last = curr - 1;
+ size_t i;
+
+ if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
+ /* If no policy mapping: matched if one child present */
+ if (node->nchild)
+ return 1;
+ if (!tree_add_unmatched(curr, cache, NULL, node, tree))
+ return 0;
+ /* Add it */
+ } else {
+ /* If mapping: matched if one child per expected policy set */
+ STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
+ if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset))
+ return 1;
+ /* Locate unmatched nodes */
+ for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
+ ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
+ if (level_find_node(curr, node, oid))
+ continue;
+ if (!tree_add_unmatched(curr, cache, oid, node, tree))
+ return 0;
+ }
+
+ }
+
+ return 1;
+
+}
static int tree_link_any(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- X509_POLICY_TREE *tree)
- {
- size_t i;
- /*X509_POLICY_DATA *data;*/
- X509_POLICY_NODE *node;
- X509_POLICY_LEVEL *last = curr - 1;
-
- for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
- {
- node = sk_X509_POLICY_NODE_value(last->nodes, i);
-
- if (!tree_link_unmatched(curr, cache, node, tree))
- return 0;
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_TREE *tree)
+{
+ size_t i;
+ /*
+ * X509_POLICY_DATA *data;
+ */
+ X509_POLICY_NODE *node;
+ X509_POLICY_LEVEL *last = curr - 1;
+
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(last->nodes, i);
+
+ if (!tree_link_unmatched(curr, cache, node, tree))
+ return 0;
#if 0
- /* Skip any node with any children: we only want unmathced
- * nodes.
- *
- * Note: need something better for policy mapping
- * because each node may have multiple children
- */
- if (node->nchild)
- continue;
-
- /* Create a new node with qualifiers from anyPolicy and
- * id from unmatched node.
- */
- data = policy_data_new(NULL, node->data->valid_policy,
- node_critical(node));
-
- if (data == NULL)
- return 0;
- /* Curr may not have anyPolicy */
- data->qualifier_set = cache->anyPolicy->qualifier_set;
- data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (!level_add_node(curr, data, node, tree))
- {
- policy_data_free(data);
- return 0;
- }
-
+ /*
+ * Skip any node with any children: we only want unmathced nodes.
+ * Note: need something better for policy mapping because each node
+ * may have multiple children
+ */
+ if (node->nchild)
+ continue;
+
+ /*
+ * Create a new node with qualifiers from anyPolicy and id from
+ * unmatched node.
+ */
+ data = policy_data_new(NULL, node->data->valid_policy,
+ node_critical(node));
+
+ if (data == NULL)
+ return 0;
+ /* Curr may not have anyPolicy */
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!level_add_node(curr, data, node, tree)) {
+ policy_data_free(data);
+ return 0;
+ }
#endif
- }
- /* Finally add link to anyPolicy */
- if (last->anyPolicy)
- {
- if (!level_add_node(curr, cache->anyPolicy,
- last->anyPolicy, NULL))
- return 0;
- }
- return 1;
- }
-
-/* Prune the tree: delete any child mapped child data on the current level
+ }
+ /* Finally add link to anyPolicy */
+ if (last->anyPolicy) {
+ if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Prune the tree: delete any child mapped child data on the current level
* then proceed up the tree deleting any data with no children. If we ever
* have no data on a level we can halt because the tree will be empty.
*/
static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
- {
- STACK_OF(X509_POLICY_NODE) *nodes;
- X509_POLICY_NODE *node;
- int i;
- nodes = curr->nodes;
- if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
- {
- for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
- {
- node = sk_X509_POLICY_NODE_value(nodes, i);
- /* Delete any mapped data: see RFC3280 XXXX */
- if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
- {
- node->parent->nchild--;
- OPENSSL_free(node);
- (void)sk_X509_POLICY_NODE_delete(nodes,i);
- }
- }
- }
-
- for(;;) {
- --curr;
- nodes = curr->nodes;
- for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
- {
- node = sk_X509_POLICY_NODE_value(nodes, i);
- if (node->nchild == 0)
- {
- node->parent->nchild--;
- OPENSSL_free(node);
- (void)sk_X509_POLICY_NODE_delete(nodes, i);
- }
- }
- if (curr->anyPolicy && !curr->anyPolicy->nchild)
- {
- if (curr->anyPolicy->parent)
- curr->anyPolicy->parent->nchild--;
- OPENSSL_free(curr->anyPolicy);
- curr->anyPolicy = NULL;
- }
- if (curr == tree->levels)
- {
- /* If we zapped anyPolicy at top then tree is empty */
- if (!curr->anyPolicy)
- return 2;
- return 1;
- }
- }
-
- }
+{
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ X509_POLICY_NODE *node;
+ int i;
+ nodes = curr->nodes;
+ if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ /* Delete any mapped data: see RFC3280 XXXX */
+ if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes, i);
+ }
+ }
+ }
+
+ for (;;) {
+ --curr;
+ nodes = curr->nodes;
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ if (node->nchild == 0) {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes, i);
+ }
+ }
+ if (curr->anyPolicy && !curr->anyPolicy->nchild) {
+ if (curr->anyPolicy->parent)
+ curr->anyPolicy->parent->nchild--;
+ OPENSSL_free(curr->anyPolicy);
+ curr->anyPolicy = NULL;
+ }
+ if (curr == tree->levels) {
+ /* If we zapped anyPolicy at top then tree is empty */
+ if (!curr->anyPolicy)
+ return 2;
+ return 1;
+ }
+ }
+
+}
static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
- X509_POLICY_NODE *pcy)
- {
- if (!*pnodes)
- {
- *pnodes = policy_node_cmp_new();
- if (!*pnodes)
- return 0;
- }
- else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
- return 1;
-
- if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
- return 0;
-
- return 1;
-
- }
-
-/* Calculate the authority set based on policy tree.
- * The 'pnodes' parameter is used as a store for the set of policy nodes
- * used to calculate the user set. If the authority set is not anyPolicy
- * then pnodes will just point to the authority set. If however the authority
- * set is anyPolicy then the set of valid policies (other than anyPolicy)
- * is store in pnodes. The return value of '2' is used in this case to indicate
- * that pnodes should be freed.
+ X509_POLICY_NODE *pcy)
+{
+ if (!*pnodes) {
+ *pnodes = policy_node_cmp_new();
+ if (!*pnodes)
+ return 0;
+ } else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
+ return 1;
+
+ if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
+ return 0;
+
+ return 1;
+
+}
+
+/*
+ * Calculate the authority set based on policy tree. The 'pnodes' parameter
+ * is used as a store for the set of policy nodes used to calculate the user
+ * set. If the authority set is not anyPolicy then pnodes will just point to
+ * the authority set. If however the authority set is anyPolicy then the set
+ * of valid policies (other than anyPolicy) is store in pnodes. The return
+ * value of '2' is used in this case to indicate that pnodes should be freed.
*/
static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
- STACK_OF(X509_POLICY_NODE) **pnodes)
- {
- X509_POLICY_LEVEL *curr;
- X509_POLICY_NODE *node, *anyptr;
- STACK_OF(X509_POLICY_NODE) **addnodes;
- int i;
- size_t j;
- curr = tree->levels + tree->nlevel - 1;
-
- /* If last level contains anyPolicy set is anyPolicy */
- if (curr->anyPolicy)
- {
- if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
- return 0;
- addnodes = pnodes;
- }
- else
- /* Add policies to authority set */
- addnodes = &tree->auth_policies;
-
- curr = tree->levels;
- for (i = 1; i < tree->nlevel; i++)
- {
- /* If no anyPolicy node on this this level it can't
- * appear on lower levels so end search.
- */
- if (!(anyptr = curr->anyPolicy))
- break;
- curr++;
- for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
- {
- node = sk_X509_POLICY_NODE_value(curr->nodes, j);
- if ((node->parent == anyptr)
- && !tree_add_auth_node(addnodes, node))
- return 0;
- }
- }
-
- if (addnodes == pnodes)
- return 2;
-
- *pnodes = tree->auth_policies;
-
- return 1;
- }
+ STACK_OF(X509_POLICY_NODE) **pnodes)
+{
+ X509_POLICY_LEVEL *curr;
+ X509_POLICY_NODE *node, *anyptr;
+ STACK_OF(X509_POLICY_NODE) **addnodes;
+ int i;
+ size_t j;
+ curr = tree->levels + tree->nlevel - 1;
+
+ /* If last level contains anyPolicy set is anyPolicy */
+ if (curr->anyPolicy) {
+ if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
+ return 0;
+ addnodes = pnodes;
+ } else
+ /* Add policies to authority set */
+ addnodes = &tree->auth_policies;
+
+ curr = tree->levels;
+ for (i = 1; i < tree->nlevel; i++) {
+ /*
+ * If no anyPolicy node on this this level it can't appear on lower
+ * levels so end search.
+ */
+ if (!(anyptr = curr->anyPolicy))
+ break;
+ curr++;
+ for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
+ node = sk_X509_POLICY_NODE_value(curr->nodes, j);
+ if ((node->parent == anyptr)
+ && !tree_add_auth_node(addnodes, node))
+ return 0;
+ }
+ }
+
+ if (addnodes == pnodes)
+ return 2;
+
+ *pnodes = tree->auth_policies;
+
+ return 1;
+}
static int tree_calculate_user_set(X509_POLICY_TREE *tree,
- STACK_OF(ASN1_OBJECT) *policy_oids,
- STACK_OF(X509_POLICY_NODE) *auth_nodes)
- {
- size_t i;
- X509_POLICY_NODE *node;
- ASN1_OBJECT *oid;
-
- X509_POLICY_NODE *anyPolicy;
- X509_POLICY_DATA *extra;
-
- /* Check if anyPolicy present in authority constrained policy set:
- * this will happen if it is a leaf node.
- */
-
- if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
- return 1;
-
- anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
-
- for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
- {
- oid = sk_ASN1_OBJECT_value(policy_oids, i);
- if (OBJ_obj2nid(oid) == NID_any_policy)
- {
- tree->flags |= POLICY_FLAG_ANY_POLICY;
- return 1;
- }
- }
-
- for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
- {
- oid = sk_ASN1_OBJECT_value(policy_oids, i);
- node = tree_find_sk(auth_nodes, oid);
- if (!node)
- {
- if (!anyPolicy)
- continue;
- /* Create a new node with policy ID from user set
- * and qualifiers from anyPolicy.
- */
- extra = policy_data_new(NULL, oid,
- node_critical(anyPolicy));
- if (!extra)
- return 0;
- extra->qualifier_set = anyPolicy->data->qualifier_set;
- extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
- | POLICY_DATA_FLAG_EXTRA_NODE;
- node = level_add_node(NULL, extra, anyPolicy->parent,
- tree);
- }
- if (!tree->user_policies)
- {
- tree->user_policies = sk_X509_POLICY_NODE_new_null();
- if (!tree->user_policies)
- return 1;
- }
- if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
- return 0;
- }
- return 1;
-
- }
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ STACK_OF(X509_POLICY_NODE) *auth_nodes)
+{
+ size_t i;
+ X509_POLICY_NODE *node;
+ ASN1_OBJECT *oid;
+
+ X509_POLICY_NODE *anyPolicy;
+ X509_POLICY_DATA *extra;
+
+ /*
+ * Check if anyPolicy present in authority constrained policy set: this
+ * will happen if it is a leaf node.
+ */
+
+ if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
+ return 1;
+
+ anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ if (OBJ_obj2nid(oid) == NID_any_policy) {
+ tree->flags |= POLICY_FLAG_ANY_POLICY;
+ return 1;
+ }
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ node = tree_find_sk(auth_nodes, oid);
+ if (!node) {
+ if (!anyPolicy)
+ continue;
+ /*
+ * Create a new node with policy ID from user set and qualifiers
+ * from anyPolicy.
+ */
+ extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
+ if (!extra)
+ return 0;
+ extra->qualifier_set = anyPolicy->data->qualifier_set;
+ extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
+ | POLICY_DATA_FLAG_EXTRA_NODE;
+ node = level_add_node(NULL, extra, anyPolicy->parent, tree);
+ }
+ if (!tree->user_policies) {
+ tree->user_policies = sk_X509_POLICY_NODE_new_null();
+ if (!tree->user_policies)
+ return 1;
+ }
+ if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+ return 0;
+ }
+ return 1;
+
+}
static int tree_evaluate(X509_POLICY_TREE *tree)
- {
- int ret, i;
- X509_POLICY_LEVEL *curr = tree->levels + 1;
- const X509_POLICY_CACHE *cache;
-
- for(i = 1; i < tree->nlevel; i++, curr++)
- {
- cache = policy_cache_set(curr->cert);
- if (!tree_link_nodes(curr, cache))
- return 0;
-
- if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
- && !tree_link_any(curr, cache, tree))
- return 0;
- tree_print("before tree_prune()", tree, curr);
- ret = tree_prune(tree, curr);
- if (ret != 1)
- return ret;
- }
-
- return 1;
-
- }
+{
+ int ret, i;
+ X509_POLICY_LEVEL *curr = tree->levels + 1;
+ const X509_POLICY_CACHE *cache;
-static void exnode_free(X509_POLICY_NODE *node)
- {
- if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
- OPENSSL_free(node);
- }
+ for (i = 1; i < tree->nlevel; i++, curr++) {
+ cache = policy_cache_set(curr->cert);
+ if (!tree_link_nodes(curr, cache))
+ return 0;
+
+ if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
+ && !tree_link_any(curr, cache, tree))
+ return 0;
+ tree_print("before tree_prune()", tree, curr);
+ ret = tree_prune(tree, curr);
+ if (ret != 1)
+ return ret;
+ }
+
+ return 1;
+}
+
+static void exnode_free(X509_POLICY_NODE *node)
+{
+ if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
+ OPENSSL_free(node);
+}
void X509_policy_tree_free(X509_POLICY_TREE *tree)
- {
- X509_POLICY_LEVEL *curr;
- int i;
-
- if (!tree)
- return;
-
- sk_X509_POLICY_NODE_free(tree->auth_policies);
- sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
-
- for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
- {
- if (curr->cert)
- X509_free(curr->cert);
- if (curr->nodes)
- sk_X509_POLICY_NODE_pop_free(curr->nodes,
- policy_node_free);
- if (curr->anyPolicy)
- policy_node_free(curr->anyPolicy);
- }
-
- if (tree->extra_data)
- sk_X509_POLICY_DATA_pop_free(tree->extra_data,
- policy_data_free);
-
- OPENSSL_free(tree->levels);
- OPENSSL_free(tree);
-
- }
-
-/* Application policy checking function.
- * Return codes:
- * 0 Internal Error.
- * 1 Successful.
- * -1 One or more certificates contain invalid or inconsistent extensions
- * -2 User constrained policy set empty and requireExplicit true.
+{
+ X509_POLICY_LEVEL *curr;
+ int i;
+
+ if (!tree)
+ return;
+
+ sk_X509_POLICY_NODE_free(tree->auth_policies);
+ sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
+
+ for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
+ if (curr->cert)
+ X509_free(curr->cert);
+ if (curr->nodes)
+ sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
+ if (curr->anyPolicy)
+ policy_node_free(curr->anyPolicy);
+ }
+
+ if (tree->extra_data)
+ sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
+
+ OPENSSL_free(tree->levels);
+ OPENSSL_free(tree);
+
+}
+
+/*
+ * Application policy checking function. Return codes: 0 Internal Error. 1
+ * Successful. -1 One or more certificates contain invalid or inconsistent
+ * extensions -2 User constrained policy set empty and requireExplicit true.
*/
int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
- STACK_OF(X509) *certs,
- STACK_OF(ASN1_OBJECT) *policy_oids,
- unsigned int flags)
- {
- int ret;
- X509_POLICY_TREE *tree = NULL;
- STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
- *ptree = NULL;
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
+{
+ int ret;
+ X509_POLICY_TREE *tree = NULL;
+ STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
+ *ptree = NULL;
- *pexplicit_policy = 0;
- ret = tree_init(&tree, certs, flags);
+ *pexplicit_policy = 0;
+ ret = tree_init(&tree, certs, flags);
- switch (ret)
- {
+ switch (ret) {
- /* Tree empty requireExplicit False: OK */
- case 2:
- return 1;
+ /* Tree empty requireExplicit False: OK */
+ case 2:
+ return 1;
- /* Some internal error */
- case -1:
- return -1;
+ /* Some internal error */
+ case -1:
+ return -1;
- /* Some internal error */
- case 0:
- return 0;
+ /* Some internal error */
+ case 0:
+ return 0;
- /* Tree empty requireExplicit True: Error */
+ /* Tree empty requireExplicit True: Error */
- case 6:
- *pexplicit_policy = 1;
- return -2;
+ case 6:
+ *pexplicit_policy = 1;
+ return -2;
- /* Tree OK requireExplicit True: OK and continue */
- case 5:
- *pexplicit_policy = 1;
- break;
+ /* Tree OK requireExplicit True: OK and continue */
+ case 5:
+ *pexplicit_policy = 1;
+ break;
- /* Tree OK: continue */
+ /* Tree OK: continue */
- case 1:
- if (!tree)
- /*
- * tree_init() returns success and a null tree
- * if it's just looking at a trust anchor.
- * I'm not sure that returning success here is
- * correct, but I'm sure that reporting this
- * as an internal error which our caller
- * interprets as a malloc failure is wrong.
- */
- return 1;
- break;
- }
+ case 1:
+ if (!tree)
+ /*
+ * tree_init() returns success and a null tree
+ * if it's just looking at a trust anchor.
+ * I'm not sure that returning success here is
+ * correct, but I'm sure that reporting this
+ * as an internal error which our caller
+ * interprets as a malloc failure is wrong.
+ */
+ return 1;
+ break;
+ }
- if (!tree) goto error;
- ret = tree_evaluate(tree);
+ if (!tree)
+ goto error;
+ ret = tree_evaluate(tree);
- tree_print("tree_evaluate()", tree, NULL);
+ tree_print("tree_evaluate()", tree, NULL);
- if (ret <= 0)
- goto error;
+ if (ret <= 0)
+ goto error;
- /* Return value 2 means tree empty */
- if (ret == 2)
- {
- X509_policy_tree_free(tree);
- if (*pexplicit_policy)
- return -2;
- else
- return 1;
- }
+ /* Return value 2 means tree empty */
+ if (ret == 2) {
+ X509_policy_tree_free(tree);
+ if (*pexplicit_policy)
+ return -2;
+ else
+ return 1;
+ }
- /* Tree is not empty: continue */
+ /* Tree is not empty: continue */
- ret = tree_calculate_authority_set(tree, &auth_nodes);
+ ret = tree_calculate_authority_set(tree, &auth_nodes);
- if (!ret)
- goto error;
+ if (!ret)
+ goto error;
- if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
- goto error;
-
- if (ret == 2)
- sk_X509_POLICY_NODE_free(auth_nodes);
+ if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
+ goto error;
- if (tree)
- *ptree = tree;
+ if (ret == 2)
+ sk_X509_POLICY_NODE_free(auth_nodes);
- if (*pexplicit_policy)
- {
- nodes = X509_policy_tree_get0_user_policies(tree);
- if (sk_X509_POLICY_NODE_num(nodes) <= 0)
- return -2;
- }
+ if (tree)
+ *ptree = tree;
- return 1;
+ if (*pexplicit_policy) {
+ nodes = X509_policy_tree_get0_user_policies(tree);
+ if (sk_X509_POLICY_NODE_num(nodes) <= 0)
+ return -2;
+ }
- error:
+ return 1;
- X509_policy_tree_free(tree);
+ error:
- return 0;
+ X509_policy_tree_free(tree);
- }
+ return 0;
+}
diff --git a/src/crypto/x509v3/tab_test.c b/src/crypto/x509v3/tab_test.c
index c0e0cb61..19005474 100644
--- a/src/crypto/x509v3/tab_test.c
+++ b/src/crypto/x509v3/tab_test.c
@@ -1,6 +1,7 @@
/* tabtest.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -56,49 +57,52 @@
*
*/
-/* Simple program to check the ext_dat.h is correct and print out
- * problems if it is not.
+/*
+ * Simple program to check the ext_dat.h is correct and print out problems if
+ * it is not.
*/
#include <stdio.h>
#include <openssl/base.h>
#include <openssl/crypto.h>
+#include <openssl/obj.h>
#include <openssl/x509v3.h>
#if !defined(BORINGSSL_SHARED_LIBRARY)
-#include "ext_dat.h"
+# include "ext_dat.h"
#endif
int main(void)
{
#if !defined(BORINGSSL_SHARED_LIBRARY)
- unsigned i;
- int prev = -1, bad = 0;
- const X509V3_EXT_METHOD *const *tmp;
- CRYPTO_library_init();
- i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
- if(i != STANDARD_EXTENSION_COUNT)
- fprintf(stderr, "Extension number invalid expecting %d\n", i);
- tmp = standard_exts;
- for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) {
- if((*tmp)->ext_nid < prev) bad = 1;
- prev = (*tmp)->ext_nid;
-
- }
- if(bad) {
- tmp = standard_exts;
- fprintf(stderr, "Extensions out of order!\n");
- for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
- printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
- return 1;
- } else {
- printf("PASS\n");
- return 0;
- }
+ unsigned i;
+ int prev = -1, bad = 0;
+ const X509V3_EXT_METHOD *const *tmp;
+ CRYPTO_library_init();
+ i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
+ if (i != STANDARD_EXTENSION_COUNT)
+ fprintf(stderr, "Extension number invalid expecting %d\n", i);
+ tmp = standard_exts;
+ for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) {
+ if ((*tmp)->ext_nid < prev)
+ bad = 1;
+ prev = (*tmp)->ext_nid;
+
+ }
+ if (bad) {
+ tmp = standard_exts;
+ fprintf(stderr, "Extensions out of order!\n");
+ for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
+ printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
+ return 1;
+ } else {
+ printf("PASS\n");
+ return 0;
+ }
#else
- /* TODO(davidben): Fix this test in the shared library build. */
- printf("PASS\n");
- return 0;
+ /* TODO(davidben): Fix this test in the shared library build. */
+ printf("PASS\n");
+ return 0;
#endif
}
diff --git a/src/crypto/x509v3/v3_akey.c b/src/crypto/x509v3/v3_akey.c
index 9578a570..4503e615 100644
--- a/src/crypto/x509v3/v3_akey.c
+++ b/src/crypto/x509v3/v3_akey.c
@@ -1,6 +1,7 @@
/* v3_akey.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -65,148 +66,139 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist);
+ AUTHORITY_KEYID *akeyid,
+ STACK_OF(CONF_VALUE)
+ *extlist);
static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
-
-const X509V3_EXT_METHOD v3_akey_id =
- {
- NID_authority_key_identifier,
- X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
- 0,0,0,0,
- 0,0,
- (X509V3_EXT_I2V)i2v_AUTHORITY_KEYID,
- (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
- 0,0,
- NULL
- };
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD v3_akey_id = {
+ NID_authority_key_identifier,
+ X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
+ 0, 0,
+ NULL
+};
static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist)
+ AUTHORITY_KEYID *akeyid,
+ STACK_OF(CONF_VALUE)
+ *extlist)
{
- char *tmp;
- if(akeyid->keyid) {
- tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
- X509V3_add_value("keyid", tmp, &extlist);
- OPENSSL_free(tmp);
- }
- if(akeyid->issuer)
- extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
- if(akeyid->serial) {
- tmp = hex_to_string(akeyid->serial->data,
- akeyid->serial->length);
- X509V3_add_value("serial", tmp, &extlist);
- OPENSSL_free(tmp);
- }
- return extlist;
+ char *tmp;
+ if (akeyid->keyid) {
+ tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
+ X509V3_add_value("keyid", tmp, &extlist);
+ OPENSSL_free(tmp);
+ }
+ if (akeyid->issuer)
+ extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+ if (akeyid->serial) {
+ tmp = hex_to_string(akeyid->serial->data, akeyid->serial->length);
+ X509V3_add_value("serial", tmp, &extlist);
+ OPENSSL_free(tmp);
+ }
+ return extlist;
}
-/* Currently two options:
- * keyid: use the issuers subject keyid, the value 'always' means its is
- * an error if the issuer certificate doesn't have a key id.
- * issuer: use the issuers cert issuer and serial number. The default is
- * to only use this if keyid is not present. With the option 'always'
- * this is always included.
+/*
+ * Currently two options: keyid: use the issuers subject keyid, the value
+ * 'always' means its is an error if the issuer certificate doesn't have a
+ * key id. issuer: use the issuers cert issuer and serial number. The default
+ * is to only use this if keyid is not present. With the option 'always' this
+ * is always included.
*/
static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
- {
- char keyid=0, issuer=0;
- size_t i;
- int j;
- CONF_VALUE *cnf;
- ASN1_OCTET_STRING *ikeyid = NULL;
- X509_NAME *isname = NULL;
- GENERAL_NAMES * gens = NULL;
- GENERAL_NAME *gen = NULL;
- ASN1_INTEGER *serial = NULL;
- X509_EXTENSION *ext;
- X509 *cert;
- AUTHORITY_KEYID *akeyid;
-
- for(i = 0; i < sk_CONF_VALUE_num(values); i++)
- {
- cnf = sk_CONF_VALUE_value(values, i);
- if(!strcmp(cnf->name, "keyid"))
- {
- keyid = 1;
- if(cnf->value && !strcmp(cnf->value, "always"))
- keyid = 2;
- }
- else if(!strcmp(cnf->name, "issuer"))
- {
- issuer = 1;
- if(cnf->value && !strcmp(cnf->value, "always"))
- issuer = 2;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION);
- ERR_add_error_data(2, "name=", cnf->name);
- return NULL;
- }
- }
-
- if(!ctx || !ctx->issuer_cert)
- {
- if(ctx && (ctx->flags==CTX_TEST))
- return AUTHORITY_KEYID_new();
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
- return NULL;
- }
-
- cert = ctx->issuer_cert;
-
- if(keyid)
- {
- j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
- if((j >= 0) && (ext = X509_get_ext(cert, j)))
- ikeyid = X509V3_EXT_d2i(ext);
- if(keyid==2 && !ikeyid)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
- return NULL;
- }
- }
-
- if((issuer && !ikeyid) || (issuer == 2))
- {
- isname = X509_NAME_dup(X509_get_issuer_name(cert));
- serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
- if(!isname || !serial)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
- goto err;
- }
- }
-
- if(!(akeyid = AUTHORITY_KEYID_new())) goto err;
-
- if(isname)
- {
- if(!(gens = sk_GENERAL_NAME_new_null())
- || !(gen = GENERAL_NAME_new())
- || !sk_GENERAL_NAME_push(gens, gen))
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen->type = GEN_DIRNAME;
- gen->d.dirn = isname;
- }
-
- akeyid->issuer = gens;
- akeyid->serial = serial;
- akeyid->keyid = ikeyid;
-
- return akeyid;
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ char keyid = 0, issuer = 0;
+ size_t i;
+ int j;
+ CONF_VALUE *cnf;
+ ASN1_OCTET_STRING *ikeyid = NULL;
+ X509_NAME *isname = NULL;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ASN1_INTEGER *serial = NULL;
+ X509_EXTENSION *ext;
+ X509 *cert;
+ AUTHORITY_KEYID *akeyid;
+
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ cnf = sk_CONF_VALUE_value(values, i);
+ if (!strcmp(cnf->name, "keyid")) {
+ keyid = 1;
+ if (cnf->value && !strcmp(cnf->value, "always"))
+ keyid = 2;
+ } else if (!strcmp(cnf->name, "issuer")) {
+ issuer = 1;
+ if (cnf->value && !strcmp(cnf->value, "always"))
+ issuer = 2;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION);
+ ERR_add_error_data(2, "name=", cnf->name);
+ return NULL;
+ }
+ }
+
+ if (!ctx || !ctx->issuer_cert) {
+ if (ctx && (ctx->flags == CTX_TEST))
+ return AUTHORITY_KEYID_new();
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
+ return NULL;
+ }
+
+ cert = ctx->issuer_cert;
+
+ if (keyid) {
+ j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+ if ((j >= 0) && (ext = X509_get_ext(cert, j)))
+ ikeyid = X509V3_EXT_d2i(ext);
+ if (keyid == 2 && !ikeyid) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
+ return NULL;
+ }
+ }
+
+ if ((issuer && !ikeyid) || (issuer == 2)) {
+ isname = X509_NAME_dup(X509_get_issuer_name(cert));
+ serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+ if (!isname || !serial) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
+ goto err;
+ }
+ }
+
+ if (!(akeyid = AUTHORITY_KEYID_new()))
+ goto err;
+
+ if (isname) {
+ if (!(gens = sk_GENERAL_NAME_new_null())
+ || !(gen = GENERAL_NAME_new())
+ || !sk_GENERAL_NAME_push(gens, gen)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen->type = GEN_DIRNAME;
+ gen->d.dirn = isname;
+ }
+
+ akeyid->issuer = gens;
+ akeyid->serial = serial;
+ akeyid->keyid = ikeyid;
+
+ return akeyid;
err:
- X509_NAME_free(isname);
- M_ASN1_INTEGER_free(serial);
- M_ASN1_OCTET_STRING_free(ikeyid);
- return NULL;
- }
+ X509_NAME_free(isname);
+ M_ASN1_INTEGER_free(serial);
+ M_ASN1_OCTET_STRING_free(ikeyid);
+ return NULL;
+}
diff --git a/src/crypto/x509v3/v3_akeya.c b/src/crypto/x509v3/v3_akeya.c
index 8b72cca2..844dee52 100644
--- a/src/crypto/x509v3/v3_akeya.c
+++ b/src/crypto/x509v3/v3_akeya.c
@@ -1,6 +1,7 @@
/* v3_akey_asn1.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,9 +64,9 @@
ASN1_SEQUENCE(AUTHORITY_KEYID) = {
- ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
- ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
- ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
+ ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
+ ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
} ASN1_SEQUENCE_END(AUTHORITY_KEYID)
IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID)
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
index cfc13486..152bd79f 100644
--- a/src/crypto/x509v3/v3_alt.c
+++ b/src/crypto/x509v3/v3_alt.c
@@ -1,5 +1,6 @@
/* v3_alt.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,560 +64,551 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
const X509V3_EXT_METHOD v3_alt[] = {
-{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_subject_alt,
-NULL, NULL, NULL},
-
-{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_issuer_alt,
-NULL, NULL, NULL},
-
-{ NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-NULL, NULL, NULL, NULL},
+ {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ (X509V3_EXT_V2I)v2i_subject_alt,
+ NULL, NULL, NULL},
+
+ {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ (X509V3_EXT_V2I)v2i_issuer_alt,
+ NULL, NULL, NULL},
+
+ {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ NULL, NULL, NULL, NULL},
};
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
- GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
+ GENERAL_NAMES *gens,
+ STACK_OF(CONF_VALUE) *ret)
{
- size_t i;
- GENERAL_NAME *gen;
- for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- gen = sk_GENERAL_NAME_value(gens, i);
- ret = i2v_GENERAL_NAME(method, gen, ret);
- }
- if(!ret) return sk_CONF_VALUE_new_null();
- return ret;
+ size_t i;
+ GENERAL_NAME *gen;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ ret = i2v_GENERAL_NAME(method, gen, ret);
+ }
+ if (!ret)
+ return sk_CONF_VALUE_new_null();
+ return ret;
}
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
- GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
+ GENERAL_NAME *gen,
+ STACK_OF(CONF_VALUE) *ret)
{
- unsigned char *p;
- char oline[256], htmp[5];
- int i;
- switch (gen->type)
- {
- case GEN_OTHERNAME:
- X509V3_add_value("othername","<unsupported>", &ret);
- break;
-
- case GEN_X400:
- X509V3_add_value("X400Name","<unsupported>", &ret);
- break;
-
- case GEN_EDIPARTY:
- X509V3_add_value("EdiPartyName","<unsupported>", &ret);
- break;
-
- case GEN_EMAIL:
- X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
- break;
-
- case GEN_DNS:
- X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
- break;
-
- case GEN_URI:
- X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
- break;
-
- case GEN_DIRNAME:
- X509_NAME_oneline(gen->d.dirn, oline, 256);
- X509V3_add_value("DirName",oline, &ret);
- break;
-
- case GEN_IPADD:
- p = gen->d.ip->data;
- if(gen->d.ip->length == 4)
- BIO_snprintf(oline, sizeof oline,
- "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- else if(gen->d.ip->length == 16)
- {
- oline[0] = 0;
- for (i = 0; i < 8; i++)
- {
- BIO_snprintf(htmp, sizeof htmp,
- "%X", p[0] << 8 | p[1]);
- p += 2;
- strcat(oline, htmp);
- if (i != 7)
- strcat(oline, ":");
- }
- }
- else
- {
- X509V3_add_value("IP Address","<invalid>", &ret);
- break;
- }
- X509V3_add_value("IP Address",oline, &ret);
- break;
-
- case GEN_RID:
- i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
- X509V3_add_value("Registered ID",oline, &ret);
- break;
- }
- return ret;
+ unsigned char *p;
+ char oline[256], htmp[5];
+ int i;
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ X509V3_add_value("othername", "<unsupported>", &ret);
+ break;
+
+ case GEN_X400:
+ X509V3_add_value("X400Name", "<unsupported>", &ret);
+ break;
+
+ case GEN_EDIPARTY:
+ X509V3_add_value("EdiPartyName", "<unsupported>", &ret);
+ break;
+
+ case GEN_EMAIL:
+ X509V3_add_value_uchar("email", gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_DNS:
+ X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_URI:
+ X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_DIRNAME:
+ X509_NAME_oneline(gen->d.dirn, oline, 256);
+ X509V3_add_value("DirName", oline, &ret);
+ break;
+
+ case GEN_IPADD:
+ p = gen->d.ip->data;
+ if (gen->d.ip->length == 4)
+ BIO_snprintf(oline, sizeof oline,
+ "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ else if (gen->d.ip->length == 16) {
+ oline[0] = 0;
+ for (i = 0; i < 8; i++) {
+ BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]);
+ p += 2;
+ strcat(oline, htmp);
+ if (i != 7)
+ strcat(oline, ":");
+ }
+ } else {
+ X509V3_add_value("IP Address", "<invalid>", &ret);
+ break;
+ }
+ X509V3_add_value("IP Address", oline, &ret);
+ break;
+
+ case GEN_RID:
+ i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
+ X509V3_add_value("Registered ID", oline, &ret);
+ break;
+ }
+ return ret;
}
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{
- unsigned char *p;
- int i;
- switch (gen->type)
- {
- case GEN_OTHERNAME:
- BIO_printf(out, "othername:<unsupported>");
- break;
-
- case GEN_X400:
- BIO_printf(out, "X400Name:<unsupported>");
- break;
-
- case GEN_EDIPARTY:
- /* Maybe fix this: it is supported now */
- BIO_printf(out, "EdiPartyName:<unsupported>");
- break;
-
- case GEN_EMAIL:
- BIO_printf(out, "email:%s",gen->d.ia5->data);
- break;
-
- case GEN_DNS:
- BIO_printf(out, "DNS:%s",gen->d.ia5->data);
- break;
-
- case GEN_URI:
- BIO_printf(out, "URI:%s",gen->d.ia5->data);
- break;
-
- case GEN_DIRNAME:
- BIO_printf(out, "DirName: ");
- X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
- break;
-
- case GEN_IPADD:
- p = gen->d.ip->data;
- if(gen->d.ip->length == 4)
- BIO_printf(out, "IP Address:%d.%d.%d.%d",
- p[0], p[1], p[2], p[3]);
- else if(gen->d.ip->length == 16)
- {
- BIO_printf(out, "IP Address");
- for (i = 0; i < 8; i++)
- {
- BIO_printf(out, ":%X", p[0] << 8 | p[1]);
- p += 2;
- }
- BIO_puts(out, "\n");
- }
- else
- {
- BIO_printf(out,"IP Address:<invalid>");
- break;
- }
- break;
-
- case GEN_RID:
- BIO_printf(out, "Registered ID");
- i2a_ASN1_OBJECT(out, gen->d.rid);
- break;
- }
- return 1;
+ unsigned char *p;
+ int i;
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ BIO_printf(out, "othername:<unsupported>");
+ break;
+
+ case GEN_X400:
+ BIO_printf(out, "X400Name:<unsupported>");
+ break;
+
+ case GEN_EDIPARTY:
+ /* Maybe fix this: it is supported now */
+ BIO_printf(out, "EdiPartyName:<unsupported>");
+ break;
+
+ case GEN_EMAIL:
+ BIO_printf(out, "email:%s", gen->d.ia5->data);
+ break;
+
+ case GEN_DNS:
+ BIO_printf(out, "DNS:%s", gen->d.ia5->data);
+ break;
+
+ case GEN_URI:
+ BIO_printf(out, "URI:%s", gen->d.ia5->data);
+ break;
+
+ case GEN_DIRNAME:
+ BIO_printf(out, "DirName: ");
+ X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
+ break;
+
+ case GEN_IPADD:
+ p = gen->d.ip->data;
+ if (gen->d.ip->length == 4)
+ BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ else if (gen->d.ip->length == 16) {
+ BIO_printf(out, "IP Address");
+ for (i = 0; i < 8; i++) {
+ BIO_printf(out, ":%X", p[0] << 8 | p[1]);
+ p += 2;
+ }
+ BIO_puts(out, "\n");
+ } else {
+ BIO_printf(out, "IP Address:<invalid>");
+ break;
+ }
+ break;
+
+ case GEN_RID:
+ BIO_printf(out, "Registered ID");
+ i2a_ASN1_OBJECT(out, gen->d.rid);
+ break;
+ }
+ return 1;
}
static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
{
- GENERAL_NAMES *gens = NULL;
- CONF_VALUE *cnf;
- size_t i;
- if(!(gens = sk_GENERAL_NAME_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if(!name_cmp(cnf->name, "issuer") && cnf->value &&
- !strcmp(cnf->value, "copy")) {
- if(!copy_issuer(ctx, gens)) goto err;
- } else {
- GENERAL_NAME *gen;
- if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
- goto err;
- sk_GENERAL_NAME_push(gens, gen);
- }
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
+ GENERAL_NAMES *gens = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if (!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!name_cmp(cnf->name, "issuer") && cnf->value &&
+ !strcmp(cnf->value, "copy")) {
+ if (!copy_issuer(ctx, gens))
+ goto err;
+ } else {
+ GENERAL_NAME *gen;
+ if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
}
/* Append subject altname of issuer to issuer alt name of subject */
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
{
- GENERAL_NAMES *ialt;
- GENERAL_NAME *gen;
- X509_EXTENSION *ext;
- int i;
- size_t j;
- if(ctx && (ctx->flags == CTX_TEST)) return 1;
- if(!ctx || !ctx->issuer_cert) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
- goto err;
- }
- i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
- if(i < 0) return 1;
- if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
- !(ialt = X509V3_EXT_d2i(ext)) ) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
- goto err;
- }
-
- for(j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
- gen = sk_GENERAL_NAME_value(ialt, j);
- if(!sk_GENERAL_NAME_push(gens, gen)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- sk_GENERAL_NAME_free(ialt);
-
- return 1;
-
- err:
- return 0;
-
+ GENERAL_NAMES *ialt;
+ GENERAL_NAME *gen;
+ X509_EXTENSION *ext;
+ int i;
+ size_t j;
+ if (ctx && (ctx->flags == CTX_TEST))
+ return 1;
+ if (!ctx || !ctx->issuer_cert) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
+ goto err;
+ }
+ i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
+ if (i < 0)
+ return 1;
+ if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
+ !(ialt = X509V3_EXT_d2i(ext))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
+ goto err;
+ }
+
+ for (j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
+ gen = sk_GENERAL_NAME_value(ialt, j);
+ if (!sk_GENERAL_NAME_push(gens, gen)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ sk_GENERAL_NAME_free(ialt);
+
+ return 1;
+
+ err:
+ return 0;
+
}
static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
{
- GENERAL_NAMES *gens = NULL;
- CONF_VALUE *cnf;
- size_t i;
- if(!(gens = sk_GENERAL_NAME_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if(!name_cmp(cnf->name, "email") && cnf->value &&
- !strcmp(cnf->value, "copy")) {
- if(!copy_email(ctx, gens, 0)) goto err;
- } else if(!name_cmp(cnf->name, "email") && cnf->value &&
- !strcmp(cnf->value, "move")) {
- if(!copy_email(ctx, gens, 1)) goto err;
- } else {
- GENERAL_NAME *gen;
- if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
- goto err;
- sk_GENERAL_NAME_push(gens, gen);
- }
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
+ GENERAL_NAMES *gens = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if (!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!name_cmp(cnf->name, "email") && cnf->value &&
+ !strcmp(cnf->value, "copy")) {
+ if (!copy_email(ctx, gens, 0))
+ goto err;
+ } else if (!name_cmp(cnf->name, "email") && cnf->value &&
+ !strcmp(cnf->value, "move")) {
+ if (!copy_email(ctx, gens, 1))
+ goto err;
+ } else {
+ GENERAL_NAME *gen;
+ if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
}
-/* Copy any email addresses in a certificate or request to
- * GENERAL_NAMES
+/*
+ * Copy any email addresses in a certificate or request to GENERAL_NAMES
*/
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
{
- X509_NAME *nm;
- ASN1_IA5STRING *email = NULL;
- X509_NAME_ENTRY *ne;
- GENERAL_NAME *gen = NULL;
- int i;
- if(ctx != NULL && ctx->flags == CTX_TEST)
- return 1;
- if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
- goto err;
- }
- /* Find the subject name */
- if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
- else nm = X509_REQ_get_subject_name(ctx->subject_req);
-
- /* Now add any email address(es) to STACK */
- i = -1;
- while((i = X509_NAME_get_index_by_NID(nm,
- NID_pkcs9_emailAddress, i)) >= 0) {
- ne = X509_NAME_get_entry(nm, i);
- email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
- if (move_p)
- {
- X509_NAME_delete_entry(nm, i);
- X509_NAME_ENTRY_free(ne);
- i--;
- }
- if(!email || !(gen = GENERAL_NAME_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen->d.ia5 = email;
- email = NULL;
- gen->type = GEN_EMAIL;
- if(!sk_GENERAL_NAME_push(gens, gen)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen = NULL;
- }
-
-
- return 1;
-
- err:
- GENERAL_NAME_free(gen);
- M_ASN1_IA5STRING_free(email);
- return 0;
-
+ X509_NAME *nm;
+ ASN1_IA5STRING *email = NULL;
+ X509_NAME_ENTRY *ne;
+ GENERAL_NAME *gen = NULL;
+ int i;
+ if (ctx != NULL && ctx->flags == CTX_TEST)
+ return 1;
+ if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
+ goto err;
+ }
+ /* Find the subject name */
+ if (ctx->subject_cert)
+ nm = X509_get_subject_name(ctx->subject_cert);
+ else
+ nm = X509_REQ_get_subject_name(ctx->subject_req);
+
+ /* Now add any email address(es) to STACK */
+ i = -1;
+ while ((i = X509_NAME_get_index_by_NID(nm,
+ NID_pkcs9_emailAddress, i)) >= 0) {
+ ne = X509_NAME_get_entry(nm, i);
+ email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
+ if (move_p) {
+ X509_NAME_delete_entry(nm, i);
+ X509_NAME_ENTRY_free(ne);
+ i--;
+ }
+ if (!email || !(gen = GENERAL_NAME_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen->d.ia5 = email;
+ email = NULL;
+ gen->type = GEN_EMAIL;
+ if (!sk_GENERAL_NAME_push(gens, gen)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen = NULL;
+ }
+
+ return 1;
+
+ err:
+ GENERAL_NAME_free(gen);
+ M_ASN1_IA5STRING_free(email);
+ return 0;
+
}
GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
{
- GENERAL_NAME *gen;
- GENERAL_NAMES *gens = NULL;
- CONF_VALUE *cnf;
- size_t i;
- if(!(gens = sk_GENERAL_NAME_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
- sk_GENERAL_NAME_push(gens, gen);
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
+ GENERAL_NAME *gen;
+ GENERAL_NAMES *gens = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if (!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
}
-GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- CONF_VALUE *cnf)
- {
- return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
- }
+GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf)
+{
+ return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+}
GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- int gen_type, char *value, int is_nc)
- {
- char is_string = 0;
- GENERAL_NAME *gen = NULL;
-
- if(!value)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
- return NULL;
- }
-
- if (out)
- gen = out;
- else
- {
- gen = GENERAL_NAME_new();
- if(gen == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- }
-
- switch (gen_type)
- {
- case GEN_URI:
- case GEN_EMAIL:
- case GEN_DNS:
- is_string = 1;
- break;
-
- case GEN_RID:
- {
- ASN1_OBJECT *obj;
- if(!(obj = OBJ_txt2obj(value,0)))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
- gen->d.rid = obj;
- }
- break;
-
- case GEN_IPADD:
- if (is_nc)
- gen->d.ip = a2i_IPADDRESS_NC(value);
- else
- gen->d.ip = a2i_IPADDRESS(value);
- if(gen->d.ip == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
- break;
-
- case GEN_DIRNAME:
- if (!do_dirname(gen, value, ctx))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
- goto err;
- }
- break;
-
- case GEN_OTHERNAME:
- if (!do_othername(gen, value, ctx))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
- goto err;
- }
- break;
- default:
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
- goto err;
- }
-
- if(is_string)
- {
- if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
- !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
- strlen(value)))
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- gen->type = gen_type;
-
- return gen;
-
- err:
- if (!out)
- GENERAL_NAME_free(gen);
- return NULL;
- }
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, int gen_type, char *value,
+ int is_nc)
+{
+ char is_string = 0;
+ GENERAL_NAME *gen = NULL;
+
+ if (!value) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if (out)
+ gen = out;
+ else {
+ gen = GENERAL_NAME_new();
+ if (gen == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+
+ switch (gen_type) {
+ case GEN_URI:
+ case GEN_EMAIL:
+ case GEN_DNS:
+ is_string = 1;
+ break;
+
+ case GEN_RID:
+ {
+ ASN1_OBJECT *obj;
+ if (!(obj = OBJ_txt2obj(value, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+ gen->d.rid = obj;
+ }
+ break;
+
+ case GEN_IPADD:
+ if (is_nc)
+ gen->d.ip = a2i_IPADDRESS_NC(value);
+ else
+ gen->d.ip = a2i_IPADDRESS(value);
+ if (gen->d.ip == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+ break;
+
+ case GEN_DIRNAME:
+ if (!do_dirname(gen, value, ctx)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
+ goto err;
+ }
+ break;
+
+ case GEN_OTHERNAME:
+ if (!do_othername(gen, value, ctx)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
+ goto err;
+ }
+ break;
+ default:
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
+ goto err;
+ }
+
+ if (is_string) {
+ if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
+ !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
+ strlen(value))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ gen->type = gen_type;
+
+ return gen;
+
+ err:
+ if (!out)
+ GENERAL_NAME_free(gen);
+ return NULL;
+}
GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
- {
- int type;
-
- char *name, *value;
-
- name = cnf->name;
- value = cnf->value;
-
- if(!value)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
- return NULL;
- }
-
- if(!name_cmp(name, "email"))
- type = GEN_EMAIL;
- else if(!name_cmp(name, "URI"))
- type = GEN_URI;
- else if(!name_cmp(name, "DNS"))
- type = GEN_DNS;
- else if(!name_cmp(name, "RID"))
- type = GEN_RID;
- else if(!name_cmp(name, "IP"))
- type = GEN_IPADD;
- else if(!name_cmp(name, "dirName"))
- type = GEN_DIRNAME;
- else if(!name_cmp(name, "otherName"))
- type = GEN_OTHERNAME;
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
- ERR_add_error_data(2, "name=", name);
- return NULL;
- }
-
- return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
-
- }
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
+{
+ int type;
+
+ char *name, *value;
+
+ name = cnf->name;
+ value = cnf->value;
+
+ if (!value) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if (!name_cmp(name, "email"))
+ type = GEN_EMAIL;
+ else if (!name_cmp(name, "URI"))
+ type = GEN_URI;
+ else if (!name_cmp(name, "DNS"))
+ type = GEN_DNS;
+ else if (!name_cmp(name, "RID"))
+ type = GEN_RID;
+ else if (!name_cmp(name, "IP"))
+ type = GEN_IPADD;
+ else if (!name_cmp(name, "dirName"))
+ type = GEN_DIRNAME;
+ else if (!name_cmp(name, "otherName"))
+ type = GEN_OTHERNAME;
+ else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
+ ERR_add_error_data(2, "name=", name);
+ return NULL;
+ }
+
+ return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
+
+}
static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
- {
- char *objtmp = NULL, *p;
- int objlen;
- if (!(p = strchr(value, ';')))
- return 0;
- if (!(gen->d.otherName = OTHERNAME_new()))
- return 0;
- /* Free this up because we will overwrite it.
- * no need to free type_id because it is static
- */
- ASN1_TYPE_free(gen->d.otherName->value);
- if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
- return 0;
- objlen = p - value;
- objtmp = OPENSSL_malloc(objlen + 1);
- if (objtmp == NULL)
- return 0;
- strncpy(objtmp, value, objlen);
- objtmp[objlen] = 0;
- gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
- OPENSSL_free(objtmp);
- if (!gen->d.otherName->type_id)
- return 0;
- return 1;
- }
+{
+ char *objtmp = NULL, *p;
+ int objlen;
+ if (!(p = strchr(value, ';')))
+ return 0;
+ if (!(gen->d.otherName = OTHERNAME_new()))
+ return 0;
+ /*
+ * Free this up because we will overwrite it. no need to free type_id
+ * because it is static
+ */
+ ASN1_TYPE_free(gen->d.otherName->value);
+ if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
+ return 0;
+ objlen = p - value;
+ objtmp = OPENSSL_malloc(objlen + 1);
+ if (objtmp == NULL)
+ return 0;
+ strncpy(objtmp, value, objlen);
+ objtmp[objlen] = 0;
+ gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
+ OPENSSL_free(objtmp);
+ if (!gen->d.otherName->type_id)
+ return 0;
+ return 1;
+}
static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
- {
- int ret = 0;
- STACK_OF(CONF_VALUE) *sk = NULL;
- X509_NAME *nm = X509_NAME_new();
- if (nm == NULL)
- goto err;
- sk = X509V3_get_section(ctx, value);
- if (sk == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
- ERR_add_error_data(2, "section=", value);
- goto err;
- }
- /* FIXME: should allow other character types... */
- if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC))
- goto err;
- gen->d.dirn = nm;
- ret = 1;
-
-err:
- if (!ret)
- X509_NAME_free(nm);
- X509V3_section_free(ctx, sk);
- return ret;
- }
+{
+ int ret = 0;
+ STACK_OF(CONF_VALUE) *sk = NULL;
+ X509_NAME *nm = X509_NAME_new();
+ if (nm == NULL)
+ goto err;
+ sk = X509V3_get_section(ctx, value);
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+ ERR_add_error_data(2, "section=", value);
+ goto err;
+ }
+ /* FIXME: should allow other character types... */
+ if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC))
+ goto err;
+ gen->d.dirn = nm;
+ ret = 1;
+
+ err:
+ if (!ret)
+ X509_NAME_free(nm);
+ X509V3_section_free(ctx, sk);
+ return ret;
+}
diff --git a/src/crypto/x509v3/v3_bcons.c b/src/crypto/x509v3/v3_bcons.c
index 73ef21ee..aefefdff 100644
--- a/src/crypto/x509v3/v3_bcons.c
+++ b/src/crypto/x509v3/v3_bcons.c
@@ -1,6 +1,7 @@
/* v3_bcons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <string.h>
@@ -65,62 +65,69 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist);
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ BASIC_CONSTRAINTS *bcons,
+ STACK_OF(CONF_VALUE)
+ *extlist);
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
const X509V3_EXT_METHOD v3_bcons = {
-NID_basic_constraints, 0,
-ASN1_ITEM_ref(BASIC_CONSTRAINTS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS,
-(X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
-NULL,NULL,
-NULL
+ NID_basic_constraints, 0,
+ ASN1_ITEM_ref(BASIC_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS,
+ (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
+ NULL, NULL,
+ NULL
};
ASN1_SEQUENCE(BASIC_CONSTRAINTS) = {
- ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
- ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
+ ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
+ ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
-
static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist)
+ BASIC_CONSTRAINTS *bcons,
+ STACK_OF(CONF_VALUE)
+ *extlist)
{
- X509V3_add_value_bool("CA", bcons->ca, &extlist);
- X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
- return extlist;
+ X509V3_add_value_bool("CA", bcons->ca, &extlist);
+ X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
+ return extlist;
}
static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
{
- BASIC_CONSTRAINTS *bcons=NULL;
- CONF_VALUE *val;
- size_t i;
- if(!(bcons = BASIC_CONSTRAINTS_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
- val = sk_CONF_VALUE_value(values, i);
- if(!strcmp(val->name, "CA")) {
- if(!X509V3_get_value_bool(val, &bcons->ca)) goto err;
- } else if(!strcmp(val->name, "pathlen")) {
- if(!X509V3_get_value_int(val, &bcons->pathlen)) goto err;
- } else {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
- X509V3_conf_err(val);
- goto err;
- }
- }
- return bcons;
- err:
- BASIC_CONSTRAINTS_free(bcons);
- return NULL;
+ BASIC_CONSTRAINTS *bcons = NULL;
+ CONF_VALUE *val;
+ size_t i;
+ if (!(bcons = BASIC_CONSTRAINTS_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if (!strcmp(val->name, "CA")) {
+ if (!X509V3_get_value_bool(val, &bcons->ca))
+ goto err;
+ } else if (!strcmp(val->name, "pathlen")) {
+ if (!X509V3_get_value_int(val, &bcons->pathlen))
+ goto err;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ return bcons;
+ err:
+ BASIC_CONSTRAINTS_free(bcons);
+ return NULL;
}
-
diff --git a/src/crypto/x509v3/v3_bitst.c b/src/crypto/x509v3/v3_bitst.c
index e1e20871..86a8c361 100644
--- a/src/crypto/x509v3/v3_bitst.c
+++ b/src/crypto/x509v3/v3_bitst.c
@@ -1,6 +1,7 @@
/* v3_bitst.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,80 +63,79 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static const BIT_STRING_BITNAME ns_cert_type_table[] = {
-{0, "SSL Client", "client"},
-{1, "SSL Server", "server"},
-{2, "S/MIME", "email"},
-{3, "Object Signing", "objsign"},
-{4, "Unused", "reserved"},
-{5, "SSL CA", "sslCA"},
-{6, "S/MIME CA", "emailCA"},
-{7, "Object Signing CA", "objCA"},
-{-1, NULL, NULL}
+ {0, "SSL Client", "client"},
+ {1, "SSL Server", "server"},
+ {2, "S/MIME", "email"},
+ {3, "Object Signing", "objsign"},
+ {4, "Unused", "reserved"},
+ {5, "SSL CA", "sslCA"},
+ {6, "S/MIME CA", "emailCA"},
+ {7, "Object Signing CA", "objCA"},
+ {-1, NULL, NULL}
};
static const BIT_STRING_BITNAME key_usage_type_table[] = {
-{0, "Digital Signature", "digitalSignature"},
-{1, "Non Repudiation", "nonRepudiation"},
-{2, "Key Encipherment", "keyEncipherment"},
-{3, "Data Encipherment", "dataEncipherment"},
-{4, "Key Agreement", "keyAgreement"},
-{5, "Certificate Sign", "keyCertSign"},
-{6, "CRL Sign", "cRLSign"},
-{7, "Encipher Only", "encipherOnly"},
-{8, "Decipher Only", "decipherOnly"},
-{-1, NULL, NULL}
+ {0, "Digital Signature", "digitalSignature"},
+ {1, "Non Repudiation", "nonRepudiation"},
+ {2, "Key Encipherment", "keyEncipherment"},
+ {3, "Data Encipherment", "dataEncipherment"},
+ {4, "Key Agreement", "keyAgreement"},
+ {5, "Certificate Sign", "keyCertSign"},
+ {6, "CRL Sign", "cRLSign"},
+ {7, "Encipher Only", "encipherOnly"},
+ {8, "Decipher Only", "decipherOnly"},
+ {-1, NULL, NULL}
};
-
-
-const X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
-const X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table);
+const X509V3_EXT_METHOD v3_nscert =
+EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
+const X509V3_EXT_METHOD v3_key_usage =
+EXT_BITSTRING(NID_key_usage, key_usage_type_table);
STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *ret)
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *ret)
{
- const BIT_STRING_BITNAME *bnam;
- for(bnam =method->usr_data; bnam->lname; bnam++) {
- if(ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
- X509V3_add_value(bnam->lname, NULL, &ret);
- }
- return ret;
+ const BIT_STRING_BITNAME *bnam;
+ for (bnam = method->usr_data; bnam->lname; bnam++) {
+ if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
+ X509V3_add_value(bnam->lname, NULL, &ret);
+ }
+ return ret;
}
-
+
ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
{
- CONF_VALUE *val;
- ASN1_BIT_STRING *bs;
- size_t i;
- const BIT_STRING_BITNAME *bnam;
- if(!(bs = M_ASN1_BIT_STRING_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- for(bnam = method->usr_data; bnam->lname; bnam++) {
- if(!strcmp(bnam->sname, val->name) ||
- !strcmp(bnam->lname, val->name) ) {
- if(!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- M_ASN1_BIT_STRING_free(bs);
- return NULL;
- }
- break;
- }
- }
- if(!bnam->lname) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
- X509V3_conf_err(val);
- M_ASN1_BIT_STRING_free(bs);
- return NULL;
- }
- }
- return bs;
+ CONF_VALUE *val;
+ ASN1_BIT_STRING *bs;
+ size_t i;
+ const BIT_STRING_BITNAME *bnam;
+ if (!(bs = M_ASN1_BIT_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ for (bnam = method->usr_data; bnam->lname; bnam++) {
+ if (!strcmp(bnam->sname, val->name) ||
+ !strcmp(bnam->lname, val->name)) {
+ if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ M_ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ break;
+ }
+ }
+ if (!bnam->lname) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
+ X509V3_conf_err(val);
+ M_ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ }
+ return bs;
}
-
-
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
index fe715665..66abca4e 100644
--- a/src/crypto/x509v3/v3_conf.c
+++ b/src/crypto/x509v3/v3_conf.c
@@ -1,6 +1,7 @@
/* v3_conf.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -69,391 +70,391 @@
#include "../internal.h"
-
static int v3_check_critical(char **value);
static int v3_check_generic(char **value);
-static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value);
-static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type, X509V3_CTX *ctx);
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
- int crit, void *ext_struc);
-static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len);
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ int crit, char *value);
+static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
+ int crit, int type,
+ X509V3_CTX *ctx);
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+ int ext_nid, int crit, void *ext_struc);
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
+ long *ext_len);
/* CONF *conf: Config file */
/* char *name: Name */
/* char *value: Value */
X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
- char *value)
- {
- int crit;
- int ext_type;
- X509_EXTENSION *ret;
- crit = v3_check_critical(&value);
- if ((ext_type = v3_check_generic(&value)))
- return v3_generic_extension(name, value, crit, ext_type, ctx);
- ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
- if (!ret)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
- ERR_add_error_data(4,"name=", name, ", value=", value);
- }
- return ret;
- }
+ char *value)
+{
+ int crit;
+ int ext_type;
+ X509_EXTENSION *ret;
+ crit = v3_check_critical(&value);
+ if ((ext_type = v3_check_generic(&value)))
+ return v3_generic_extension(name, value, crit, ext_type, ctx);
+ ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
+ ERR_add_error_data(4, "name=", name, ", value=", value);
+ }
+ return ret;
+}
/* CONF *conf: Config file */
/* char *value: Value */
X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- char *value)
- {
- int crit;
- int ext_type;
- crit = v3_check_critical(&value);
- if ((ext_type = v3_check_generic(&value)))
- return v3_generic_extension(OBJ_nid2sn(ext_nid),
- value, crit, ext_type, ctx);
- return do_ext_nconf(conf, ctx, ext_nid, crit, value);
- }
+ char *value)
+{
+ int crit;
+ int ext_type;
+ crit = v3_check_critical(&value);
+ if ((ext_type = v3_check_generic(&value)))
+ return v3_generic_extension(OBJ_nid2sn(ext_nid),
+ value, crit, ext_type, ctx);
+ return do_ext_nconf(conf, ctx, ext_nid, crit, value);
+}
/* CONF *conf: Config file */
/* char *value: Value */
static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- int crit, char *value)
- {
- const X509V3_EXT_METHOD *method;
- X509_EXTENSION *ext;
- STACK_OF(CONF_VALUE) *nval;
- void *ext_struc;
- if (ext_nid == NID_undef)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
- return NULL;
- }
- if (!(method = X509V3_EXT_get_nid(ext_nid)))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
- return NULL;
- }
- /* Now get internal extension representation based on type */
- if (method->v2i)
- {
- if(*value == '@') nval = NCONF_get_section(conf, value + 1);
- else nval = X509V3_parse_list(value);
- if(sk_CONF_VALUE_num(nval) <= 0)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
- ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value);
- return NULL;
- }
- ext_struc = method->v2i(method, ctx, nval);
- if(*value != '@') sk_CONF_VALUE_pop_free(nval,
- X509V3_conf_free);
- if(!ext_struc) return NULL;
- }
- else if(method->s2i)
- {
- if(!(ext_struc = method->s2i(method, ctx, value))) return NULL;
- }
- else if(method->r2i)
- {
- if(!ctx->db || !ctx->db_meth)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
- return NULL;
- }
- if(!(ext_struc = method->r2i(method, ctx, value))) return NULL;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
- ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
- return NULL;
- }
-
- ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
- if(method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
- else method->ext_free(ext_struc);
- return ext;
-
- }
-
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
- int crit, void *ext_struc)
- {
- unsigned char *ext_der;
- int ext_len;
- ASN1_OCTET_STRING *ext_oct;
- X509_EXTENSION *ext;
- /* Convert internal representation to DER */
- if (method->it)
- {
- ext_der = NULL;
- ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
- if (ext_len < 0) goto merr;
- }
- else
- {
- unsigned char *p;
- ext_len = method->i2d(ext_struc, NULL);
- if(!(ext_der = OPENSSL_malloc(ext_len))) goto merr;
- p = ext_der;
- method->i2d(ext_struc, &p);
- }
- if (!(ext_oct = M_ASN1_OCTET_STRING_new())) goto merr;
- ext_oct->data = ext_der;
- ext_oct->length = ext_len;
-
- ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
- if (!ext) goto merr;
- M_ASN1_OCTET_STRING_free(ext_oct);
-
- return ext;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
-
- }
+ int crit, char *value)
+{
+ const X509V3_EXT_METHOD *method;
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ void *ext_struc;
+ if (ext_nid == NID_undef) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
+ return NULL;
+ }
+ if (!(method = X509V3_EXT_get_nid(ext_nid))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ /* Now get internal extension representation based on type */
+ if (method->v2i) {
+ if (*value == '@')
+ nval = NCONF_get_section(conf, value + 1);
+ else
+ nval = X509V3_parse_list(value);
+ if (sk_CONF_VALUE_num(nval) <= 0) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
+ ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=",
+ value);
+ return NULL;
+ }
+ ext_struc = method->v2i(method, ctx, nval);
+ if (*value != '@')
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+ if (!ext_struc)
+ return NULL;
+ } else if (method->s2i) {
+ if (!(ext_struc = method->s2i(method, ctx, value)))
+ return NULL;
+ } else if (method->r2i) {
+ if (!ctx->db || !ctx->db_meth) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
+ return NULL;
+ }
+ if (!(ext_struc = method->r2i(method, ctx, value)))
+ return NULL;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
+ ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
+ return NULL;
+ }
+
+ ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
+ if (method->it)
+ ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
+ else
+ method->ext_free(ext_struc);
+ return ext;
+
+}
+
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+ int ext_nid, int crit, void *ext_struc)
+{
+ unsigned char *ext_der;
+ int ext_len;
+ ASN1_OCTET_STRING *ext_oct;
+ X509_EXTENSION *ext;
+ /* Convert internal representation to DER */
+ if (method->it) {
+ ext_der = NULL;
+ ext_len =
+ ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
+ if (ext_len < 0)
+ goto merr;
+ } else {
+ unsigned char *p;
+ ext_len = method->i2d(ext_struc, NULL);
+ if (!(ext_der = OPENSSL_malloc(ext_len)))
+ goto merr;
+ p = ext_der;
+ method->i2d(ext_struc, &p);
+ }
+ if (!(ext_oct = M_ASN1_OCTET_STRING_new()))
+ goto merr;
+ ext_oct->data = ext_der;
+ ext_oct->length = ext_len;
+
+ ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
+ if (!ext)
+ goto merr;
+ M_ASN1_OCTET_STRING_free(ext_oct);
+
+ return ext;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+
+}
/* Given an internal structure, nid and critical flag create an extension */
X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
- {
- const X509V3_EXT_METHOD *method;
- if (!(method = X509V3_EXT_get_nid(ext_nid))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
- return NULL;
- }
- return do_ext_i2d(method, ext_nid, crit, ext_struc);
+{
+ const X509V3_EXT_METHOD *method;
+ if (!(method = X509V3_EXT_get_nid(ext_nid))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ return do_ext_i2d(method, ext_nid, crit, ext_struc);
}
/* Check the extension string for critical flag */
static int v3_check_critical(char **value)
{
- char *p = *value;
- if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0;
- p+=9;
- while(isspace((unsigned char)*p)) p++;
- *value = p;
- return 1;
+ char *p = *value;
+ if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
+ return 0;
+ p += 9;
+ while (isspace((unsigned char)*p))
+ p++;
+ *value = p;
+ return 1;
}
/* Check extension string for generic extension and return the type */
static int v3_check_generic(char **value)
{
- int gen_type = 0;
- char *p = *value;
- if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4))
- {
- p+=4;
- gen_type = 1;
- }
- else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5))
- {
- p+=5;
- gen_type = 2;
- }
- else
- return 0;
-
- while (isspace((unsigned char)*p)) p++;
- *value = p;
- return gen_type;
+ int gen_type = 0;
+ char *p = *value;
+ if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
+ p += 4;
+ gen_type = 1;
+ } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
+ p += 5;
+ gen_type = 2;
+ } else
+ return 0;
+
+ while (isspace((unsigned char)*p))
+ p++;
+ *value = p;
+ return gen_type;
}
/* Create a generic extension: for now just handle DER type */
static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
- int crit, int gen_type,
- X509V3_CTX *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
- {
- unsigned char *ext_der=NULL;
- long ext_len;
- ASN1_OBJECT *obj=NULL;
- ASN1_OCTET_STRING *oct=NULL;
- X509_EXTENSION *extension=NULL;
- if (!(obj = OBJ_txt2obj(ext, 0)))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
- ERR_add_error_data(2, "name=", ext);
- goto err;
- }
-
- if (gen_type == 1)
- ext_der = string_to_hex(value, &ext_len);
- else if (gen_type == 2)
- ext_der = generic_asn1(value, ctx, &ext_len);
-
- if (ext_der == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
-
- if (!(oct = M_ASN1_OCTET_STRING_new()))
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- oct->data = ext_der;
- oct->length = ext_len;
- ext_der = NULL;
-
- extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
-
- err:
- ASN1_OBJECT_free(obj);
- M_ASN1_OCTET_STRING_free(oct);
- if(ext_der) OPENSSL_free(ext_der);
- return extension;
-
- }
-
-static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len)
- {
- ASN1_TYPE *typ;
- unsigned char *ext_der = NULL;
- typ = ASN1_generate_v3(value, ctx);
- if (typ == NULL)
- return NULL;
- *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
- ASN1_TYPE_free(typ);
- return ext_der;
- }
-
-/* This is the main function: add a bunch of extensions based on a config file
- * section to an extension STACK.
- */
+ int crit, int gen_type,
+ X509V3_CTX *ctx)
+{
+ unsigned char *ext_der = NULL;
+ long ext_len = 0;
+ ASN1_OBJECT *obj = NULL;
+ ASN1_OCTET_STRING *oct = NULL;
+ X509_EXTENSION *extension = NULL;
+ if (!(obj = OBJ_txt2obj(ext, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
+ ERR_add_error_data(2, "name=", ext);
+ goto err;
+ }
+
+ if (gen_type == 1)
+ ext_der = string_to_hex(value, &ext_len);
+ else if (gen_type == 2)
+ ext_der = generic_asn1(value, ctx, &ext_len);
+
+ if (ext_der == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+
+ if (!(oct = M_ASN1_OCTET_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ oct->data = ext_der;
+ oct->length = ext_len;
+ ext_der = NULL;
+
+ extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
+
+ err:
+ ASN1_OBJECT_free(obj);
+ M_ASN1_OCTET_STRING_free(oct);
+ if (ext_der)
+ OPENSSL_free(ext_der);
+ return extension;
+}
+
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
+ long *ext_len)
+{
+ ASN1_TYPE *typ;
+ unsigned char *ext_der = NULL;
+ typ = ASN1_generate_v3(value, ctx);
+ if (typ == NULL)
+ return NULL;
+ *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
+ ASN1_TYPE_free(typ);
+ return ext_der;
+}
+
+/*
+ * This is the main function: add a bunch of extensions based on a config
+ * file section to an extension STACK.
+ */
int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section,
- STACK_OF(X509_EXTENSION) **sk)
- {
- X509_EXTENSION *ext;
- STACK_OF(CONF_VALUE) *nval;
- CONF_VALUE *val;
- size_t i;
- if (!(nval = NCONF_get_section(conf, section))) return 0;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++)
- {
- val = sk_CONF_VALUE_value(nval, i);
- if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
- return 0;
- if (sk) X509v3_add_ext(sk, ext, -1);
- X509_EXTENSION_free(ext);
- }
- return 1;
- }
-
-/* Convenience functions to add extensions to a certificate, CRL and request */
+ STACK_OF(X509_EXTENSION) **sk)
+{
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ CONF_VALUE *val;
+ size_t i;
+ if (!(nval = NCONF_get_section(conf, section)))
+ return 0;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
+ return 0;
+ if (sk)
+ X509v3_add_ext(sk, ext, -1);
+ X509_EXTENSION_free(ext);
+ }
+ return 1;
+}
+
+/*
+ * Convenience functions to add extensions to a certificate, CRL and request
+ */
int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
- X509 *cert)
- {
- STACK_OF(X509_EXTENSION) **sk = NULL;
- if (cert)
- sk = &cert->cert_info->extensions;
- return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
- }
+ X509 *cert)
+{
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (cert)
+ sk = &cert->cert_info->extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
/* Same as above but for a CRL */
int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
- X509_CRL *crl)
- {
- STACK_OF(X509_EXTENSION) **sk = NULL;
- if (crl)
- sk = &crl->crl->extensions;
- return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
- }
+ X509_CRL *crl)
+{
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (crl)
+ sk = &crl->crl->extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
/* Add extensions to certificate request */
int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
- X509_REQ *req)
- {
- STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
- int i;
- if (req)
- sk = &extlist;
- i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
- if (!i || !sk)
- return i;
- i = X509_REQ_add_extensions(req, extlist);
- sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
- return i;
- }
+ X509_REQ *req)
+{
+ STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
+ int i;
+ if (req)
+ sk = &extlist;
+ i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+ if (!i || !sk)
+ return i;
+ i = X509_REQ_add_extensions(req, extlist);
+ sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
+ return i;
+}
/* Config database functions */
-char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
- {
- if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
- return NULL;
- }
- if (ctx->db_meth->get_string)
- return ctx->db_meth->get_string(ctx->db, name, section);
- return NULL;
- }
-
-STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section)
- {
- if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
- return NULL;
- }
- if (ctx->db_meth->get_section)
- return ctx->db_meth->get_section(ctx->db, section);
- return NULL;
- }
+char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
+{
+ if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_string)
+ return ctx->db_meth->get_string(ctx->db, name, section);
+ return NULL;
+}
+
+STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section)
+{
+ if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_section)
+ return ctx->db_meth->get_section(ctx->db, section);
+ return NULL;
+}
void X509V3_string_free(X509V3_CTX *ctx, char *str)
- {
- if (!str) return;
- if (ctx->db_meth->free_string)
- ctx->db_meth->free_string(ctx->db, str);
- }
+{
+ if (!str)
+ return;
+ if (ctx->db_meth->free_string)
+ ctx->db_meth->free_string(ctx->db, str);
+}
void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
- {
- if (!section) return;
- if (ctx->db_meth->free_section)
- ctx->db_meth->free_section(ctx->db, section);
- }
+{
+ if (!section)
+ return;
+ if (ctx->db_meth->free_section)
+ ctx->db_meth->free_section(ctx->db, section);
+}
static char *nconf_get_string(void *db, char *section, char *value)
- {
- /* TODO(fork): this should return a const value. */
- return (char *) NCONF_get_string(db, section, value);
- }
+{
+ /* TODO(fork): this should return a const value. */
+ return (char *)NCONF_get_string(db, section, value);
+}
static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section)
- {
- return NCONF_get_section(db, section);
- }
+{
+ return NCONF_get_section(db, section);
+}
static const X509V3_CONF_METHOD nconf_method = {
-nconf_get_string,
-nconf_get_section,
-NULL,
-NULL
+ nconf_get_string,
+ nconf_get_section,
+ NULL,
+ NULL
};
void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
- {
- ctx->db_meth = &nconf_method;
- ctx->db = conf;
- }
+{
+ ctx->db_meth = &nconf_method;
+ ctx->db = conf;
+}
void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
- X509_CRL *crl, int flags)
- {
- ctx->issuer_cert = issuer;
- ctx->subject_cert = subj;
- ctx->crl = crl;
- ctx->subject_req = req;
- ctx->flags = flags;
- }
-
+ X509_CRL *crl, int flags)
+{
+ ctx->issuer_cert = issuer;
+ ctx->subject_cert = subj;
+ ctx->crl = crl;
+ ctx->subject_req = req;
+ ctx->flags = flags;
+}
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index 0b586762..d67dcb08 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -1,6 +1,7 @@
/* v3_cpols.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -72,35 +73,38 @@
/* Certificate policies extension support: this one is a bit complex... */
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, int indent);
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value);
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent);
+static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
+ BIO *out, int indent);
+static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *value);
+static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+ int indent);
static void print_notice(BIO *out, USERNOTICE *notice, int indent);
static POLICYINFO *policy_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *polstrs, int ia5org);
+ STACK_OF(CONF_VALUE) *polstrs, int ia5org);
static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *unot, int ia5org);
+ STACK_OF(CONF_VALUE) *unot, int ia5org);
static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
const X509V3_EXT_METHOD v3_cpols = {
-NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
-0,0,0,0,
-0,0,
-0,0,
-(X509V3_EXT_I2R)i2r_certpol,
-(X509V3_EXT_R2I)r2i_certpol,
-NULL
+ NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2R)i2r_certpol,
+ (X509V3_EXT_R2I)r2i_certpol,
+ NULL
};
-ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
+ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
ASN1_SEQUENCE(POLICYINFO) = {
- ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
- ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
+ ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
+ ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
} ASN1_SEQUENCE_END(POLICYINFO)
IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
@@ -108,368 +112,385 @@ IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
ASN1_ADB(POLICYQUALINFO) = {
- ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
- ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
+ ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
+ ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
ASN1_SEQUENCE(POLICYQUALINFO) = {
- ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
- ASN1_ADB_OBJECT(POLICYQUALINFO)
+ ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(POLICYQUALINFO)
} ASN1_SEQUENCE_END(POLICYQUALINFO)
IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
ASN1_SEQUENCE(USERNOTICE) = {
- ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
- ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
+ ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
+ ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
} ASN1_SEQUENCE_END(USERNOTICE)
IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
ASN1_SEQUENCE(NOTICEREF) = {
- ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
- ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
+ ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
+ ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
} ASN1_SEQUENCE_END(NOTICEREF)
IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *value)
+ X509V3_CTX *ctx, char *value)
{
- STACK_OF(POLICYINFO) *pols = NULL;
- char *pstr;
- POLICYINFO *pol;
- ASN1_OBJECT *pobj;
- STACK_OF(CONF_VALUE) *vals;
- CONF_VALUE *cnf;
- size_t i;
- int ia5org;
- pols = sk_POLICYINFO_new_null();
- if (pols == NULL) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- vals = X509V3_parse_list(value);
- if (vals == NULL) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB);
- goto err;
- }
- ia5org = 0;
- for(i = 0; i < sk_CONF_VALUE_num(vals); i++) {
- cnf = sk_CONF_VALUE_value(vals, i);
- if(cnf->value || !cnf->name ) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pstr = cnf->name;
- if(!strcmp(pstr,"ia5org")) {
- ia5org = 1;
- continue;
- } else if(*pstr == '@') {
- STACK_OF(CONF_VALUE) *polsect;
- polsect = X509V3_get_section(ctx, pstr + 1);
- if(!polsect) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- pol = policy_section(ctx, polsect, ia5org);
- X509V3_section_free(ctx, polsect);
- if(!pol) goto err;
- } else {
- if(!(pobj = OBJ_txt2obj(cnf->name, 0))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pol = POLICYINFO_new();
- pol->policyid = pobj;
- }
- if (!sk_POLICYINFO_push(pols, pol)){
- POLICYINFO_free(pol);
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- return pols;
- err:
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
- return NULL;
+ STACK_OF(POLICYINFO) *pols = NULL;
+ char *pstr;
+ POLICYINFO *pol;
+ ASN1_OBJECT *pobj;
+ STACK_OF(CONF_VALUE) *vals;
+ CONF_VALUE *cnf;
+ size_t i;
+ int ia5org;
+ pols = sk_POLICYINFO_new_null();
+ if (pols == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ vals = X509V3_parse_list(value);
+ if (vals == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB);
+ goto err;
+ }
+ ia5org = 0;
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ cnf = sk_CONF_VALUE_value(vals, i);
+ if (cnf->value || !cnf->name) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pstr = cnf->name;
+ if (!strcmp(pstr, "ia5org")) {
+ ia5org = 1;
+ continue;
+ } else if (*pstr == '@') {
+ STACK_OF(CONF_VALUE) *polsect;
+ polsect = X509V3_get_section(ctx, pstr + 1);
+ if (!polsect) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol = policy_section(ctx, polsect, ia5org);
+ X509V3_section_free(ctx, polsect);
+ if (!pol)
+ goto err;
+ } else {
+ if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol = POLICYINFO_new();
+ if (pol == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_OBJECT_free(pobj);
+ goto err;
+ }
+ pol->policyid = pobj;
+ }
+ if (!sk_POLICYINFO_push(pols, pol)) {
+ POLICYINFO_free(pol);
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pols;
+ err:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
+ return NULL;
}
static POLICYINFO *policy_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *polstrs, int ia5org)
+ STACK_OF(CONF_VALUE) *polstrs, int ia5org)
{
- size_t i;
- CONF_VALUE *cnf;
- POLICYINFO *pol;
- POLICYQUALINFO *qual;
- if(!(pol = POLICYINFO_new())) goto merr;
- for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
- cnf = sk_CONF_VALUE_value(polstrs, i);
- if(!strcmp(cnf->name, "policyIdentifier")) {
- ASN1_OBJECT *pobj;
- if(!(pobj = OBJ_txt2obj(cnf->value, 0))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pol->policyid = pobj;
-
- } else if(!name_cmp(cnf->name, "CPS")) {
- if(!pol->qualifiers) pol->qualifiers =
- sk_POLICYQUALINFO_new_null();
- if(!(qual = POLICYQUALINFO_new())) goto merr;
- if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
- goto merr;
- /* TODO(fork): const correctness */
- qual->pqualid = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_qt_cps);
- if (qual->pqualid == NULL) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- qual->d.cpsuri = M_ASN1_IA5STRING_new();
- if (qual->d.cpsuri == NULL) {
- goto err;
- }
- if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
- strlen(cnf->value))) goto merr;
- } else if(!name_cmp(cnf->name, "userNotice")) {
- STACK_OF(CONF_VALUE) *unot;
- if(*cnf->value != '@') {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
- X509V3_conf_err(cnf);
- goto err;
- }
- unot = X509V3_get_section(ctx, cnf->value + 1);
- if(!unot) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- qual = notice_section(ctx, unot, ia5org);
- X509V3_section_free(ctx, unot);
- if(!qual) goto err;
- if(!pol->qualifiers) pol->qualifiers =
- sk_POLICYQUALINFO_new_null();
- if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
- goto merr;
- } else {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- if(!pol->policyid) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
- goto err;
- }
-
- return pol;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-
- err:
- POLICYINFO_free(pol);
- return NULL;
-
-
+ size_t i;
+ CONF_VALUE *cnf;
+ POLICYINFO *pol;
+ POLICYQUALINFO *qual;
+ if (!(pol = POLICYINFO_new()))
+ goto merr;
+ for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
+ cnf = sk_CONF_VALUE_value(polstrs, i);
+ if (!strcmp(cnf->name, "policyIdentifier")) {
+ ASN1_OBJECT *pobj;
+ if (!(pobj = OBJ_txt2obj(cnf->value, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol->policyid = pobj;
+
+ } else if (!name_cmp(cnf->name, "CPS")) {
+ if (!pol->qualifiers)
+ pol->qualifiers = sk_POLICYQUALINFO_new_null();
+ if (!(qual = POLICYQUALINFO_new()))
+ goto merr;
+ if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ /* TODO(fork): const correctness */
+ qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_cps);
+ if (qual->pqualid == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ qual->d.cpsuri = M_ASN1_IA5STRING_new();
+ if (qual->d.cpsuri == NULL) {
+ goto err;
+ }
+ if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
+ strlen(cnf->value)))
+ goto merr;
+ } else if (!name_cmp(cnf->name, "userNotice")) {
+ STACK_OF(CONF_VALUE) *unot;
+ if (*cnf->value != '@') {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ unot = X509V3_get_section(ctx, cnf->value + 1);
+ if (!unot) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ qual = notice_section(ctx, unot, ia5org);
+ X509V3_section_free(ctx, unot);
+ if (!qual)
+ goto err;
+ if (!pol->qualifiers)
+ pol->qualifiers = sk_POLICYQUALINFO_new_null();
+ if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ if (!pol->policyid) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
+ goto err;
+ }
+
+ return pol;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYINFO_free(pol);
+ return NULL;
+
}
static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *unot, int ia5org)
+ STACK_OF(CONF_VALUE) *unot, int ia5org)
{
- size_t i;
- int ret;
- CONF_VALUE *cnf;
- USERNOTICE *not;
- POLICYQUALINFO *qual;
- if(!(qual = POLICYQUALINFO_new())) goto merr;
- /* TODO(fork): const correctness */
- qual->pqualid = (ASN1_OBJECT *) OBJ_nid2obj(NID_id_qt_unotice);
- if (qual->pqualid == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if(!(not = USERNOTICE_new())) goto merr;
- qual->d.usernotice = not;
- for(i = 0; i < sk_CONF_VALUE_num(unot); i++) {
- cnf = sk_CONF_VALUE_value(unot, i);
- if(!strcmp(cnf->name, "explicitText")) {
- not->exptext = M_ASN1_VISIBLESTRING_new();
- if (not->exptext == NULL)
- goto merr;
- if(!ASN1_STRING_set(not->exptext, cnf->value,
- strlen(cnf->value))) goto merr;
- } else if(!strcmp(cnf->name, "organization")) {
- NOTICEREF *nref;
- if(!not->noticeref) {
- if(!(nref = NOTICEREF_new())) goto merr;
- not->noticeref = nref;
- } else nref = not->noticeref;
- if(ia5org) nref->organization->type = V_ASN1_IA5STRING;
- else nref->organization->type = V_ASN1_VISIBLESTRING;
- if(!ASN1_STRING_set(nref->organization, cnf->value,
- strlen(cnf->value))) goto merr;
- } else if(!strcmp(cnf->name, "noticeNumbers")) {
- NOTICEREF *nref;
- STACK_OF(CONF_VALUE) *nos;
- if(!not->noticeref) {
- if(!(nref = NOTICEREF_new())) goto merr;
- not->noticeref = nref;
- } else nref = not->noticeref;
- nos = X509V3_parse_list(cnf->value);
- if(!nos || !sk_CONF_VALUE_num(nos)) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS);
- X509V3_conf_err(cnf);
- goto err;
- }
- ret = nref_nos(nref->noticenos, nos);
- sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
- if (!ret)
- goto err;
- } else {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
- X509V3_conf_err(cnf);
- goto err;
- }
- }
-
- if(not->noticeref &&
- (!not->noticeref->noticenos || !not->noticeref->organization)) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
- goto err;
- }
-
- return qual;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-
- err:
- POLICYQUALINFO_free(qual);
- return NULL;
+ size_t i;
+ int ret;
+ CONF_VALUE *cnf;
+ USERNOTICE *not;
+ POLICYQUALINFO *qual;
+ if (!(qual = POLICYQUALINFO_new()))
+ goto merr;
+ /* TODO(fork): const correctness */
+ qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_unotice);
+ if (qual->pqualid == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (!(not = USERNOTICE_new()))
+ goto merr;
+ qual->d.usernotice = not;
+ for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
+ cnf = sk_CONF_VALUE_value(unot, i);
+ if (!strcmp(cnf->name, "explicitText")) {
+ not->exptext = M_ASN1_VISIBLESTRING_new();
+ if (not->exptext == NULL)
+ goto merr;
+ if (!ASN1_STRING_set(not->exptext, cnf->value,
+ strlen(cnf->value)))
+ goto merr;
+ } else if (!strcmp(cnf->name, "organization")) {
+ NOTICEREF *nref;
+ if (!not->noticeref) {
+ if (!(nref = NOTICEREF_new()))
+ goto merr;
+ not->noticeref = nref;
+ } else
+ nref = not->noticeref;
+ if (ia5org)
+ nref->organization->type = V_ASN1_IA5STRING;
+ else
+ nref->organization->type = V_ASN1_VISIBLESTRING;
+ if (!ASN1_STRING_set(nref->organization, cnf->value,
+ strlen(cnf->value)))
+ goto merr;
+ } else if (!strcmp(cnf->name, "noticeNumbers")) {
+ NOTICEREF *nref;
+ STACK_OF(CONF_VALUE) *nos;
+ if (!not->noticeref) {
+ if (!(nref = NOTICEREF_new()))
+ goto merr;
+ not->noticeref = nref;
+ } else
+ nref = not->noticeref;
+ nos = X509V3_parse_list(cnf->value);
+ if (!nos || !sk_CONF_VALUE_num(nos)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ ret = nref_nos(nref->noticenos, nos);
+ sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
+ if (!ret)
+ goto err;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+
+ if (not->noticeref &&
+ (!not->noticeref->noticenos || !not->noticeref->organization)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
+ goto err;
+ }
+
+ return qual;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYQUALINFO_free(qual);
+ return NULL;
}
static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
{
- CONF_VALUE *cnf;
- ASN1_INTEGER *aint;
-
- size_t i;
-
- for(i = 0; i < sk_CONF_VALUE_num(nos); i++) {
- cnf = sk_CONF_VALUE_value(nos, i);
- if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER);
- goto err;
- }
- if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr;
- }
- return 1;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-
- err:
- sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
- return 0;
+ CONF_VALUE *cnf;
+ ASN1_INTEGER *aint;
+
+ size_t i;
+
+ for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
+ cnf = sk_CONF_VALUE_value(nos, i);
+ if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER);
+ goto err;
+ }
+ if (!sk_ASN1_INTEGER_push(nnums, aint))
+ goto merr;
+ }
+ return 1;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
+ return 0;
}
-
static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
- BIO *out, int indent)
+ BIO *out, int indent)
{
- size_t i;
- POLICYINFO *pinfo;
- /* First print out the policy OIDs */
- for(i = 0; i < sk_POLICYINFO_num(pol); i++) {
- pinfo = sk_POLICYINFO_value(pol, i);
- BIO_printf(out, "%*sPolicy: ", indent, "");
- i2a_ASN1_OBJECT(out, pinfo->policyid);
- BIO_puts(out, "\n");
- if(pinfo->qualifiers)
- print_qualifiers(out, pinfo->qualifiers, indent + 2);
- }
- return 1;
+ size_t i;
+ POLICYINFO *pinfo;
+ /* First print out the policy OIDs */
+ for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
+ pinfo = sk_POLICYINFO_value(pol, i);
+ BIO_printf(out, "%*sPolicy: ", indent, "");
+ i2a_ASN1_OBJECT(out, pinfo->policyid);
+ BIO_puts(out, "\n");
+ if (pinfo->qualifiers)
+ print_qualifiers(out, pinfo->qualifiers, indent + 2);
+ }
+ return 1;
}
static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
- int indent)
+ int indent)
{
- POLICYQUALINFO *qualinfo;
- size_t i;
- for(i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
- qualinfo = sk_POLICYQUALINFO_value(quals, i);
- switch(OBJ_obj2nid(qualinfo->pqualid))
- {
- case NID_id_qt_cps:
- BIO_printf(out, "%*sCPS: %s\n", indent, "",
- qualinfo->d.cpsuri->data);
- break;
-
- case NID_id_qt_unotice:
- BIO_printf(out, "%*sUser Notice:\n", indent, "");
- print_notice(out, qualinfo->d.usernotice, indent + 2);
- break;
-
- default:
- BIO_printf(out, "%*sUnknown Qualifier: ",
- indent + 2, "");
-
- i2a_ASN1_OBJECT(out, qualinfo->pqualid);
- BIO_puts(out, "\n");
- break;
- }
- }
+ POLICYQUALINFO *qualinfo;
+ size_t i;
+ for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
+ qualinfo = sk_POLICYQUALINFO_value(quals, i);
+ switch (OBJ_obj2nid(qualinfo->pqualid)) {
+ case NID_id_qt_cps:
+ BIO_printf(out, "%*sCPS: %s\n", indent, "",
+ qualinfo->d.cpsuri->data);
+ break;
+
+ case NID_id_qt_unotice:
+ BIO_printf(out, "%*sUser Notice:\n", indent, "");
+ print_notice(out, qualinfo->d.usernotice, indent + 2);
+ break;
+
+ default:
+ BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
+
+ i2a_ASN1_OBJECT(out, qualinfo->pqualid);
+ BIO_puts(out, "\n");
+ break;
+ }
+ }
}
static void print_notice(BIO *out, USERNOTICE *notice, int indent)
{
- size_t i;
- if(notice->noticeref) {
- NOTICEREF *ref;
- ref = notice->noticeref;
- BIO_printf(out, "%*sOrganization: %s\n", indent, "",
- ref->organization->data);
- BIO_printf(out, "%*sNumber%s: ", indent, "",
- sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
- for(i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
- ASN1_INTEGER *num;
- char *tmp;
- num = sk_ASN1_INTEGER_value(ref->noticenos, i);
- if(i) BIO_puts(out, ", ");
- tmp = i2s_ASN1_INTEGER(NULL, num);
- BIO_puts(out, tmp);
- OPENSSL_free(tmp);
- }
- BIO_puts(out, "\n");
- }
- if(notice->exptext)
- BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
- notice->exptext->data);
+ size_t i;
+ if (notice->noticeref) {
+ NOTICEREF *ref;
+ ref = notice->noticeref;
+ BIO_printf(out, "%*sOrganization: %s\n", indent, "",
+ ref->organization->data);
+ BIO_printf(out, "%*sNumber%s: ", indent, "",
+ sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
+ for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
+ ASN1_INTEGER *num;
+ char *tmp;
+ num = sk_ASN1_INTEGER_value(ref->noticenos, i);
+ if (i)
+ BIO_puts(out, ", ");
+ tmp = i2s_ASN1_INTEGER(NULL, num);
+ BIO_puts(out, tmp);
+ OPENSSL_free(tmp);
+ }
+ BIO_puts(out, "\n");
+ }
+ if (notice->exptext)
+ BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
+ notice->exptext->data);
}
void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
- {
- const X509_POLICY_DATA *dat = node->data;
-
- BIO_printf(out, "%*sPolicy: ", indent, "");
-
- i2a_ASN1_OBJECT(out, dat->valid_policy);
- BIO_puts(out, "\n");
- BIO_printf(out, "%*s%s\n", indent + 2, "",
- node_data_critical(dat) ? "Critical" : "Non Critical");
- if (dat->qualifier_set)
- print_qualifiers(out, dat->qualifier_set, indent + 2);
- else
- BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
- }
+{
+ const X509_POLICY_DATA *dat = node->data;
+
+ BIO_printf(out, "%*sPolicy: ", indent, "");
+
+ i2a_ASN1_OBJECT(out, dat->valid_policy);
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*s%s\n", indent + 2, "",
+ node_data_critical(dat) ? "Critical" : "Non Critical");
+ if (dat->qualifier_set)
+ print_qualifiers(out, dat->qualifier_set, indent + 2);
+ else
+ BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
+}
diff --git a/src/crypto/x509v3/v3_crld.c b/src/crypto/x509v3/v3_crld.c
index 3984c316..c93c4495 100644
--- a/src/crypto/x509v3/v3_crld.c
+++ b/src/crypto/x509v3/v3_crld.c
@@ -1,6 +1,7 @@
/* v3_crld.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -65,552 +66,496 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static void *v2i_crld(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
- int indent);
-
-const X509V3_EXT_METHOD v3_crld =
- {
- NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
- 0,0,0,0,
- 0,0,
- 0,
- v2i_crld,
- i2r_crldp,0,
- NULL
- };
-
-const X509V3_EXT_METHOD v3_freshest_crl =
- {
- NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
- 0,0,0,0,
- 0,0,
- 0,
- v2i_crld,
- i2r_crldp,0,
- NULL
- };
-
-static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect)
- {
- STACK_OF(CONF_VALUE) *gnsect;
- STACK_OF(GENERAL_NAME) *gens;
- if (*sect == '@')
- gnsect = X509V3_get_section(ctx, sect + 1);
- else
- gnsect = X509V3_parse_list(sect);
- if (!gnsect)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
- return NULL;
- }
- gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
- if (*sect == '@')
- X509V3_section_free(ctx, gnsect);
- else
- sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
- return gens;
- }
+ int indent);
+
+const X509V3_EXT_METHOD v3_crld = {
+ NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_crld,
+ i2r_crldp, 0,
+ NULL
+};
+
+const X509V3_EXT_METHOD v3_freshest_crl = {
+ NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_crld,
+ i2r_crldp, 0,
+ NULL
+};
+
+static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
+ char *sect)
+{
+ STACK_OF(CONF_VALUE) *gnsect;
+ STACK_OF(GENERAL_NAME) *gens;
+ if (*sect == '@')
+ gnsect = X509V3_get_section(ctx, sect + 1);
+ else
+ gnsect = X509V3_parse_list(sect);
+ if (!gnsect) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+ return NULL;
+ }
+ gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
+ if (*sect == '@')
+ X509V3_section_free(ctx, gnsect);
+ else
+ sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
+ return gens;
+}
static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
- CONF_VALUE *cnf)
- {
- STACK_OF(GENERAL_NAME) *fnm = NULL;
- STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
- if (!strncmp(cnf->name, "fullname", 9))
- {
- fnm = gnames_from_sectname(ctx, cnf->value);
- if (!fnm)
- goto err;
- }
- else if (!strcmp(cnf->name, "relativename"))
- {
- int ret;
- STACK_OF(CONF_VALUE) *dnsect;
- X509_NAME *nm;
- nm = X509_NAME_new();
- if (!nm)
- return -1;
- dnsect = X509V3_get_section(ctx, cnf->value);
- if (!dnsect)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
- return -1;
- }
- ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
- X509V3_section_free(ctx, dnsect);
- rnm = nm->entries;
- nm->entries = NULL;
- X509_NAME_free(nm);
- if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
- goto err;
- /* Since its a name fragment can't have more than one
- * RDNSequence
- */
- if (sk_X509_NAME_ENTRY_value(rnm,
- sk_X509_NAME_ENTRY_num(rnm) - 1)->set)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
- goto err;
- }
- }
- else
- return 0;
-
- if (*pdp)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
- goto err;
- }
-
- *pdp = DIST_POINT_NAME_new();
- if (!*pdp)
- goto err;
- if (fnm)
- {
- (*pdp)->type = 0;
- (*pdp)->name.fullname = fnm;
- }
- else
- {
- (*pdp)->type = 1;
- (*pdp)->name.relativename = rnm;
- }
-
- return 1;
-
- err:
- if (fnm)
- sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
- if (rnm)
- sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
- return -1;
- }
+ CONF_VALUE *cnf)
+{
+ STACK_OF(GENERAL_NAME) *fnm = NULL;
+ STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
+ if (!strncmp(cnf->name, "fullname", 9)) {
+ fnm = gnames_from_sectname(ctx, cnf->value);
+ if (!fnm)
+ goto err;
+ } else if (!strcmp(cnf->name, "relativename")) {
+ int ret;
+ STACK_OF(CONF_VALUE) *dnsect;
+ X509_NAME *nm;
+ nm = X509_NAME_new();
+ if (!nm)
+ return -1;
+ dnsect = X509V3_get_section(ctx, cnf->value);
+ if (!dnsect) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+ return -1;
+ }
+ ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
+ X509V3_section_free(ctx, dnsect);
+ rnm = nm->entries;
+ nm->entries = NULL;
+ X509_NAME_free(nm);
+ if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
+ goto err;
+ /*
+ * Since its a name fragment can't have more than one RDNSequence
+ */
+ if (sk_X509_NAME_ENTRY_value(rnm,
+ sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
+ goto err;
+ }
+ } else
+ return 0;
+
+ if (*pdp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
+ goto err;
+ }
+
+ *pdp = DIST_POINT_NAME_new();
+ if (!*pdp)
+ goto err;
+ if (fnm) {
+ (*pdp)->type = 0;
+ (*pdp)->name.fullname = fnm;
+ } else {
+ (*pdp)->type = 1;
+ (*pdp)->name.relativename = rnm;
+ }
+
+ return 1;
+
+ err:
+ if (fnm)
+ sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
+ if (rnm)
+ sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
+ return -1;
+}
static const BIT_STRING_BITNAME reason_flags[] = {
-{0, "Unused", "unused"},
-{1, "Key Compromise", "keyCompromise"},
-{2, "CA Compromise", "CACompromise"},
-{3, "Affiliation Changed", "affiliationChanged"},
-{4, "Superseded", "superseded"},
-{5, "Cessation Of Operation", "cessationOfOperation"},
-{6, "Certificate Hold", "certificateHold"},
-{7, "Privilege Withdrawn", "privilegeWithdrawn"},
-{8, "AA Compromise", "AACompromise"},
-{-1, NULL, NULL}
+ {0, "Unused", "unused"},
+ {1, "Key Compromise", "keyCompromise"},
+ {2, "CA Compromise", "CACompromise"},
+ {3, "Affiliation Changed", "affiliationChanged"},
+ {4, "Superseded", "superseded"},
+ {5, "Cessation Of Operation", "cessationOfOperation"},
+ {6, "Certificate Hold", "certificateHold"},
+ {7, "Privilege Withdrawn", "privilegeWithdrawn"},
+ {8, "AA Compromise", "AACompromise"},
+ {-1, NULL, NULL}
};
static int set_reasons(ASN1_BIT_STRING **preas, char *value)
- {
- STACK_OF(CONF_VALUE) *rsk = NULL;
- const BIT_STRING_BITNAME *pbn;
- const char *bnam;
- size_t i;
- int ret = 0;
- rsk = X509V3_parse_list(value);
- if (!rsk)
- return 0;
- if (*preas)
- return 0;
- for (i = 0; i < sk_CONF_VALUE_num(rsk); i++)
- {
- bnam = sk_CONF_VALUE_value(rsk, i)->name;
- if (!*preas)
- {
- *preas = ASN1_BIT_STRING_new();
- if (!*preas)
- goto err;
- }
- for (pbn = reason_flags; pbn->lname; pbn++)
- {
- if (!strcmp(pbn->sname, bnam))
- {
- if (!ASN1_BIT_STRING_set_bit(*preas,
- pbn->bitnum, 1))
- goto err;
- break;
- }
- }
- if (!pbn->lname)
- goto err;
- }
- ret = 1;
-
- err:
- sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
- return ret;
- }
+{
+ STACK_OF(CONF_VALUE) *rsk = NULL;
+ const BIT_STRING_BITNAME *pbn;
+ const char *bnam;
+ size_t i;
+ int ret = 0;
+ rsk = X509V3_parse_list(value);
+ if (!rsk)
+ return 0;
+ if (*preas)
+ return 0;
+ for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
+ bnam = sk_CONF_VALUE_value(rsk, i)->name;
+ if (!*preas) {
+ *preas = ASN1_BIT_STRING_new();
+ if (!*preas)
+ goto err;
+ }
+ for (pbn = reason_flags; pbn->lname; pbn++) {
+ if (!strcmp(pbn->sname, bnam)) {
+ if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
+ goto err;
+ break;
+ }
+ }
+ if (!pbn->lname)
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
+ return ret;
+}
static int print_reasons(BIO *out, const char *rname,
- ASN1_BIT_STRING *rflags, int indent)
- {
- int first = 1;
- const BIT_STRING_BITNAME *pbn;
- BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
- for (pbn = reason_flags; pbn->lname; pbn++)
- {
- if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum))
- {
- if (first)
- first = 0;
- else
- BIO_puts(out, ", ");
- BIO_puts(out, pbn->lname);
- }
- }
- if (first)
- BIO_puts(out, "<EMPTY>\n");
- else
- BIO_puts(out, "\n");
- return 1;
- }
+ ASN1_BIT_STRING *rflags, int indent)
+{
+ int first = 1;
+ const BIT_STRING_BITNAME *pbn;
+ BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
+ for (pbn = reason_flags; pbn->lname; pbn++) {
+ if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
+ if (first)
+ first = 0;
+ else
+ BIO_puts(out, ", ");
+ BIO_puts(out, pbn->lname);
+ }
+ }
+ if (first)
+ BIO_puts(out, "<EMPTY>\n");
+ else
+ BIO_puts(out, "\n");
+ return 1;
+}
static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
- {
- size_t i;
- CONF_VALUE *cnf;
- DIST_POINT *point = NULL;
- point = DIST_POINT_new();
- if (!point)
- goto err;
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
- {
- int ret;
- cnf = sk_CONF_VALUE_value(nval, i);
- ret = set_dist_point_name(&point->distpoint, ctx, cnf);
- if (ret > 0)
- continue;
- if (ret < 0)
- goto err;
- if (!strcmp(cnf->name, "reasons"))
- {
- if (!set_reasons(&point->reasons, cnf->value))
- goto err;
- }
- else if (!strcmp(cnf->name, "CRLissuer"))
- {
- point->CRLissuer =
- gnames_from_sectname(ctx, cnf->value);
- if (!point->CRLissuer)
- goto err;
- }
- }
-
- return point;
-
-
- err:
- if (point)
- DIST_POINT_free(point);
- return NULL;
- }
+ STACK_OF(CONF_VALUE) *nval)
+{
+ size_t i;
+ CONF_VALUE *cnf;
+ DIST_POINT *point = NULL;
+ point = DIST_POINT_new();
+ if (!point)
+ goto err;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ int ret;
+ cnf = sk_CONF_VALUE_value(nval, i);
+ ret = set_dist_point_name(&point->distpoint, ctx, cnf);
+ if (ret > 0)
+ continue;
+ if (ret < 0)
+ goto err;
+ if (!strcmp(cnf->name, "reasons")) {
+ if (!set_reasons(&point->reasons, cnf->value))
+ goto err;
+ } else if (!strcmp(cnf->name, "CRLissuer")) {
+ point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
+ if (!point->CRLissuer)
+ goto err;
+ }
+ }
+
+ return point;
+
+ err:
+ if (point)
+ DIST_POINT_free(point);
+ return NULL;
+}
static void *v2i_crld(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
- {
- STACK_OF(DIST_POINT) *crld = NULL;
- GENERAL_NAMES *gens = NULL;
- GENERAL_NAME *gen = NULL;
- CONF_VALUE *cnf;
- size_t i;
- if(!(crld = sk_DIST_POINT_new_null())) goto merr;
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- DIST_POINT *point;
- cnf = sk_CONF_VALUE_value(nval, i);
- if (!cnf->value)
- {
- STACK_OF(CONF_VALUE) *dpsect;
- dpsect = X509V3_get_section(ctx, cnf->name);
- if (!dpsect)
- goto err;
- point = crldp_from_section(ctx, dpsect);
- X509V3_section_free(ctx, dpsect);
- if (!point)
- goto err;
- if(!sk_DIST_POINT_push(crld, point))
- {
- DIST_POINT_free(point);
- goto merr;
- }
- }
- else
- {
- if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
- goto err;
- if(!(gens = GENERAL_NAMES_new()))
- goto merr;
- if(!sk_GENERAL_NAME_push(gens, gen))
- goto merr;
- gen = NULL;
- if(!(point = DIST_POINT_new()))
- goto merr;
- if(!sk_DIST_POINT_push(crld, point))
- {
- DIST_POINT_free(point);
- goto merr;
- }
- if(!(point->distpoint = DIST_POINT_NAME_new()))
- goto merr;
- point->distpoint->name.fullname = gens;
- point->distpoint->type = 0;
- gens = NULL;
- }
- }
- return crld;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- err:
- GENERAL_NAME_free(gen);
- GENERAL_NAMES_free(gens);
- sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
- return NULL;
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ STACK_OF(DIST_POINT) *crld = NULL;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if (!(crld = sk_DIST_POINT_new_null()))
+ goto merr;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ DIST_POINT *point;
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!cnf->value) {
+ STACK_OF(CONF_VALUE) *dpsect;
+ dpsect = X509V3_get_section(ctx, cnf->name);
+ if (!dpsect)
+ goto err;
+ point = crldp_from_section(ctx, dpsect);
+ X509V3_section_free(ctx, dpsect);
+ if (!point)
+ goto err;
+ if (!sk_DIST_POINT_push(crld, point)) {
+ DIST_POINT_free(point);
+ goto merr;
+ }
+ } else {
+ if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+ goto err;
+ if (!(gens = GENERAL_NAMES_new()))
+ goto merr;
+ if (!sk_GENERAL_NAME_push(gens, gen))
+ goto merr;
+ gen = NULL;
+ if (!(point = DIST_POINT_new()))
+ goto merr;
+ if (!sk_DIST_POINT_push(crld, point)) {
+ DIST_POINT_free(point);
+ goto merr;
+ }
+ if (!(point->distpoint = DIST_POINT_NAME_new()))
+ goto merr;
+ point->distpoint->name.fullname = gens;
+ point->distpoint->type = 0;
+ gens = NULL;
+ }
+ }
+ return crld;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ GENERAL_NAME_free(gen);
+ GENERAL_NAMES_free(gens);
+ sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
+ return NULL;
}
IMPLEMENT_ASN1_SET_OF(DIST_POINT)
static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
- {
- DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
-
- switch(operation)
- {
- case ASN1_OP_NEW_POST:
- dpn->dpname = NULL;
- break;
-
- case ASN1_OP_FREE_POST:
- if (dpn->dpname)
- X509_NAME_free(dpn->dpname);
- break;
- }
- return 1;
- }
+ void *exarg)
+{
+ DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
+
+ switch (operation) {
+ case ASN1_OP_NEW_POST:
+ dpn->dpname = NULL;
+ break;
+
+ case ASN1_OP_FREE_POST:
+ if (dpn->dpname)
+ X509_NAME_free(dpn->dpname);
+ break;
+ }
+ return 1;
+}
ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
- ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
- ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
+ ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
+ ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
ASN1_SEQUENCE(DIST_POINT) = {
- ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
- ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
- ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
+ ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
+ ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
} ASN1_SEQUENCE_END(DIST_POINT)
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
-ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
+ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
- ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
+ ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
- int indent);
+ int indent);
static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-
-const X509V3_EXT_METHOD v3_idp =
- {
- NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
- ASN1_ITEM_ref(ISSUING_DIST_POINT),
- 0,0,0,0,
- 0,0,
- 0,
- v2i_idp,
- i2r_idp,0,
- NULL
- };
+ STACK_OF(CONF_VALUE) *nval);
+
+const X509V3_EXT_METHOD v3_idp = {
+ NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(ISSUING_DIST_POINT),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_idp,
+ i2r_idp, 0,
+ NULL
+};
static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
- {
- ISSUING_DIST_POINT *idp = NULL;
- CONF_VALUE *cnf;
- char *name, *val;
- size_t i;
- int ret;
- idp = ISSUING_DIST_POINT_new();
- if (!idp)
- goto merr;
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
- {
- cnf = sk_CONF_VALUE_value(nval, i);
- name = cnf->name;
- val = cnf->value;
- ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
- if (ret > 0)
- continue;
- if (ret < 0)
- goto err;
- if (!strcmp(name, "onlyuser"))
- {
- if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
- goto err;
- }
- else if (!strcmp(name, "onlyCA"))
- {
- if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
- goto err;
- }
- else if (!strcmp(name, "onlyAA"))
- {
- if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
- goto err;
- }
- else if (!strcmp(name, "indirectCRL"))
- {
- if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
- goto err;
- }
- else if (!strcmp(name, "onlysomereasons"))
- {
- if (!set_reasons(&idp->onlysomereasons, val))
- goto err;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- return idp;
-
- merr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- err:
- ISSUING_DIST_POINT_free(idp);
- return NULL;
- }
+ STACK_OF(CONF_VALUE) *nval)
+{
+ ISSUING_DIST_POINT *idp = NULL;
+ CONF_VALUE *cnf;
+ char *name, *val;
+ size_t i;
+ int ret;
+ idp = ISSUING_DIST_POINT_new();
+ if (!idp)
+ goto merr;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ name = cnf->name;
+ val = cnf->value;
+ ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
+ if (ret > 0)
+ continue;
+ if (ret < 0)
+ goto err;
+ if (!strcmp(name, "onlyuser")) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
+ goto err;
+ } else if (!strcmp(name, "onlyCA")) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
+ goto err;
+ } else if (!strcmp(name, "onlyAA")) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
+ goto err;
+ } else if (!strcmp(name, "indirectCRL")) {
+ if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
+ goto err;
+ } else if (!strcmp(name, "onlysomereasons")) {
+ if (!set_reasons(&idp->onlysomereasons, val))
+ goto err;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ return idp;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ ISSUING_DIST_POINT_free(idp);
+ return NULL;
+}
static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
- {
- size_t i;
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
- {
- BIO_printf(out, "%*s", indent + 2, "");
- GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
- BIO_puts(out, "\n");
- }
- return 1;
- }
+{
+ size_t i;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ BIO_printf(out, "%*s", indent + 2, "");
+ GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
+ BIO_puts(out, "\n");
+ }
+ return 1;
+}
static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
- {
- if (dpn->type == 0)
- {
- BIO_printf(out, "%*sFull Name:\n", indent, "");
- print_gens(out, dpn->name.fullname, indent);
- }
- else
- {
- X509_NAME ntmp;
- ntmp.entries = dpn->name.relativename;
- BIO_printf(out, "%*sRelative Name:\n%*s",
- indent, "", indent + 2, "");
- X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
- BIO_puts(out, "\n");
- }
- return 1;
- }
+{
+ if (dpn->type == 0) {
+ BIO_printf(out, "%*sFull Name:\n", indent, "");
+ print_gens(out, dpn->name.fullname, indent);
+ } else {
+ X509_NAME ntmp;
+ ntmp.entries = dpn->name.relativename;
+ BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
+ X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
+ BIO_puts(out, "\n");
+ }
+ return 1;
+}
static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
- int indent)
- {
- ISSUING_DIST_POINT *idp = pidp;
- if (idp->distpoint)
- print_distpoint(out, idp->distpoint, indent);
- if (idp->onlyuser > 0)
- BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
- if (idp->onlyCA > 0)
- BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
- if (idp->indirectCRL > 0)
- BIO_printf(out, "%*sIndirect CRL\n", indent, "");
- if (idp->onlysomereasons)
- print_reasons(out, "Only Some Reasons",
- idp->onlysomereasons, indent);
- if (idp->onlyattr > 0)
- BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
- if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
- && (idp->indirectCRL <= 0) && !idp->onlysomereasons
- && (idp->onlyattr <= 0))
- BIO_printf(out, "%*s<EMPTY>\n", indent, "");
-
- return 1;
- }
+ int indent)
+{
+ ISSUING_DIST_POINT *idp = pidp;
+ if (idp->distpoint)
+ print_distpoint(out, idp->distpoint, indent);
+ if (idp->onlyuser > 0)
+ BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
+ if (idp->onlyCA > 0)
+ BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
+ if (idp->indirectCRL > 0)
+ BIO_printf(out, "%*sIndirect CRL\n", indent, "");
+ if (idp->onlysomereasons)
+ print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
+ if (idp->onlyattr > 0)
+ BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
+ if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
+ && (idp->indirectCRL <= 0) && !idp->onlysomereasons
+ && (idp->onlyattr <= 0))
+ BIO_printf(out, "%*s<EMPTY>\n", indent, "");
+
+ return 1;
+}
static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
- int indent)
- {
- STACK_OF(DIST_POINT) *crld = pcrldp;
- DIST_POINT *point;
- size_t i;
- for(i = 0; i < sk_DIST_POINT_num(crld); i++)
- {
- BIO_puts(out, "\n");
- point = sk_DIST_POINT_value(crld, i);
- if(point->distpoint)
- print_distpoint(out, point->distpoint, indent);
- if(point->reasons)
- print_reasons(out, "Reasons", point->reasons,
- indent);
- if(point->CRLissuer)
- {
- BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
- print_gens(out, point->CRLissuer, indent);
- }
- }
- return 1;
- }
+ int indent)
+{
+ STACK_OF(DIST_POINT) *crld = pcrldp;
+ DIST_POINT *point;
+ size_t i;
+ for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
+ BIO_puts(out, "\n");
+ point = sk_DIST_POINT_value(crld, i);
+ if (point->distpoint)
+ print_distpoint(out, point->distpoint, indent);
+ if (point->reasons)
+ print_reasons(out, "Reasons", point->reasons, indent);
+ if (point->CRLissuer) {
+ BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
+ print_gens(out, point->CRLissuer, indent);
+ }
+ }
+ return 1;
+}
int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
- {
- size_t i;
- STACK_OF(X509_NAME_ENTRY) *frag;
- X509_NAME_ENTRY *ne;
- if (!dpn || (dpn->type != 1))
- return 1;
- frag = dpn->name.relativename;
- dpn->dpname = X509_NAME_dup(iname);
- if (!dpn->dpname)
- return 0;
- for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++)
- {
- ne = sk_X509_NAME_ENTRY_value(frag, i);
- if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
- {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
- }
- /* generate cached encoding of name */
- if (i2d_X509_NAME(dpn->dpname, NULL) < 0)
- {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
- return 1;
- }
+{
+ size_t i;
+ STACK_OF(X509_NAME_ENTRY) *frag;
+ X509_NAME_ENTRY *ne;
+ if (!dpn || (dpn->type != 1))
+ return 1;
+ frag = dpn->name.relativename;
+ dpn->dpname = X509_NAME_dup(iname);
+ if (!dpn->dpname)
+ return 0;
+ for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
+ ne = sk_X509_NAME_ENTRY_value(frag, i);
+ if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
+ X509_NAME_free(dpn->dpname);
+ dpn->dpname = NULL;
+ return 0;
+ }
+ }
+ /* generate cached encoding of name */
+ if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
+ X509_NAME_free(dpn->dpname);
+ dpn->dpname = NULL;
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/crypto/x509v3/v3_enum.c b/src/crypto/x509v3/v3_enum.c
index 0fe6bb63..6bfb232c 100644
--- a/src/crypto/x509v3/v3_enum.c
+++ b/src/crypto/x509v3/v3_enum.c
@@ -1,6 +1,7 @@
/* v3_enum.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -60,39 +61,40 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static const ENUMERATED_NAMES crl_reasons[] = {
-{CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
-{CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
-{CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
-{CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"},
-{CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
-{CRL_REASON_CESSATION_OF_OPERATION,
- "Cessation Of Operation", "cessationOfOperation"},
-{CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
-{CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
-{CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"},
-{CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
-{-1, NULL, NULL}
+ {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
+ {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
+ {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
+ {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed",
+ "affiliationChanged"},
+ {CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
+ {CRL_REASON_CESSATION_OF_OPERATION,
+ "Cessation Of Operation", "cessationOfOperation"},
+ {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
+ {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
+ {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn",
+ "privilegeWithdrawn"},
+ {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
+ {-1, NULL, NULL}
};
-const X509V3_EXT_METHOD v3_crl_reason = {
-NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
-0,0,0,0,
-(X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
-0,
-0,0,0,0,
-(void *)crl_reasons};
-
+const X509V3_EXT_METHOD v3_crl_reason = {
+ NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
+ 0,
+ 0, 0, 0, 0,
+ (void *)crl_reasons
+};
-char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
- ASN1_ENUMERATED *e)
+char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *e)
{
- const ENUMERATED_NAMES *enam;
- long strval;
- strval = ASN1_ENUMERATED_get(e);
- for(enam = method->usr_data; enam->lname; enam++) {
- if(strval == enam->bitnum) return BUF_strdup(enam->lname);
- }
- return i2s_ASN1_ENUMERATED(method, e);
+ const ENUMERATED_NAMES *enam;
+ long strval;
+ strval = ASN1_ENUMERATED_get(e);
+ for (enam = method->usr_data; enam->lname; enam++) {
+ if (strval == enam->bitnum)
+ return BUF_strdup(enam->lname);
+ }
+ return i2s_ASN1_ENUMERATED(method, e);
}
diff --git a/src/crypto/x509v3/v3_extku.c b/src/crypto/x509v3/v3_extku.c
index d64eb9cc..952e032c 100644
--- a/src/crypto/x509v3/v3_extku.c
+++ b/src/crypto/x509v3/v3_extku.c
@@ -1,6 +1,7 @@
/* v3_extku.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <openssl/asn1t.h>
@@ -63,83 +63,86 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
- void *eku, STACK_OF(CONF_VALUE) *extlist);
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+ *method, void *eku, STACK_OF(CONF_VALUE)
+ *extlist);
const X509V3_EXT_METHOD v3_ext_ku = {
- NID_ext_key_usage, 0,
- ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
- 0,0,0,0,
- 0,0,
- i2v_EXTENDED_KEY_USAGE,
- v2i_EXTENDED_KEY_USAGE,
- 0,0,
- NULL
+ NID_ext_key_usage, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0, 0,
+ NULL
};
/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
const X509V3_EXT_METHOD v3_ocsp_accresp = {
- NID_id_pkix_OCSP_acceptableResponses, 0,
- ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
- 0,0,0,0,
- 0,0,
- i2v_EXTENDED_KEY_USAGE,
- v2i_EXTENDED_KEY_USAGE,
- 0,0,
- NULL
+ NID_id_pkix_OCSP_acceptableResponses, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0, 0,
+ NULL
};
-ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
+ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
-static STACK_OF(CONF_VALUE) *
- i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, void *a,
- STACK_OF(CONF_VALUE) *ext_list)
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *ext_list)
{
- EXTENDED_KEY_USAGE *eku = a;
- size_t i;
- ASN1_OBJECT *obj;
- char obj_tmp[80];
- for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
- obj = sk_ASN1_OBJECT_value(eku, i);
- i2t_ASN1_OBJECT(obj_tmp, 80, obj);
- X509V3_add_value(NULL, obj_tmp, &ext_list);
- }
- return ext_list;
+ EXTENDED_KEY_USAGE *eku = a;
+ size_t i;
+ ASN1_OBJECT *obj;
+ char obj_tmp[80];
+ for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+ obj = sk_ASN1_OBJECT_value(eku, i);
+ i2t_ASN1_OBJECT(obj_tmp, 80, obj);
+ X509V3_add_value(NULL, obj_tmp, &ext_list);
+ }
+ return ext_list;
}
static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
{
- EXTENDED_KEY_USAGE *extku;
- char *extval;
- ASN1_OBJECT *objtmp;
- CONF_VALUE *val;
- size_t i;
+ EXTENDED_KEY_USAGE *extku;
+ char *extval;
+ ASN1_OBJECT *objtmp;
+ CONF_VALUE *val;
+ size_t i;
- if(!(extku = sk_ASN1_OBJECT_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if (!(extku = sk_ASN1_OBJECT_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if(val->value) extval = val->value;
- else extval = val->name;
- if(!(objtmp = OBJ_txt2obj(extval, 0))) {
- sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return NULL;
- }
- sk_ASN1_OBJECT_push(extku, objtmp);
- }
- return extku;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (val->value)
+ extval = val->value;
+ else
+ extval = val->name;
+ if (!(objtmp = OBJ_txt2obj(extval, 0))) {
+ sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ sk_ASN1_OBJECT_push(extku, objtmp);
+ }
+ return extku;
}
diff --git a/src/crypto/x509v3/v3_genn.c b/src/crypto/x509v3/v3_genn.c
index 8b0a68d4..2331cd49 100644
--- a/src/crypto/x509v3/v3_genn.c
+++ b/src/crypto/x509v3/v3_genn.c
@@ -1,6 +1,7 @@
/* v3_genn.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <openssl/asn1t.h>
@@ -64,189 +64,187 @@
ASN1_SEQUENCE(OTHERNAME) = {
- ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
- /* Maybe have a true ANY DEFINED BY later */
- ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
+ ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
+ /* Maybe have a true ANY DEFINED BY later */
+ ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
} ASN1_SEQUENCE_END(OTHERNAME)
IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
ASN1_SEQUENCE(EDIPARTYNAME) = {
- ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
- ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
+ ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
+ ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
} ASN1_SEQUENCE_END(EDIPARTYNAME)
IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
ASN1_CHOICE(GENERAL_NAME) = {
- ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
- ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
- ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
- /* Don't decode this */
- ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
- /* X509_NAME is a CHOICE type so use EXPLICIT */
- ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
- ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
- ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
- ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
- ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
+ ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
+ ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
+ ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
+ /* Don't decode this */
+ ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
+ /* X509_NAME is a CHOICE type so use EXPLICIT */
+ ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
+ ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
+ ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
+ ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
+ ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
} ASN1_CHOICE_END(GENERAL_NAME)
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
-ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
+ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
- {
- return (GENERAL_NAME *) ASN1_dup((i2d_of_void *) i2d_GENERAL_NAME,
- (d2i_of_void *) d2i_GENERAL_NAME,
- (char *) a);
- }
+{
+ return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
+ (d2i_of_void *)d2i_GENERAL_NAME,
+ (char *)a);
+}
/* Returns 0 if they are equal, != 0 otherwise. */
int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
- {
- int result = -1;
-
- if (!a || !b || a->type != b->type) return -1;
- switch(a->type)
- {
- case GEN_X400:
- case GEN_EDIPARTY:
- result = ASN1_TYPE_cmp(a->d.other, b->d.other);
- break;
-
- case GEN_OTHERNAME:
- result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
- break;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
- break;
-
- case GEN_DIRNAME:
- result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
- break;
-
- case GEN_IPADD:
- result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
- break;
-
- case GEN_RID:
- result = OBJ_cmp(a->d.rid, b->d.rid);
- break;
- }
- return result;
- }
+{
+ int result = -1;
+
+ if (!a || !b || a->type != b->type)
+ return -1;
+ switch (a->type) {
+ case GEN_X400:
+ case GEN_EDIPARTY:
+ result = ASN1_TYPE_cmp(a->d.other, b->d.other);
+ break;
+
+ case GEN_OTHERNAME:
+ result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
+ break;
+
+ case GEN_DIRNAME:
+ result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
+ break;
+
+ case GEN_IPADD:
+ result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
+ break;
+
+ case GEN_RID:
+ result = OBJ_cmp(a->d.rid, b->d.rid);
+ break;
+ }
+ return result;
+}
/* Returns 0 if they are equal, != 0 otherwise. */
int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
- {
- int result = -1;
-
- if (!a || !b) return -1;
- /* Check their type first. */
- if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
- return result;
- /* Check the value. */
- result = ASN1_TYPE_cmp(a->value, b->value);
- return result;
- }
+{
+ int result = -1;
+
+ if (!a || !b)
+ return -1;
+ /* Check their type first. */
+ if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
+ return result;
+ /* Check the value. */
+ result = ASN1_TYPE_cmp(a->value, b->value);
+ return result;
+}
void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
- {
- switch(type)
- {
- case GEN_X400:
- case GEN_EDIPARTY:
- a->d.other = value;
- break;
-
- case GEN_OTHERNAME:
- a->d.otherName = value;
- break;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- a->d.ia5 = value;
- break;
-
- case GEN_DIRNAME:
- a->d.dirn = value;
- break;
-
- case GEN_IPADD:
- a->d.ip = value;
- break;
-
- case GEN_RID:
- a->d.rid = value;
- break;
- }
- a->type = type;
- }
+{
+ switch (type) {
+ case GEN_X400:
+ case GEN_EDIPARTY:
+ a->d.other = value;
+ break;
+
+ case GEN_OTHERNAME:
+ a->d.otherName = value;
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ a->d.ia5 = value;
+ break;
+
+ case GEN_DIRNAME:
+ a->d.dirn = value;
+ break;
+
+ case GEN_IPADD:
+ a->d.ip = value;
+ break;
+
+ case GEN_RID:
+ a->d.rid = value;
+ break;
+ }
+ a->type = type;
+}
void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
- {
- if (ptype)
- *ptype = a->type;
- switch(a->type)
- {
- case GEN_X400:
- case GEN_EDIPARTY:
- return a->d.other;
-
- case GEN_OTHERNAME:
- return a->d.otherName;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- return a->d.ia5;
-
- case GEN_DIRNAME:
- return a->d.dirn;
-
- case GEN_IPADD:
- return a->d.ip;
-
- case GEN_RID:
- return a->d.rid;
-
- default:
- return NULL;
- }
- }
+{
+ if (ptype)
+ *ptype = a->type;
+ switch (a->type) {
+ case GEN_X400:
+ case GEN_EDIPARTY:
+ return a->d.other;
-int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
- ASN1_OBJECT *oid, ASN1_TYPE *value)
- {
- OTHERNAME *oth;
- oth = OTHERNAME_new();
- if (!oth)
- return 0;
- oth->type_id = oid;
- oth->value = value;
- GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
- return 1;
- }
-
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
- ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
- {
- if (gen->type != GEN_OTHERNAME)
- return 0;
- if (poid)
- *poid = gen->d.otherName->type_id;
- if (pvalue)
- *pvalue = gen->d.otherName->value;
- return 1;
- }
+ case GEN_OTHERNAME:
+ return a->d.otherName;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ return a->d.ia5;
+
+ case GEN_DIRNAME:
+ return a->d.dirn;
+ case GEN_IPADD:
+ return a->d.ip;
+
+ case GEN_RID:
+ return a->d.rid;
+
+ default:
+ return NULL;
+ }
+}
+
+int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+ ASN1_OBJECT *oid, ASN1_TYPE *value)
+{
+ OTHERNAME *oth;
+ oth = OTHERNAME_new();
+ if (!oth)
+ return 0;
+ oth->type_id = oid;
+ oth->value = value;
+ GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
+ return 1;
+}
+
+int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+ ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
+{
+ if (gen->type != GEN_OTHERNAME)
+ return 0;
+ if (poid)
+ *poid = gen->d.otherName->type_id;
+ if (pvalue)
+ *pvalue = gen->d.otherName->value;
+ return 1;
+}
diff --git a/src/crypto/x509v3/v3_ia5.c b/src/crypto/x509v3/v3_ia5.c
index 5a272335..6fc6b59b 100644
--- a/src/crypto/x509v3/v3_ia5.c
+++ b/src/crypto/x509v3/v3_ia5.c
@@ -1,6 +1,7 @@
/* v3_ia5.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -66,52 +67,53 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
-static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_ns_ia5_list[] = {
-EXT_IA5STRING(NID_netscape_base_url),
-EXT_IA5STRING(NID_netscape_revocation_url),
-EXT_IA5STRING(NID_netscape_ca_revocation_url),
-EXT_IA5STRING(NID_netscape_renewal_url),
-EXT_IA5STRING(NID_netscape_ca_policy_url),
-EXT_IA5STRING(NID_netscape_ssl_server_name),
-EXT_IA5STRING(NID_netscape_comment),
-EXT_END
+static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ ASN1_IA5STRING *ia5);
+static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD v3_ns_ia5_list[] = {
+ EXT_IA5STRING(NID_netscape_base_url),
+ EXT_IA5STRING(NID_netscape_revocation_url),
+ EXT_IA5STRING(NID_netscape_ca_revocation_url),
+ EXT_IA5STRING(NID_netscape_renewal_url),
+ EXT_IA5STRING(NID_netscape_ca_policy_url),
+ EXT_IA5STRING(NID_netscape_ssl_server_name),
+ EXT_IA5STRING(NID_netscape_comment),
+ EXT_END
};
-
static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
- ASN1_IA5STRING *ia5)
+ ASN1_IA5STRING *ia5)
{
- char *tmp;
- if(!ia5 || !ia5->length) return NULL;
- if(!(tmp = OPENSSL_malloc(ia5->length + 1))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- memcpy(tmp, ia5->data, ia5->length);
- tmp[ia5->length] = 0;
- return tmp;
+ char *tmp;
+ if (!ia5 || !ia5->length)
+ return NULL;
+ if (!(tmp = OPENSSL_malloc(ia5->length + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memcpy(tmp, ia5->data, ia5->length);
+ tmp[ia5->length] = 0;
+ return tmp;
}
static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str)
+ X509V3_CTX *ctx, char *str)
{
- ASN1_IA5STRING *ia5;
- if(!str) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
- return NULL;
- }
- if(!(ia5 = M_ASN1_IA5STRING_new())) goto err;
- if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str,
- strlen(str))) {
- M_ASN1_IA5STRING_free(ia5);
- goto err;
- }
- return ia5;
- err:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
+ ASN1_IA5STRING *ia5;
+ if (!str) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (!(ia5 = M_ASN1_IA5STRING_new()))
+ goto err;
+ if (!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char *)str,
+ strlen(str))) {
+ M_ASN1_IA5STRING_free(ia5);
+ goto err;
+ }
+ return ia5;
+ err:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
}
-
diff --git a/src/crypto/x509v3/v3_info.c b/src/crypto/x509v3/v3_info.c
index 475c56f7..482208d7 100644
--- a/src/crypto/x509v3/v3_info.c
+++ b/src/crypto/x509v3/v3_info.c
@@ -1,6 +1,7 @@
/* v3_info.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -68,133 +69,144 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method, AUTHORITY_INFO_ACCESS
+ *ainfo, STACK_OF(CONF_VALUE)
+ *ret);
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE)
+ *nval);
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
- AUTHORITY_INFO_ACCESS *ainfo,
- STACK_OF(CONF_VALUE) *ret);
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+ 0, 0,
+ NULL
+};
-const X509V3_EXT_METHOD v3_info =
-{ NID_info_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
-(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
-0,0,
-NULL};
-
-const X509V3_EXT_METHOD v3_sinfo =
-{ NID_sinfo_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
-(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
-0,0,
-NULL};
+const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+ 0, 0,
+ NULL
+};
ASN1_SEQUENCE(ACCESS_DESCRIPTION) = {
- ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
- ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION)
IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
-ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
+ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS)
IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
- AUTHORITY_INFO_ACCESS *ainfo,
- STACK_OF(CONF_VALUE) *ret)
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method, AUTHORITY_INFO_ACCESS
+ *ainfo, STACK_OF(CONF_VALUE)
+ *ret)
{
- ACCESS_DESCRIPTION *desc;
- size_t i;
- int nlen;
- char objtmp[80], *ntmp;
- CONF_VALUE *vtmp;
- for(i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
- desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
- ret = i2v_GENERAL_NAME(method, desc->location, ret);
- if(!ret) break;
- vtmp = sk_CONF_VALUE_value(ret, i);
- i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method);
- nlen = strlen(objtmp) + strlen(vtmp->name) + 5;
- ntmp = OPENSSL_malloc(nlen);
- if(!ntmp) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- BUF_strlcpy(ntmp, objtmp, nlen);
- BUF_strlcat(ntmp, " - ", nlen);
- BUF_strlcat(ntmp, vtmp->name, nlen);
- OPENSSL_free(vtmp->name);
- vtmp->name = ntmp;
-
- }
- if(!ret) return sk_CONF_VALUE_new_null();
- return ret;
+ ACCESS_DESCRIPTION *desc;
+ size_t i;
+ int nlen;
+ char objtmp[80], *ntmp;
+ CONF_VALUE *vtmp;
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+ desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
+ ret = i2v_GENERAL_NAME(method, desc->location, ret);
+ if (!ret)
+ break;
+ vtmp = sk_CONF_VALUE_value(ret, i);
+ i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method);
+ nlen = strlen(objtmp) + strlen(vtmp->name) + 5;
+ ntmp = OPENSSL_malloc(nlen);
+ if (!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ BUF_strlcpy(ntmp, objtmp, nlen);
+ BUF_strlcat(ntmp, " - ", nlen);
+ BUF_strlcat(ntmp, vtmp->name, nlen);
+ OPENSSL_free(vtmp->name);
+ vtmp->name = ntmp;
+
+ }
+ if (!ret)
+ return sk_CONF_VALUE_new_null();
+ return ret;
}
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE)
+ *nval)
{
- AUTHORITY_INFO_ACCESS *ainfo = NULL;
- CONF_VALUE *cnf, ctmp;
- ACCESS_DESCRIPTION *acc;
- size_t i;
- int objlen;
- char *objtmp, *ptmp;
- if(!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if(!(acc = ACCESS_DESCRIPTION_new())
- || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ptmp = strchr(cnf->name, ';');
- if(!ptmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
- goto err;
- }
- objlen = ptmp - cnf->name;
- ctmp.name = ptmp + 1;
- ctmp.value = cnf->value;
- if(!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
- goto err;
- if(!(objtmp = OPENSSL_malloc(objlen + 1))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- strncpy(objtmp, cnf->name, objlen);
- objtmp[objlen] = 0;
- acc->method = OBJ_txt2obj(objtmp, 0);
- if(!acc->method) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
- ERR_add_error_data(2, "value=", objtmp);
- OPENSSL_free(objtmp);
- goto err;
- }
- OPENSSL_free(objtmp);
+ AUTHORITY_INFO_ACCESS *ainfo = NULL;
+ CONF_VALUE *cnf, ctmp;
+ ACCESS_DESCRIPTION *acc;
+ size_t i;
+ int objlen;
+ char *objtmp, *ptmp;
+ if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!(acc = ACCESS_DESCRIPTION_new())
+ || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ptmp = strchr(cnf->name, ';');
+ if (!ptmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
+ goto err;
+ }
+ objlen = ptmp - cnf->name;
+ ctmp.name = ptmp + 1;
+ ctmp.value = cnf->value;
+ if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
+ goto err;
+ if (!(objtmp = OPENSSL_malloc(objlen + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ strncpy(objtmp, cnf->name, objlen);
+ objtmp[objlen] = 0;
+ acc->method = OBJ_txt2obj(objtmp, 0);
+ if (!acc->method) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
+ ERR_add_error_data(2, "value=", objtmp);
+ OPENSSL_free(objtmp);
+ goto err;
+ }
+ OPENSSL_free(objtmp);
- }
- return ainfo;
- err:
- sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
- return NULL;
+ }
+ return ainfo;
+ err:
+ sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
+ return NULL;
}
-int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a)
- {
- i2a_ASN1_OBJECT(bp, a->method);
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION *a)
+{
+ i2a_ASN1_OBJECT(bp, a->method);
#ifdef UNDEF
- i2a_GENERAL_NAME(bp, a->location);
+ i2a_GENERAL_NAME(bp, a->location);
#endif
- return 2;
- }
+ return 2;
+}
diff --git a/src/crypto/x509v3/v3_int.c b/src/crypto/x509v3/v3_int.c
index 8ca23bd7..7bde446c 100644
--- a/src/crypto/x509v3/v3_int.c
+++ b/src/crypto/x509v3/v3_int.c
@@ -1,6 +1,7 @@
/* v3_int.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -59,29 +60,32 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
+const X509V3_EXT_METHOD v3_crl_num = {
+ NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0, 0, 0, 0, NULL
+};
-const X509V3_EXT_METHOD v3_crl_num = {
- NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0,0,0,0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- 0,
- 0,0,0,0, NULL};
+const X509V3_EXT_METHOD v3_delta_crl = {
+ NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0, 0, 0, 0, NULL
+};
-const X509V3_EXT_METHOD v3_delta_crl = {
- NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0,0,0,0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- 0,
- 0,0,0,0, NULL};
+static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
+ char *value)
+{
+ return s2i_ASN1_INTEGER(meth, value);
+}
-static void * s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, char *value)
- {
- return s2i_ASN1_INTEGER(meth, value);
- }
-
-const X509V3_EXT_METHOD v3_inhibit_anyp = {
- NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0,0,0,0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- (X509V3_EXT_S2I)s2i_asn1_int,
- 0,0,0,0, NULL};
+const X509V3_EXT_METHOD v3_inhibit_anyp = {
+ NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ (X509V3_EXT_S2I)s2i_asn1_int,
+ 0, 0, 0, 0, NULL
+};
diff --git a/src/crypto/x509v3/v3_lib.c b/src/crypto/x509v3/v3_lib.c
index f8e5531d..c4718e33 100644
--- a/src/crypto/x509v3/v3_lib.c
+++ b/src/crypto/x509v3/v3_lib.c
@@ -1,6 +1,7 @@
/* v3_lib.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -70,266 +71,292 @@ static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
static void ext_list_free(X509V3_EXT_METHOD *ext);
-static int ext_stack_cmp(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b)
+static int ext_stack_cmp(const X509V3_EXT_METHOD **a,
+ const X509V3_EXT_METHOD **b)
{
- return ((*a)->ext_nid - (*b)->ext_nid);
+ return ((*a)->ext_nid - (*b)->ext_nid);
}
int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
{
- if(!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- ext_list_free(ext);
- return 0;
- }
- if(!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- ext_list_free(ext);
- return 0;
- }
- return 1;
+ if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ ext_list_free(ext);
+ return 0;
+ }
+ if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ ext_list_free(ext);
+ return 0;
+ }
+ return 1;
}
-static int ext_cmp(const void *void_a,
- const void *void_b)
+static int ext_cmp(const void *void_a, const void *void_b)
{
- const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD**) void_a;
- const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD**) void_b;
- return ext_stack_cmp(a, b);
+ const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a;
+ const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b;
+ return ext_stack_cmp(a, b);
}
const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
{
- X509V3_EXT_METHOD tmp;
- const X509V3_EXT_METHOD *t = &tmp, * const *ret;
- size_t idx;
-
- if(nid < 0) return NULL;
- tmp.ext_nid = nid;
- ret = bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, sizeof(X509V3_EXT_METHOD*), ext_cmp);
- if(ret) return *ret;
- if(!ext_list) return NULL;
-
- if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
- return NULL;
- return sk_X509V3_EXT_METHOD_value(ext_list, idx);
+ X509V3_EXT_METHOD tmp;
+ const X509V3_EXT_METHOD *t = &tmp, *const *ret;
+ size_t idx;
+
+ if (nid < 0)
+ return NULL;
+ tmp.ext_nid = nid;
+ ret =
+ bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT,
+ sizeof(X509V3_EXT_METHOD *), ext_cmp);
+ if (ret)
+ return *ret;
+ if (!ext_list)
+ return NULL;
+
+ if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
+ return NULL;
+ return sk_X509V3_EXT_METHOD_value(ext_list, idx);
}
const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
{
- int nid;
- if((nid = OBJ_obj2nid(ext->object)) == NID_undef) return NULL;
- return X509V3_EXT_get_nid(nid);
+ int nid;
+ if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
+ return NULL;
+ return X509V3_EXT_get_nid(nid);
}
int X509V3_EXT_free(int nid, void *ext_data)
{
- const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
- if (ext_method == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
- return 0;
- }
-
- if (ext_method->it != NULL)
- ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
- else if (ext_method->ext_free != NULL)
- ext_method->ext_free(ext_data);
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
- return 0;
- }
-
- return 1;
+ const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
+ if (ext_method == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+ return 0;
+ }
+
+ if (ext_method->it != NULL)
+ ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
+ else if (ext_method->ext_free != NULL)
+ ext_method->ext_free(ext_data);
+ else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+ return 0;
+ }
+
+ return 1;
}
int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
{
- for(;extlist->ext_nid!=-1;extlist++)
- if(!X509V3_EXT_add(extlist)) return 0;
- return 1;
+ for (; extlist->ext_nid != -1; extlist++)
+ if (!X509V3_EXT_add(extlist))
+ return 0;
+ return 1;
}
int X509V3_EXT_add_alias(int nid_to, int nid_from)
{
- const X509V3_EXT_METHOD *ext;
- X509V3_EXT_METHOD *tmpext;
-
- if(!(ext = X509V3_EXT_get_nid(nid_from))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND);
- return 0;
- }
- if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- *tmpext = *ext;
- tmpext->ext_nid = nid_to;
- tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
- return X509V3_EXT_add(tmpext);
+ const X509V3_EXT_METHOD *ext;
+ X509V3_EXT_METHOD *tmpext;
+
+ if (!(ext = X509V3_EXT_get_nid(nid_from))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND);
+ return 0;
+ }
+ if (!
+ (tmpext =
+ (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ *tmpext = *ext;
+ tmpext->ext_nid = nid_to;
+ tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
+ return X509V3_EXT_add(tmpext);
}
void X509V3_EXT_cleanup(void)
{
- sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
- ext_list = NULL;
+ sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
+ ext_list = NULL;
}
static void ext_list_free(X509V3_EXT_METHOD *ext)
{
- if(ext->ext_flags & X509V3_EXT_DYNAMIC) OPENSSL_free(ext);
+ if (ext->ext_flags & X509V3_EXT_DYNAMIC)
+ OPENSSL_free(ext);
}
-/* Legacy function: we don't need to add standard extensions
- * any more because they are now kept in ext_dat.h.
+/*
+ * Legacy function: we don't need to add standard extensions any more because
+ * they are now kept in ext_dat.h.
*/
int X509V3_add_standard_extensions(void)
{
- return 1;
+ return 1;
}
/* Return an extension internal structure */
void *X509V3_EXT_d2i(X509_EXTENSION *ext)
{
- const X509V3_EXT_METHOD *method;
- const unsigned char *p;
-
- if(!(method = X509V3_EXT_get(ext))) return NULL;
- p = ext->value->data;
- if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
- return method->d2i(NULL, &p, ext->value->length);
+ const X509V3_EXT_METHOD *method;
+ const unsigned char *p;
+
+ if (!(method = X509V3_EXT_get(ext)))
+ return NULL;
+ p = ext->value->data;
+ if (method->it)
+ return ASN1_item_d2i(NULL, &p, ext->value->length,
+ ASN1_ITEM_ptr(method->it));
+ return method->d2i(NULL, &p, ext->value->length);
}
-/* Get critical flag and decoded version of extension from a NID.
- * The "idx" variable returns the last found extension and can
- * be used to retrieve multiple extensions of the same NID.
- * However multiple extensions with the same NID is usually
- * due to a badly encoded certificate so if idx is NULL we
- * choke if multiple extensions exist.
- * The "crit" variable is set to the critical value.
- * The return value is the decoded extension or NULL on
- * error. The actual error can have several different causes,
- * the value of *crit reflects the cause:
- * >= 0, extension found but not decoded (reflects critical value).
- * -1 extension not found.
- * -2 extension occurs more than once.
+/*
+ * Get critical flag and decoded version of extension from a NID. The "idx"
+ * variable returns the last found extension and can be used to retrieve
+ * multiple extensions of the same NID. However multiple extensions with the
+ * same NID is usually due to a badly encoded certificate so if idx is NULL
+ * we choke if multiple extensions exist. The "crit" variable is set to the
+ * critical value. The return value is the decoded extension or NULL on
+ * error. The actual error can have several different causes, the value of
+ * *crit reflects the cause: >= 0, extension found but not decoded (reflects
+ * critical value). -1 extension not found. -2 extension occurs more than
+ * once.
*/
-void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
+void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
+ int *idx)
{
- int lastpos;
- size_t i;
- X509_EXTENSION *ex, *found_ex = NULL;
- if(!x) {
- if(idx) *idx = -1;
- if(crit) *crit = -1;
- return NULL;
- }
- if(idx) lastpos = *idx + 1;
- else lastpos = 0;
- if(lastpos < 0) lastpos = 0;
- for(i = lastpos; i < sk_X509_EXTENSION_num(x); i++)
- {
- ex = sk_X509_EXTENSION_value(x, i);
- if(OBJ_obj2nid(ex->object) == nid) {
- if(idx) {
- *idx = i;
- found_ex = ex;
- break;
- } else if(found_ex) {
- /* Found more than one */
- if(crit) *crit = -2;
- return NULL;
- }
- found_ex = ex;
- }
- }
- if(found_ex) {
- /* Found it */
- if(crit) *crit = X509_EXTENSION_get_critical(found_ex);
- return X509V3_EXT_d2i(found_ex);
- }
-
- /* Extension not found */
- if(idx) *idx = -1;
- if(crit) *crit = -1;
- return NULL;
+ int lastpos;
+ size_t i;
+ X509_EXTENSION *ex, *found_ex = NULL;
+ if (!x) {
+ if (idx)
+ *idx = -1;
+ if (crit)
+ *crit = -1;
+ return NULL;
+ }
+ if (idx)
+ lastpos = *idx + 1;
+ else
+ lastpos = 0;
+ if (lastpos < 0)
+ lastpos = 0;
+ for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
+ ex = sk_X509_EXTENSION_value(x, i);
+ if (OBJ_obj2nid(ex->object) == nid) {
+ if (idx) {
+ *idx = i;
+ found_ex = ex;
+ break;
+ } else if (found_ex) {
+ /* Found more than one */
+ if (crit)
+ *crit = -2;
+ return NULL;
+ }
+ found_ex = ex;
+ }
+ }
+ if (found_ex) {
+ /* Found it */
+ if (crit)
+ *crit = X509_EXTENSION_get_critical(found_ex);
+ return X509V3_EXT_d2i(found_ex);
+ }
+
+ /* Extension not found */
+ if (idx)
+ *idx = -1;
+ if (crit)
+ *crit = -1;
+ return NULL;
}
-/* This function is a general extension append, replace and delete utility.
+/*
+ * This function is a general extension append, replace and delete utility.
* The precise operation is governed by the 'flags' value. The 'crit' and
* 'value' arguments (if relevant) are the extensions internal structure.
*/
int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
- int crit, unsigned long flags)
+ int crit, unsigned long flags)
{
- int extidx = -1;
- int errcode;
- X509_EXTENSION *ext, *extmp;
- unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
-
- /* If appending we don't care if it exists, otherwise
- * look for existing extension.
- */
- if(ext_op != X509V3_ADD_APPEND)
- extidx = X509v3_get_ext_by_NID(*x, nid, -1);
-
- /* See if extension exists */
- if(extidx >= 0) {
- /* If keep existing, nothing to do */
- if(ext_op == X509V3_ADD_KEEP_EXISTING)
- return 1;
- /* If default then its an error */
- if(ext_op == X509V3_ADD_DEFAULT) {
- errcode = X509V3_R_EXTENSION_EXISTS;
- goto err;
- }
- /* If delete, just delete it */
- if(ext_op == X509V3_ADD_DELETE) {
- if(!sk_X509_EXTENSION_delete(*x, extidx)) return -1;
- return 1;
- }
- } else {
- /* If replace existing or delete, error since
- * extension must exist
- */
- if((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
- (ext_op == X509V3_ADD_DELETE)) {
- errcode = X509V3_R_EXTENSION_NOT_FOUND;
- goto err;
- }
- }
-
- /* If we get this far then we have to create an extension:
- * could have some flags for alternative encoding schemes...
- */
-
- ext = X509V3_EXT_i2d(nid, crit, value);
-
- if(!ext) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
- return 0;
- }
-
- /* If extension exists replace it.. */
- if(extidx >= 0) {
- extmp = sk_X509_EXTENSION_value(*x, extidx);
- X509_EXTENSION_free(extmp);
- if(!sk_X509_EXTENSION_set(*x, extidx, ext)) return -1;
- return 1;
- }
-
- if(!*x && !(*x = sk_X509_EXTENSION_new_null())) return -1;
- if(!sk_X509_EXTENSION_push(*x, ext)) return -1;
-
- return 1;
-
- err:
- if(!(flags & X509V3_ADD_SILENT))
- OPENSSL_PUT_ERROR(X509V3, errcode);
- return 0;
+ int extidx = -1;
+ int errcode;
+ X509_EXTENSION *ext, *extmp;
+ unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
+
+ /*
+ * If appending we don't care if it exists, otherwise look for existing
+ * extension.
+ */
+ if (ext_op != X509V3_ADD_APPEND)
+ extidx = X509v3_get_ext_by_NID(*x, nid, -1);
+
+ /* See if extension exists */
+ if (extidx >= 0) {
+ /* If keep existing, nothing to do */
+ if (ext_op == X509V3_ADD_KEEP_EXISTING)
+ return 1;
+ /* If default then its an error */
+ if (ext_op == X509V3_ADD_DEFAULT) {
+ errcode = X509V3_R_EXTENSION_EXISTS;
+ goto err;
+ }
+ /* If delete, just delete it */
+ if (ext_op == X509V3_ADD_DELETE) {
+ if (!sk_X509_EXTENSION_delete(*x, extidx))
+ return -1;
+ return 1;
+ }
+ } else {
+ /*
+ * If replace existing or delete, error since extension must exist
+ */
+ if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
+ (ext_op == X509V3_ADD_DELETE)) {
+ errcode = X509V3_R_EXTENSION_NOT_FOUND;
+ goto err;
+ }
+ }
+
+ /*
+ * If we get this far then we have to create an extension: could have
+ * some flags for alternative encoding schemes...
+ */
+
+ ext = X509V3_EXT_i2d(nid, crit, value);
+
+ if (!ext) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
+ return 0;
+ }
+
+ /* If extension exists replace it.. */
+ if (extidx >= 0) {
+ extmp = sk_X509_EXTENSION_value(*x, extidx);
+ X509_EXTENSION_free(extmp);
+ if (!sk_X509_EXTENSION_set(*x, extidx, ext))
+ return -1;
+ return 1;
+ }
+
+ if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
+ return -1;
+ if (!sk_X509_EXTENSION_push(*x, ext))
+ return -1;
+
+ return 1;
+
+ err:
+ if (!(flags & X509V3_ADD_SILENT))
+ OPENSSL_PUT_ERROR(X509V3, errcode);
+ return 0;
}
diff --git a/src/crypto/x509v3/v3_ncons.c b/src/crypto/x509v3/v3_ncons.c
index 19f5e949..368ad272 100644
--- a/src/crypto/x509v3/v3_ncons.c
+++ b/src/crypto/x509v3/v3_ncons.c
@@ -1,5 +1,6 @@
/* v3_ncons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <string.h>
@@ -65,14 +65,14 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- void *a, BIO *bp, int ind);
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+ BIO *bp, int ind);
static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
- STACK_OF(GENERAL_SUBTREE) *trees,
- BIO *bp, int ind, const char *name);
+ STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
+ int ind, const char *name);
static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
@@ -83,428 +83,400 @@ static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
const X509V3_EXT_METHOD v3_name_constraints = {
- NID_name_constraints, 0,
- ASN1_ITEM_ref(NAME_CONSTRAINTS),
- 0,0,0,0,
- 0,0,
- 0, v2i_NAME_CONSTRAINTS,
- i2r_NAME_CONSTRAINTS,0,
- NULL
+ NID_name_constraints, 0,
+ ASN1_ITEM_ref(NAME_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, v2i_NAME_CONSTRAINTS,
+ i2r_NAME_CONSTRAINTS, 0,
+ NULL
};
ASN1_SEQUENCE(GENERAL_SUBTREE) = {
- ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
- ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
- ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
+ ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
- ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
- GENERAL_SUBTREE, 0),
- ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
- GENERAL_SUBTREE, 1),
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
+ GENERAL_SUBTREE, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
+ GENERAL_SUBTREE, 1),
} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
-
+
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
- {
- size_t i;
- CONF_VALUE tval, *val;
- STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
- NAME_CONSTRAINTS *ncons = NULL;
- GENERAL_SUBTREE *sub = NULL;
- ncons = NAME_CONSTRAINTS_new();
- if (!ncons)
- goto memerr;
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
- {
- val = sk_CONF_VALUE_value(nval, i);
- if (!strncmp(val->name, "permitted", 9) && val->name[9])
- {
- ptree = &ncons->permittedSubtrees;
- tval.name = val->name + 10;
- }
- else if (!strncmp(val->name, "excluded", 8) && val->name[8])
- {
- ptree = &ncons->excludedSubtrees;
- tval.name = val->name + 9;
- }
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
- goto err;
- }
- tval.value = val->value;
- sub = GENERAL_SUBTREE_new();
- if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
- goto err;
- if (!*ptree)
- *ptree = sk_GENERAL_SUBTREE_new_null();
- if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
- goto memerr;
- sub = NULL;
- }
-
- return ncons;
-
- memerr:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- err:
- if (ncons)
- NAME_CONSTRAINTS_free(ncons);
- if (sub)
- GENERAL_SUBTREE_free(sub);
-
- return NULL;
- }
-
-
-
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ size_t i;
+ CONF_VALUE tval, *val;
+ STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
+ NAME_CONSTRAINTS *ncons = NULL;
+ GENERAL_SUBTREE *sub = NULL;
+ ncons = NAME_CONSTRAINTS_new();
+ if (!ncons)
+ goto memerr;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (!strncmp(val->name, "permitted", 9) && val->name[9]) {
+ ptree = &ncons->permittedSubtrees;
+ tval.name = val->name + 10;
+ } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) {
+ ptree = &ncons->excludedSubtrees;
+ tval.name = val->name + 9;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
+ goto err;
+ }
+ tval.value = val->value;
+ sub = GENERAL_SUBTREE_new();
+ if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
+ goto err;
+ if (!*ptree)
+ *ptree = sk_GENERAL_SUBTREE_new_null();
+ if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
+ goto memerr;
+ sub = NULL;
+ }
+
+ return ncons;
+
+ memerr:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ if (ncons)
+ NAME_CONSTRAINTS_free(ncons);
+ if (sub)
+ GENERAL_SUBTREE_free(sub);
+
+ return NULL;
+}
static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
- BIO *bp, int ind)
- {
- NAME_CONSTRAINTS *ncons = a;
- do_i2r_name_constraints(method, ncons->permittedSubtrees,
- bp, ind, "Permitted");
- do_i2r_name_constraints(method, ncons->excludedSubtrees,
- bp, ind, "Excluded");
- return 1;
- }
+ BIO *bp, int ind)
+{
+ NAME_CONSTRAINTS *ncons = a;
+ do_i2r_name_constraints(method, ncons->permittedSubtrees,
+ bp, ind, "Permitted");
+ do_i2r_name_constraints(method, ncons->excludedSubtrees,
+ bp, ind, "Excluded");
+ return 1;
+}
static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
- STACK_OF(GENERAL_SUBTREE) *trees,
- BIO *bp, int ind, const char *name)
- {
- GENERAL_SUBTREE *tree;
- size_t i;
- if (sk_GENERAL_SUBTREE_num(trees) > 0)
- BIO_printf(bp, "%*s%s:\n", ind, "", name);
- for(i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++)
- {
- tree = sk_GENERAL_SUBTREE_value(trees, i);
- BIO_printf(bp, "%*s", ind + 2, "");
- if (tree->base->type == GEN_IPADD)
- print_nc_ipadd(bp, tree->base->d.ip);
- else
- GENERAL_NAME_print(bp, tree->base);
- BIO_puts(bp, "\n");
- }
- return 1;
- }
+ STACK_OF(GENERAL_SUBTREE) *trees,
+ BIO *bp, int ind, const char *name)
+{
+ GENERAL_SUBTREE *tree;
+ size_t i;
+ if (sk_GENERAL_SUBTREE_num(trees) > 0)
+ BIO_printf(bp, "%*s%s:\n", ind, "", name);
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
+ tree = sk_GENERAL_SUBTREE_value(trees, i);
+ BIO_printf(bp, "%*s", ind + 2, "");
+ if (tree->base->type == GEN_IPADD)
+ print_nc_ipadd(bp, tree->base->d.ip);
+ else
+ GENERAL_NAME_print(bp, tree->base);
+ BIO_puts(bp, "\n");
+ }
+ return 1;
+}
static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
- {
- int i, len;
- unsigned char *p;
- p = ip->data;
- len = ip->length;
- BIO_puts(bp, "IP:");
- if(len == 8)
- {
- BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
- p[0], p[1], p[2], p[3],
- p[4], p[5], p[6], p[7]);
- }
- else if(len == 32)
- {
- for (i = 0; i < 16; i++)
- {
- BIO_printf(bp, "%X", p[0] << 8 | p[1]);
- p += 2;
- if (i == 7)
- BIO_puts(bp, "/");
- else if (i != 15)
- BIO_puts(bp, ":");
- }
- }
- else
- BIO_printf(bp, "IP Address:<invalid>");
- return 1;
- }
-
-/* Check a certificate conforms to a specified set of constraints.
- * Return values:
- * X509_V_OK: All constraints obeyed.
- * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
- * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
- * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
- * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
- * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax.
- * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name
-
+{
+ int i, len;
+ unsigned char *p;
+ p = ip->data;
+ len = ip->length;
+ BIO_puts(bp, "IP:");
+ if (len == 8) {
+ BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ } else if (len == 32) {
+ for (i = 0; i < 16; i++) {
+ BIO_printf(bp, "%X", p[0] << 8 | p[1]);
+ p += 2;
+ if (i == 7)
+ BIO_puts(bp, "/");
+ else if (i != 15)
+ BIO_puts(bp, ":");
+ }
+ } else
+ BIO_printf(bp, "IP Address:<invalid>");
+ return 1;
+}
+
+/*
+ * Check a certificate conforms to a specified set of constraints. Return
+ * values: X509_V_OK: All constraints obeyed.
+ * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
+ * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
+ * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint
+ * syntax. X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of
+ * name
+ *
*/
int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
- {
- int r, i;
- size_t j;
- X509_NAME *nm;
+{
+ int r, i;
+ size_t j;
+ X509_NAME *nm;
- nm = X509_get_subject_name(x);
+ nm = X509_get_subject_name(x);
- if (X509_NAME_entry_count(nm) > 0)
- {
- GENERAL_NAME gntmp;
- gntmp.type = GEN_DIRNAME;
- gntmp.d.directoryName = nm;
+ if (X509_NAME_entry_count(nm) > 0) {
+ GENERAL_NAME gntmp;
+ gntmp.type = GEN_DIRNAME;
+ gntmp.d.directoryName = nm;
- r = nc_match(&gntmp, nc);
+ r = nc_match(&gntmp, nc);
- if (r != X509_V_OK)
- return r;
+ if (r != X509_V_OK)
+ return r;
- gntmp.type = GEN_EMAIL;
+ gntmp.type = GEN_EMAIL;
+ /* Process any email address attributes in subject name */
- /* Process any email address attributes in subject name */
+ for (i = -1;;) {
+ X509_NAME_ENTRY *ne;
+ i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i);
+ if (i == -1)
+ break;
+ ne = X509_NAME_get_entry(nm, i);
+ gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
+ if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- for (i = -1;;)
- {
- X509_NAME_ENTRY *ne;
- i = X509_NAME_get_index_by_NID(nm,
- NID_pkcs9_emailAddress,
- i);
- if (i == -1)
- break;
- ne = X509_NAME_get_entry(nm, i);
- gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
- if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ r = nc_match(&gntmp, nc);
- r = nc_match(&gntmp, nc);
+ if (r != X509_V_OK)
+ return r;
+ }
- if (r != X509_V_OK)
- return r;
- }
-
- }
+ }
- for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++)
- {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
- r = nc_match(gen, nc);
- if (r != X509_V_OK)
- return r;
- }
+ for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
+ r = nc_match(gen, nc);
+ if (r != X509_V_OK)
+ return r;
+ }
- return X509_V_OK;
+ return X509_V_OK;
- }
+}
static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
- {
- GENERAL_SUBTREE *sub;
- int r, match = 0;
- size_t i;
-
- /* Permitted subtrees: if any subtrees exist of matching the type
- * at least one subtree must match.
- */
-
- for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++)
- {
- sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
- if (gen->type != sub->base->type)
- continue;
- if (sub->minimum || sub->maximum)
- return X509_V_ERR_SUBTREE_MINMAX;
- /* If we already have a match don't bother trying any more */
- if (match == 2)
- continue;
- if (match == 0)
- match = 1;
- r = nc_match_single(gen, sub->base);
- if (r == X509_V_OK)
- match = 2;
- else if (r != X509_V_ERR_PERMITTED_VIOLATION)
- return r;
- }
-
- if (match == 1)
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- /* Excluded subtrees: must not match any of these */
-
- for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++)
- {
- sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
- if (gen->type != sub->base->type)
- continue;
- if (sub->minimum || sub->maximum)
- return X509_V_ERR_SUBTREE_MINMAX;
-
- r = nc_match_single(gen, sub->base);
- if (r == X509_V_OK)
- return X509_V_ERR_EXCLUDED_VIOLATION;
- else if (r != X509_V_ERR_PERMITTED_VIOLATION)
- return r;
-
- }
-
- return X509_V_OK;
-
- }
+{
+ GENERAL_SUBTREE *sub;
+ int r, match = 0;
+ size_t i;
+
+ /*
+ * Permitted subtrees: if any subtrees exist of matching the type at
+ * least one subtree must match.
+ */
+
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
+ sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
+ if (gen->type != sub->base->type)
+ continue;
+ if (sub->minimum || sub->maximum)
+ return X509_V_ERR_SUBTREE_MINMAX;
+ /* If we already have a match don't bother trying any more */
+ if (match == 2)
+ continue;
+ if (match == 0)
+ match = 1;
+ r = nc_match_single(gen, sub->base);
+ if (r == X509_V_OK)
+ match = 2;
+ else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+ return r;
+ }
+
+ if (match == 1)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ /* Excluded subtrees: must not match any of these */
+
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
+ sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
+ if (gen->type != sub->base->type)
+ continue;
+ if (sub->minimum || sub->maximum)
+ return X509_V_ERR_SUBTREE_MINMAX;
+
+ r = nc_match_single(gen, sub->base);
+ if (r == X509_V_OK)
+ return X509_V_ERR_EXCLUDED_VIOLATION;
+ else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+ return r;
+
+ }
+
+ return X509_V_OK;
+
+}
static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
- {
- switch(base->type)
- {
- case GEN_DIRNAME:
- return nc_dn(gen->d.directoryName, base->d.directoryName);
+{
+ switch (base->type) {
+ case GEN_DIRNAME:
+ return nc_dn(gen->d.directoryName, base->d.directoryName);
- case GEN_DNS:
- return nc_dns(gen->d.dNSName, base->d.dNSName);
+ case GEN_DNS:
+ return nc_dns(gen->d.dNSName, base->d.dNSName);
- case GEN_EMAIL:
- return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
+ case GEN_EMAIL:
+ return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
- case GEN_URI:
- return nc_uri(gen->d.uniformResourceIdentifier,
- base->d.uniformResourceIdentifier);
+ case GEN_URI:
+ return nc_uri(gen->d.uniformResourceIdentifier,
+ base->d.uniformResourceIdentifier);
- default:
- return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
- }
+ default:
+ return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
+ }
- }
+}
-/* directoryName name constraint matching.
- * The canonical encoding of X509_NAME makes this comparison easy. It is
- * matched if the subtree is a subset of the name.
+/*
+ * directoryName name constraint matching. The canonical encoding of
+ * X509_NAME makes this comparison easy. It is matched if the subtree is a
+ * subset of the name.
*/
static int nc_dn(X509_NAME *nm, X509_NAME *base)
- {
- /* Ensure canonical encodings are up to date. */
- if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
- return X509_V_ERR_OUT_OF_MEM;
- if (base->modified && i2d_X509_NAME(base, NULL) < 0)
- return X509_V_ERR_OUT_OF_MEM;
- if (base->canon_enclen > nm->canon_enclen)
- return X509_V_ERR_PERMITTED_VIOLATION;
- if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
- return X509_V_ERR_PERMITTED_VIOLATION;
- return X509_V_OK;
- }
+{
+ /* Ensure canonical encodings are up to date. */
+ if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
+ return X509_V_ERR_OUT_OF_MEM;
+ if (base->modified && i2d_X509_NAME(base, NULL) < 0)
+ return X509_V_ERR_OUT_OF_MEM;
+ if (base->canon_enclen > nm->canon_enclen)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ return X509_V_OK;
+}
static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
- {
- char *baseptr = (char *)base->data;
- char *dnsptr = (char *)dns->data;
- /* Empty matches everything */
- if (!*baseptr)
- return X509_V_OK;
- /* Otherwise can add zero or more components on the left so
- * compare RHS and if dns is longer and expect '.' as preceding
- * character.
- */
- if (dns->length > base->length)
- {
- dnsptr += dns->length - base->length;
- if (*baseptr != '.' && dnsptr[-1] != '.')
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- if (OPENSSL_strcasecmp(baseptr, dnsptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
- }
+{
+ char *baseptr = (char *)base->data;
+ char *dnsptr = (char *)dns->data;
+ /* Empty matches everything */
+ if (!*baseptr)
+ return X509_V_OK;
+ /*
+ * Otherwise can add zero or more components on the left so compare RHS
+ * and if dns is longer and expect '.' as preceding character.
+ */
+ if (dns->length > base->length) {
+ dnsptr += dns->length - base->length;
+ if (*baseptr != '.' && dnsptr[-1] != '.')
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if (OPENSSL_strcasecmp(baseptr, dnsptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
- {
- const char *baseptr = (char *)base->data;
- const char *emlptr = (char *)eml->data;
-
- const char *baseat = strchr(baseptr, '@');
- const char *emlat = strchr(emlptr, '@');
- if (!emlat)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- /* Special case: inital '.' is RHS match */
- if (!baseat && (*baseptr == '.'))
- {
- if (eml->length > base->length)
- {
- emlptr += eml->length - base->length;
- if (!OPENSSL_strcasecmp(baseptr, emlptr))
- return X509_V_OK;
- }
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- /* If we have anything before '@' match local part */
-
- if (baseat)
- {
- if (baseat != baseptr)
- {
- if ((baseat - baseptr) != (emlat - emlptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
- /* Case sensitive match of local part */
- if (strncmp(baseptr, emlptr, emlat - emlptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
- /* Position base after '@' */
- baseptr = baseat + 1;
- }
- emlptr = emlat + 1;
- /* Just have hostname left to match: case insensitive */
- if (OPENSSL_strcasecmp(baseptr, emlptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
- }
+{
+ const char *baseptr = (char *)base->data;
+ const char *emlptr = (char *)eml->data;
+
+ const char *baseat = strchr(baseptr, '@');
+ const char *emlat = strchr(emlptr, '@');
+ if (!emlat)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ /* Special case: inital '.' is RHS match */
+ if (!baseat && (*baseptr == '.')) {
+ if (eml->length > base->length) {
+ emlptr += eml->length - base->length;
+ if (!OPENSSL_strcasecmp(baseptr, emlptr))
+ return X509_V_OK;
+ }
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ /* If we have anything before '@' match local part */
+
+ if (baseat) {
+ if (baseat != baseptr) {
+ if ((baseat - baseptr) != (emlat - emlptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ /* Case sensitive match of local part */
+ if (strncmp(baseptr, emlptr, emlat - emlptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+ /* Position base after '@' */
+ baseptr = baseat + 1;
+ }
+ emlptr = emlat + 1;
+ /* Just have hostname left to match: case insensitive */
+ if (OPENSSL_strcasecmp(baseptr, emlptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
- {
- const char *baseptr = (char *)base->data;
- const char *hostptr = (char *)uri->data;
- const char *p = strchr(hostptr, ':');
- int hostlen;
- /* Check for foo:// and skip past it */
- if (!p || (p[1] != '/') || (p[2] != '/'))
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- hostptr = p + 3;
-
- /* Determine length of hostname part of URI */
-
- /* Look for a port indicator as end of hostname first */
-
- p = strchr(hostptr, ':');
- /* Otherwise look for trailing slash */
- if (!p)
- p = strchr(hostptr, '/');
-
- if (!p)
- hostlen = strlen(hostptr);
- else
- hostlen = p - hostptr;
-
- if (hostlen == 0)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-
- /* Special case: inital '.' is RHS match */
- if (*baseptr == '.')
- {
- if (hostlen > base->length)
- {
- p = hostptr + hostlen - base->length;
- if (!OPENSSL_strncasecmp(p, baseptr, base->length))
- return X509_V_OK;
- }
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- if ((base->length != (int)hostlen) || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
- }
+{
+ const char *baseptr = (char *)base->data;
+ const char *hostptr = (char *)uri->data;
+ const char *p = strchr(hostptr, ':');
+ int hostlen;
+ /* Check for foo:// and skip past it */
+ if (!p || (p[1] != '/') || (p[2] != '/'))
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ hostptr = p + 3;
+
+ /* Determine length of hostname part of URI */
+
+ /* Look for a port indicator as end of hostname first */
+
+ p = strchr(hostptr, ':');
+ /* Otherwise look for trailing slash */
+ if (!p)
+ p = strchr(hostptr, '/');
+
+ if (!p)
+ hostlen = strlen(hostptr);
+ else
+ hostlen = p - hostptr;
+
+ if (hostlen == 0)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+
+ /* Special case: inital '.' is RHS match */
+ if (*baseptr == '.') {
+ if (hostlen > base->length) {
+ p = hostptr + hostlen - base->length;
+ if (!OPENSSL_strncasecmp(p, baseptr, base->length))
+ return X509_V_OK;
+ }
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if ((base->length != (int)hostlen)
+ || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
diff --git a/src/crypto/x509v3/v3_pci.c b/src/crypto/x509v3/v3_pci.c
index f19a37a8..220f65e1 100644
--- a/src/crypto/x509v3/v3_pci.c
+++ b/src/crypto/x509v3/v3_pci.c
@@ -1,6 +1,7 @@
/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
-/* Contributed to the OpenSSL Project 2004
- * by Richard Levitte (richard@levitte.org)
+/*
+ * Contributed to the OpenSSL Project 2004 by Richard Levitte
+ * (richard@levitte.org)
*/
/* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
@@ -43,293 +44,274 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
- BIO *out, int indent);
+ BIO *out, int indent);
static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str);
+ X509V3_CTX *ctx, char *str);
const X509V3_EXT_METHOD v3_pci =
- { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
- 0,0,0,0,
- 0,0,
- NULL, NULL,
- (X509V3_EXT_I2R)i2r_pci,
- (X509V3_EXT_R2I)r2i_pci,
- NULL,
- };
+ { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
+ 0, 0, 0, 0,
+ 0, 0,
+ NULL, NULL,
+ (X509V3_EXT_I2R)i2r_pci,
+ (X509V3_EXT_R2I)r2i_pci,
+ NULL,
+};
static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
- BIO *out, int indent)
- {
- BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
- if (pci->pcPathLengthConstraint)
- i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
- else
- BIO_printf(out, "infinite");
- BIO_puts(out, "\n");
- BIO_printf(out, "%*sPolicy Language: ", indent, "");
- i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
- BIO_puts(out, "\n");
- if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
- BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
- pci->proxyPolicy->policy->data);
- return 1;
- }
+ BIO *out, int indent)
+{
+ BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
+ if (pci->pcPathLengthConstraint)
+ i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
+ else
+ BIO_printf(out, "infinite");
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*sPolicy Language: ", indent, "");
+ i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
+ BIO_puts(out, "\n");
+ if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
+ BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
+ pci->proxyPolicy->policy->data);
+ return 1;
+}
static int process_pci_value(CONF_VALUE *val,
- ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
- ASN1_OCTET_STRING **policy)
- {
- int free_policy = 0;
+ ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
+ ASN1_OCTET_STRING **policy)
+{
+ int free_policy = 0;
- if (strcmp(val->name, "language") == 0)
- {
- if (*language)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
- X509V3_conf_err(val);
- return 0;
- }
- if (!(*language = OBJ_txt2obj(val->value, 0)))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return 0;
- }
- }
- else if (strcmp(val->name, "pathlen") == 0)
- {
- if (*pathlen)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
- X509V3_conf_err(val);
- return 0;
- }
- if (!X509V3_get_value_int(val, pathlen))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
- X509V3_conf_err(val);
- return 0;
- }
- }
- else if (strcmp(val->name, "policy") == 0)
- {
- unsigned char *tmp_data = NULL;
- long val_len;
- if (!*policy)
- {
- *policy = ASN1_OCTET_STRING_new();
- if (!*policy)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- return 0;
- }
- free_policy = 1;
- }
- if (strncmp(val->value, "hex:", 4) == 0)
- {
- unsigned char *tmp_data2 =
- string_to_hex(val->value + 4, &val_len);
+ if (strcmp(val->name, "language") == 0) {
+ if (*language) {
+ OPENSSL_PUT_ERROR(X509V3,
+ X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if (!(*language = OBJ_txt2obj(val->value, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ } else if (strcmp(val->name, "pathlen") == 0) {
+ if (*pathlen) {
+ OPENSSL_PUT_ERROR(X509V3,
+ X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if (!X509V3_get_value_int(val, pathlen)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ } else if (strcmp(val->name, "policy") == 0) {
+ unsigned char *tmp_data = NULL;
+ long val_len;
+ if (!*policy) {
+ *policy = ASN1_OCTET_STRING_new();
+ if (!*policy) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ free_policy = 1;
+ }
+ if (strncmp(val->value, "hex:", 4) == 0) {
+ unsigned char *tmp_data2 =
+ string_to_hex(val->value + 4, &val_len);
- if (!tmp_data2)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
- X509V3_conf_err(val);
- goto err;
- }
+ if (!tmp_data2) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
+ X509V3_conf_err(val);
+ goto err;
+ }
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + val_len + 1);
- if (tmp_data)
- {
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length],
- tmp_data2, val_len);
- (*policy)->length += val_len;
- (*policy)->data[(*policy)->length] = '\0';
- }
- else
- {
- OPENSSL_free(tmp_data2);
- /* realloc failure implies the original data space is b0rked too! */
- (*policy)->data = NULL;
- (*policy)->length = 0;
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- OPENSSL_free(tmp_data2);
- }
- else if (strncmp(val->value, "file:", 5) == 0)
- {
- unsigned char buf[2048];
- int n;
- BIO *b = BIO_new_file(val->value + 5, "r");
- if (!b)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
- X509V3_conf_err(val);
- goto err;
- }
- while((n = BIO_read(b, buf, sizeof(buf))) > 0
- || (n == 0 && BIO_should_retry(b)))
- {
- if (!n) continue;
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data) {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ tmp_data2, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ } else {
+ OPENSSL_free(tmp_data2);
+ /*
+ * realloc failure implies the original data space is b0rked
+ * too!
+ */
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ OPENSSL_free(tmp_data2);
+ } else if (strncmp(val->value, "file:", 5) == 0) {
+ unsigned char buf[2048];
+ int n;
+ BIO *b = BIO_new_file(val->value + 5, "r");
+ if (!b) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ while ((n = BIO_read(b, buf, sizeof(buf))) > 0
+ || (n == 0 && BIO_should_retry(b))) {
+ if (!n)
+ continue;
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + n + 1);
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + n + 1);
- if (!tmp_data)
- break;
+ if (!tmp_data)
+ break;
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length],
- buf, n);
- (*policy)->length += n;
- (*policy)->data[(*policy)->length] = '\0';
- }
- BIO_free_all(b);
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length], buf, n);
+ (*policy)->length += n;
+ (*policy)->data[(*policy)->length] = '\0';
+ }
+ BIO_free_all(b);
- if (n < 0)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
- X509V3_conf_err(val);
- goto err;
- }
- }
- else if (strncmp(val->value, "text:", 5) == 0)
- {
- val_len = strlen(val->value + 5);
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + val_len + 1);
- if (tmp_data)
- {
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length],
- val->value + 5, val_len);
- (*policy)->length += val_len;
- (*policy)->data[(*policy)->length] = '\0';
- }
- else
- {
- /* realloc failure implies the original data space is b0rked too! */
- (*policy)->data = NULL;
- (*policy)->length = 0;
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- }
- else
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
- X509V3_conf_err(val);
- goto err;
- }
- if (!tmp_data)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- }
- return 1;
-err:
- if (free_policy)
- {
- ASN1_OCTET_STRING_free(*policy);
- *policy = NULL;
- }
- return 0;
- }
+ if (n < 0) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ } else if (strncmp(val->value, "text:", 5) == 0) {
+ val_len = strlen(val->value + 5);
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data) {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ val->value + 5, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ } else {
+ /*
+ * realloc failure implies the original data space is b0rked
+ * too!
+ */
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (!tmp_data) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ return 1;
+ err:
+ if (free_policy) {
+ ASN1_OCTET_STRING_free(*policy);
+ *policy = NULL;
+ }
+ return 0;
+}
static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *value)
- {
- PROXY_CERT_INFO_EXTENSION *pci = NULL;
- STACK_OF(CONF_VALUE) *vals;
- ASN1_OBJECT *language = NULL;
- ASN1_INTEGER *pathlen = NULL;
- ASN1_OCTET_STRING *policy = NULL;
- size_t i, j;
- int nid;
+ X509V3_CTX *ctx, char *value)
+{
+ PROXY_CERT_INFO_EXTENSION *pci = NULL;
+ STACK_OF(CONF_VALUE) *vals;
+ ASN1_OBJECT *language = NULL;
+ ASN1_INTEGER *pathlen = NULL;
+ ASN1_OCTET_STRING *policy = NULL;
+ size_t i, j;
+ int nid;
- vals = X509V3_parse_list(value);
- for (i = 0; i < sk_CONF_VALUE_num(vals); i++)
- {
- CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
- if (!cnf->name || (*cnf->name != '@' && !cnf->value))
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
- X509V3_conf_err(cnf);
- goto err;
- }
- if (*cnf->name == '@')
- {
- STACK_OF(CONF_VALUE) *sect;
- int success_p = 1;
+ vals = X509V3_parse_list(value);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
+ if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ if (*cnf->name == '@') {
+ STACK_OF(CONF_VALUE) *sect;
+ int success_p = 1;
- sect = X509V3_get_section(ctx, cnf->name + 1);
- if (!sect)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
- X509V3_conf_err(cnf);
- goto err;
- }
- for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++)
- {
- success_p =
- process_pci_value(sk_CONF_VALUE_value(sect, j),
- &language, &pathlen, &policy);
- }
- X509V3_section_free(ctx, sect);
- if (!success_p)
- goto err;
- }
- else
- {
- if (!process_pci_value(cnf,
- &language, &pathlen, &policy))
- {
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- }
+ sect = X509V3_get_section(ctx, cnf->name + 1);
+ if (!sect) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
+ success_p =
+ process_pci_value(sk_CONF_VALUE_value(sect, j),
+ &language, &pathlen, &policy);
+ }
+ X509V3_section_free(ctx, sect);
+ if (!success_p)
+ goto err;
+ } else {
+ if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ }
- /* Language is mandatory */
- if (!language)
- {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
- goto err;
- }
- nid = OBJ_obj2nid(language);
- if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy)
- {
- OPENSSL_PUT_ERROR(X509V3,
- X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
- goto err;
- }
+ /* Language is mandatory */
+ if (!language) {
+ OPENSSL_PUT_ERROR(X509V3,
+ X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
+ goto err;
+ }
+ nid = OBJ_obj2nid(language);
+ if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) {
+ OPENSSL_PUT_ERROR(X509V3,
+ X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
+ goto err;
+ }
- pci = PROXY_CERT_INFO_EXTENSION_new();
- if (!pci)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ pci = PROXY_CERT_INFO_EXTENSION_new();
+ if (!pci) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- pci->proxyPolicy->policyLanguage = language; language = NULL;
- pci->proxyPolicy->policy = policy; policy = NULL;
- pci->pcPathLengthConstraint = pathlen; pathlen = NULL;
- goto end;
-err:
- if (language) { ASN1_OBJECT_free(language); language = NULL; }
- if (pathlen) { ASN1_INTEGER_free(pathlen); pathlen = NULL; }
- if (policy) { ASN1_OCTET_STRING_free(policy); policy = NULL; }
- if (pci) { PROXY_CERT_INFO_EXTENSION_free(pci); pci = NULL; }
-end:
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- return pci;
- }
+ pci->proxyPolicy->policyLanguage = language;
+ language = NULL;
+ pci->proxyPolicy->policy = policy;
+ policy = NULL;
+ pci->pcPathLengthConstraint = pathlen;
+ pathlen = NULL;
+ goto end;
+ err:
+ if (language) {
+ ASN1_OBJECT_free(language);
+ language = NULL;
+ }
+ if (pathlen) {
+ ASN1_INTEGER_free(pathlen);
+ pathlen = NULL;
+ }
+ if (policy) {
+ ASN1_OCTET_STRING_free(policy);
+ policy = NULL;
+ }
+ if (pci) {
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ pci = NULL;
+ }
+ end:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pci;
+}
diff --git a/src/crypto/x509v3/v3_pcia.c b/src/crypto/x509v3/v3_pcia.c
index e3e3192f..3f285f30 100644
--- a/src/crypto/x509v3/v3_pcia.c
+++ b/src/crypto/x509v3/v3_pcia.c
@@ -1,6 +1,7 @@
/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */
-/* Contributed to the OpenSSL Project 2004
- * by Richard Levitte (richard@levitte.org)
+/*
+ * Contributed to the OpenSSL Project 2004 by Richard Levitte
+ * (richard@levitte.org)
*/
/* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
@@ -40,17 +41,17 @@
ASN1_SEQUENCE(PROXY_POLICY) =
- {
- ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
- ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
+ {
+ ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
+ ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(PROXY_POLICY)
IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) =
- {
- ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
- ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
+ {
+ ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
+ ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
diff --git a/src/crypto/x509v3/v3_pcons.c b/src/crypto/x509v3/v3_pcons.c
index b7522904..1a463143 100644
--- a/src/crypto/x509v3/v3_pcons.c
+++ b/src/crypto/x509v3/v3_pcons.c
@@ -1,5 +1,6 @@
/* v3_pcons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <string.h>
@@ -65,78 +65,75 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *bcons,
- STACK_OF(CONF_VALUE) *extlist);
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+ *method, void *bcons, STACK_OF(CONF_VALUE)
+ *extlist);
static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values);
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
const X509V3_EXT_METHOD v3_policy_constraints = {
-NID_policy_constraints, 0,
-ASN1_ITEM_ref(POLICY_CONSTRAINTS),
-0,0,0,0,
-0,0,
-i2v_POLICY_CONSTRAINTS,
-v2i_POLICY_CONSTRAINTS,
-NULL,NULL,
-NULL
+ NID_policy_constraints, 0,
+ ASN1_ITEM_ref(POLICY_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_POLICY_CONSTRAINTS,
+ v2i_POLICY_CONSTRAINTS,
+ NULL, NULL,
+ NULL
};
ASN1_SEQUENCE(POLICY_CONSTRAINTS) = {
- ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
- ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
- STACK_OF(CONF_VALUE) *extlist)
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *extlist)
{
- POLICY_CONSTRAINTS *pcons = a;
- X509V3_add_value_int("Require Explicit Policy",
- pcons->requireExplicitPolicy, &extlist);
- X509V3_add_value_int("Inhibit Policy Mapping",
- pcons->inhibitPolicyMapping, &extlist);
- return extlist;
+ POLICY_CONSTRAINTS *pcons = a;
+ X509V3_add_value_int("Require Explicit Policy",
+ pcons->requireExplicitPolicy, &extlist);
+ X509V3_add_value_int("Inhibit Policy Mapping",
+ pcons->inhibitPolicyMapping, &extlist);
+ return extlist;
}
static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values)
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
{
- POLICY_CONSTRAINTS *pcons=NULL;
- CONF_VALUE *val;
- size_t i;
- if(!(pcons = POLICY_CONSTRAINTS_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
- val = sk_CONF_VALUE_value(values, i);
- if(!strcmp(val->name, "requireExplicitPolicy")) {
- if(!X509V3_get_value_int(val,
- &pcons->requireExplicitPolicy)) goto err;
- } else if(!strcmp(val->name, "inhibitPolicyMapping")) {
- if(!X509V3_get_value_int(val,
- &pcons->inhibitPolicyMapping)) goto err;
- } else {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
- X509V3_conf_err(val);
- goto err;
- }
- }
- if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
- goto err;
- }
+ POLICY_CONSTRAINTS *pcons = NULL;
+ CONF_VALUE *val;
+ size_t i;
+ if (!(pcons = POLICY_CONSTRAINTS_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if (!strcmp(val->name, "requireExplicitPolicy")) {
+ if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy))
+ goto err;
+ } else if (!strcmp(val->name, "inhibitPolicyMapping")) {
+ if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping))
+ goto err;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
+ goto err;
+ }
- return pcons;
- err:
- POLICY_CONSTRAINTS_free(pcons);
- return NULL;
+ return pcons;
+ err:
+ POLICY_CONSTRAINTS_free(pcons);
+ return NULL;
}
-
diff --git a/src/crypto/x509v3/v3_pku.c b/src/crypto/x509v3/v3_pku.c
index 445eda67..e4868b47 100644
--- a/src/crypto/x509v3/v3_pku.c
+++ b/src/crypto/x509v3/v3_pku.c
@@ -1,6 +1,7 @@
/* v3_pku.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,48 +63,48 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent);
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ PKEY_USAGE_PERIOD *usage, BIO *out,
+ int indent);
/*
-static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
-*/
+ * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ * X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+ */
const X509V3_EXT_METHOD v3_pkey_usage_period = {
-NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
-0,0,0,0,
-0,0,0,0,
-(X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
-NULL
+ NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
+ NULL
};
ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = {
- ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
- ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD)
IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
- PKEY_USAGE_PERIOD *usage, BIO *out, int indent)
+ PKEY_USAGE_PERIOD *usage, BIO *out,
+ int indent)
{
- BIO_printf(out, "%*s", indent, "");
- if(usage->notBefore) {
- BIO_write(out, "Not Before: ", 12);
- ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
- if(usage->notAfter) BIO_write(out, ", ", 2);
- }
- if(usage->notAfter) {
- BIO_write(out, "Not After: ", 11);
- ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
- }
- return 1;
+ BIO_printf(out, "%*s", indent, "");
+ if (usage->notBefore) {
+ BIO_write(out, "Not Before: ", 12);
+ ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
+ if (usage->notAfter)
+ BIO_write(out, ", ", 2);
+ }
+ if (usage->notAfter) {
+ BIO_write(out, "Not After: ", 11);
+ ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
+ }
+ return 1;
}
/*
-static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values)
-X509V3_EXT_METHOD *method;
-X509V3_CTX *ctx;
-STACK_OF(CONF_VALUE) *values;
-{
-return NULL;
-}
-*/
+ * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values)
+ * X509V3_EXT_METHOD *method; X509V3_CTX *ctx; STACK_OF(CONF_VALUE) *values;
+ * { return NULL; }
+ */
diff --git a/src/crypto/x509v3/v3_pmaps.c b/src/crypto/x509v3/v3_pmaps.c
index 5b909773..caacdb27 100644
--- a/src/crypto/x509v3/v3_pmaps.c
+++ b/src/crypto/x509v3/v3_pmaps.c
@@ -1,5 +1,6 @@
/* v3_pmaps.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <openssl/asn1t.h>
@@ -63,94 +63,92 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *pmps,
- STACK_OF(CONF_VALUE) *extlist);
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+ *method, void *pmps, STACK_OF(CONF_VALUE)
+ *extlist);
const X509V3_EXT_METHOD v3_policy_mappings = {
- NID_policy_mappings, 0,
- ASN1_ITEM_ref(POLICY_MAPPINGS),
- 0,0,0,0,
- 0,0,
- i2v_POLICY_MAPPINGS,
- v2i_POLICY_MAPPINGS,
- 0,0,
- NULL
+ NID_policy_mappings, 0,
+ ASN1_ITEM_ref(POLICY_MAPPINGS),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_POLICY_MAPPINGS,
+ v2i_POLICY_MAPPINGS,
+ 0, 0,
+ NULL
};
ASN1_SEQUENCE(POLICY_MAPPING) = {
- ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
- ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
+ ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
+ ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
} ASN1_SEQUENCE_END(POLICY_MAPPING)
-ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
- POLICY_MAPPING)
+ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
+ POLICY_MAPPING)
ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *a,
- STACK_OF(CONF_VALUE) *ext_list)
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *ext_list)
{
- POLICY_MAPPINGS *pmaps = a;
- POLICY_MAPPING *pmap;
- size_t i;
- char obj_tmp1[80];
- char obj_tmp2[80];
- for(i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
- pmap = sk_POLICY_MAPPING_value(pmaps, i);
- i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
- i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
- X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
- }
- return ext_list;
+ POLICY_MAPPINGS *pmaps = a;
+ POLICY_MAPPING *pmap;
+ size_t i;
+ char obj_tmp1[80];
+ char obj_tmp2[80];
+ for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
+ pmap = sk_POLICY_MAPPING_value(pmaps, i);
+ i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
+ i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
+ X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
+ }
+ return ext_list;
}
static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
{
- POLICY_MAPPINGS *pmaps;
- POLICY_MAPPING *pmap;
- ASN1_OBJECT *obj1, *obj2;
- CONF_VALUE *val;
- size_t i;
+ POLICY_MAPPINGS *pmaps;
+ POLICY_MAPPING *pmap;
+ ASN1_OBJECT *obj1, *obj2;
+ CONF_VALUE *val;
+ size_t i;
- if(!(pmaps = sk_POLICY_MAPPING_new_null())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if (!(pmaps = sk_POLICY_MAPPING_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if(!val->value || !val->name) {
- sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return NULL;
- }
- obj1 = OBJ_txt2obj(val->name, 0);
- obj2 = OBJ_txt2obj(val->value, 0);
- if(!obj1 || !obj2) {
- sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return NULL;
- }
- pmap = POLICY_MAPPING_new();
- if (!pmap) {
- sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- pmap->issuerDomainPolicy = obj1;
- pmap->subjectDomainPolicy = obj2;
- sk_POLICY_MAPPING_push(pmaps, pmap);
- }
- return pmaps;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (!val->value || !val->name) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ obj1 = OBJ_txt2obj(val->name, 0);
+ obj2 = OBJ_txt2obj(val->value, 0);
+ if (!obj1 || !obj2) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ pmap = POLICY_MAPPING_new();
+ if (!pmap) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ pmap->issuerDomainPolicy = obj1;
+ pmap->subjectDomainPolicy = obj2;
+ sk_POLICY_MAPPING_push(pmaps, pmap);
+ }
+ return pmaps;
}
diff --git a/src/crypto/x509v3/v3_prn.c b/src/crypto/x509v3/v3_prn.c
index 87aef4d4..5015efcc 100644
--- a/src/crypto/x509v3/v3_prn.c
+++ b/src/crypto/x509v3/v3_prn.c
@@ -1,6 +1,7 @@
/* v3_prn.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,145 +64,169 @@
#include <openssl/mem.h>
#include <openssl/x509v3.h>
-
/* Extension printing routines */
-static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported);
+static int unknown_ext_print(BIO *out, X509_EXTENSION *ext,
+ unsigned long flag, int indent, int supported);
/* Print out a name+value stack */
-void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml)
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml)
{
- size_t i;
- CONF_VALUE *nval;
- if(!val) return;
- if(!ml || !sk_CONF_VALUE_num(val)) {
- BIO_printf(out, "%*s", indent, "");
- if(!sk_CONF_VALUE_num(val)) BIO_puts(out, "<EMPTY>\n");
- }
- for(i = 0; i < sk_CONF_VALUE_num(val); i++) {
- if(ml) BIO_printf(out, "%*s", indent, "");
- else if(i > 0) BIO_printf(out, ", ");
- nval = sk_CONF_VALUE_value(val, i);
- if(!nval->name) BIO_puts(out, nval->value);
- else if(!nval->value) BIO_puts(out, nval->name);
- else BIO_printf(out, "%s:%s", nval->name, nval->value);
- if(ml) BIO_puts(out, "\n");
- }
+ size_t i;
+ CONF_VALUE *nval;
+ if (!val)
+ return;
+ if (!ml || !sk_CONF_VALUE_num(val)) {
+ BIO_printf(out, "%*s", indent, "");
+ if (!sk_CONF_VALUE_num(val))
+ BIO_puts(out, "<EMPTY>\n");
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
+ if (ml)
+ BIO_printf(out, "%*s", indent, "");
+ else if (i > 0)
+ BIO_printf(out, ", ");
+ nval = sk_CONF_VALUE_value(val, i);
+ if (!nval->name)
+ BIO_puts(out, nval->value);
+ else if (!nval->value)
+ BIO_puts(out, nval->name);
+ else
+ BIO_printf(out, "%s:%s", nval->name, nval->value);
+ if (ml)
+ BIO_puts(out, "\n");
+ }
}
/* Main routine: print out a general extension */
-int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent)
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
+ int indent)
{
- void *ext_str = NULL;
- char *value = NULL;
- const unsigned char *p;
- const X509V3_EXT_METHOD *method;
- STACK_OF(CONF_VALUE) *nval = NULL;
- int ok = 1;
-
- if(!(method = X509V3_EXT_get(ext)))
- return unknown_ext_print(out, ext, flag, indent, 0);
- p = ext->value->data;
- if(method->it) ext_str = ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
- else ext_str = method->d2i(NULL, &p, ext->value->length);
-
- if(!ext_str) return unknown_ext_print(out, ext, flag, indent, 1);
-
- if(method->i2s) {
- if(!(value = method->i2s(method, ext_str))) {
- ok = 0;
- goto err;
- }
- BIO_printf(out, "%*s%s", indent, "", value);
- } else if(method->i2v) {
- if(!(nval = method->i2v(method, ext_str, NULL))) {
- ok = 0;
- goto err;
- }
- X509V3_EXT_val_prn(out, nval, indent,
- method->ext_flags & X509V3_EXT_MULTILINE);
- } else if(method->i2r) {
- if(!method->i2r(method, ext_str, out, indent)) ok = 0;
- } else ok = 0;
-
- err:
- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
- if(value) OPENSSL_free(value);
- if(method->it) ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
- else method->ext_free(ext_str);
- return ok;
+ void *ext_str = NULL;
+ char *value = NULL;
+ const unsigned char *p;
+ const X509V3_EXT_METHOD *method;
+ STACK_OF(CONF_VALUE) *nval = NULL;
+ int ok = 1;
+
+ if (!(method = X509V3_EXT_get(ext)))
+ return unknown_ext_print(out, ext, flag, indent, 0);
+ p = ext->value->data;
+ if (method->it)
+ ext_str =
+ ASN1_item_d2i(NULL, &p, ext->value->length,
+ ASN1_ITEM_ptr(method->it));
+ else
+ ext_str = method->d2i(NULL, &p, ext->value->length);
+
+ if (!ext_str)
+ return unknown_ext_print(out, ext, flag, indent, 1);
+
+ if (method->i2s) {
+ if (!(value = method->i2s(method, ext_str))) {
+ ok = 0;
+ goto err;
+ }
+ BIO_printf(out, "%*s%s", indent, "", value);
+ } else if (method->i2v) {
+ if (!(nval = method->i2v(method, ext_str, NULL))) {
+ ok = 0;
+ goto err;
+ }
+ X509V3_EXT_val_prn(out, nval, indent,
+ method->ext_flags & X509V3_EXT_MULTILINE);
+ } else if (method->i2r) {
+ if (!method->i2r(method, ext_str, out, indent))
+ ok = 0;
+ } else
+ ok = 0;
+
+ err:
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+ if (value)
+ OPENSSL_free(value);
+ if (method->it)
+ ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
+ else
+ method->ext_free(ext_str);
+ return ok;
}
-int X509V3_extensions_print(BIO *bp, const char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent)
+int X509V3_extensions_print(BIO *bp, const char *title,
+ STACK_OF(X509_EXTENSION) *exts,
+ unsigned long flag, int indent)
{
- size_t i;
- int j;
-
- if(sk_X509_EXTENSION_num(exts) <= 0) return 1;
-
- if(title)
- {
- BIO_printf(bp,"%*s%s:\n",indent, "", title);
- indent += 4;
- }
-
- for (i=0; i<sk_X509_EXTENSION_num(exts); i++)
- {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ex;
- ex=sk_X509_EXTENSION_value(exts, i);
- if (indent && BIO_printf(bp,"%*s",indent, "") <= 0) return 0;
- obj=X509_EXTENSION_get_object(ex);
- i2a_ASN1_OBJECT(bp,obj);
- j=X509_EXTENSION_get_critical(ex);
- if (BIO_printf(bp,": %s\n",j?"critical":"") <= 0)
- return 0;
- if(!X509V3_EXT_print(bp, ex, flag, indent + 4))
- {
- BIO_printf(bp, "%*s", indent + 4, "");
- M_ASN1_OCTET_STRING_print(bp,ex->value);
- }
- if (BIO_write(bp,"\n",1) <= 0) return 0;
- }
- return 1;
+ size_t i;
+ int j;
+
+ if (sk_X509_EXTENSION_num(exts) <= 0)
+ return 1;
+
+ if (title) {
+ BIO_printf(bp, "%*s%s:\n", indent, "", title);
+ indent += 4;
+ }
+
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ex;
+ ex = sk_X509_EXTENSION_value(exts, i);
+ if (indent && BIO_printf(bp, "%*s", indent, "") <= 0)
+ return 0;
+ obj = X509_EXTENSION_get_object(ex);
+ i2a_ASN1_OBJECT(bp, obj);
+ j = X509_EXTENSION_get_critical(ex);
+ if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
+ return 0;
+ if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) {
+ BIO_printf(bp, "%*s", indent + 4, "");
+ M_ASN1_OCTET_STRING_print(bp, ex->value);
+ }
+ if (BIO_write(bp, "\n", 1) <= 0)
+ return 0;
+ }
+ return 1;
}
-static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported)
+static int unknown_ext_print(BIO *out, X509_EXTENSION *ext,
+ unsigned long flag, int indent, int supported)
{
- switch(flag & X509V3_EXT_UNKNOWN_MASK) {
-
- case X509V3_EXT_DEFAULT:
- return 0;
-
- case X509V3_EXT_ERROR_UNKNOWN:
- if(supported)
- BIO_printf(out, "%*s<Parse Error>", indent, "");
- else
- BIO_printf(out, "%*s<Not Supported>", indent, "");
- return 1;
-
- case X509V3_EXT_PARSE_UNKNOWN:
- return ASN1_parse_dump(out,
- ext->value->data, ext->value->length, indent, -1);
- case X509V3_EXT_DUMP_UNKNOWN:
- return BIO_hexdump(out, ext->value->data, ext->value->length, indent);
-
- default:
- return 1;
- }
+ switch (flag & X509V3_EXT_UNKNOWN_MASK) {
+
+ case X509V3_EXT_DEFAULT:
+ return 0;
+
+ case X509V3_EXT_ERROR_UNKNOWN:
+ if (supported)
+ BIO_printf(out, "%*s<Parse Error>", indent, "");
+ else
+ BIO_printf(out, "%*s<Not Supported>", indent, "");
+ return 1;
+
+ case X509V3_EXT_PARSE_UNKNOWN:
+ return ASN1_parse_dump(out,
+ ext->value->data, ext->value->length, indent,
+ -1);
+ case X509V3_EXT_DUMP_UNKNOWN:
+ return BIO_hexdump(out, ext->value->data, ext->value->length, indent);
+
+ default:
+ return 1;
+ }
}
-
#ifndef OPENSSL_NO_FP_API
int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent)
{
- BIO *bio_tmp;
- int ret;
- if(!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) return 0;
- ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
- BIO_free(bio_tmp);
- return ret;
+ BIO *bio_tmp;
+ int ret;
+ if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)))
+ return 0;
+ ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
+ BIO_free(bio_tmp);
+ return ret;
}
#endif
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
index 9a0a7bc4..85bc15b7 100644
--- a/src/crypto/x509v3/v3_purp.c
+++ b/src/crypto/x509v3/v3_purp.c
@@ -1,6 +1,7 @@
/* v3_purp.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
*/
/* ====================================================================
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -69,26 +70,32 @@
#include "../internal.h"
-
#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
#define ku_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
#define xku_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
+ (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
#define ns_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
+ (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
static void x509v3_cache_extensions(X509 *x);
static int check_ssl_ca(const X509 *x);
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
static int purpose_smime(const X509 *x, int ca);
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca);
static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
@@ -96,15 +103,29 @@ static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b);
static void xptable_free(X509_PURPOSE *p);
static X509_PURPOSE xstandard[] = {
- {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, (char *) "SSL client", (char *) "sslclient", NULL},
- {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, (char *) "SSL server", (char *) "sslserver", NULL},
- {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, (char *) "Netscape SSL server", (char *) "nssslserver", NULL},
- {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, (char *) "S/MIME signing", (char *) "smimesign", NULL},
- {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, (char *) "S/MIME encryption", (char *) "smimeencrypt", NULL},
- {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, (char *) "CRL signing", (char *) "crlsign", NULL},
- {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *) "Any Purpose", (char *) "any", NULL},
- {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, (char *) "OCSP helper", (char *) "ocsphelper", NULL},
- {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, (char *) "Time Stamp signing", (char *) "timestampsign", NULL},
+ {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
+ check_purpose_ssl_client, (char *)"SSL client", (char *)"sslclient",
+ NULL},
+ {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+ check_purpose_ssl_server, (char *)"SSL server", (char *)"sslserver",
+ NULL},
+ {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+ check_purpose_ns_ssl_server, (char *)"Netscape SSL server",
+ (char *)"nssslserver", NULL},
+ {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
+ (char *)"S/MIME signing", (char *)"smimesign", NULL},
+ {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
+ check_purpose_smime_encrypt, (char *)"S/MIME encryption",
+ (char *)"smimeencrypt", NULL},
+ {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
+ (char *)"CRL signing", (char *)"crlsign", NULL},
+ {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *)"Any Purpose",
+ (char *)"any", NULL},
+ {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper,
+ (char *)"OCSP helper", (char *)"ocsphelper", NULL},
+ {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
+ check_purpose_timestamp_sign, (char *)"Time Stamp signing",
+ (char *)"timestampsign", NULL},
};
#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
@@ -113,693 +134,741 @@ static STACK_OF(X509_PURPOSE) *xptable = NULL;
static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b)
{
- return (*a)->purpose - (*b)->purpose;
+ return (*a)->purpose - (*b)->purpose;
}
-/* As much as I'd like to make X509_check_purpose use a "const" X509*
- * I really can't because it does recalculate hashes and do other non-const
- * things. */
+/*
+ * As much as I'd like to make X509_check_purpose use a "const" X509* I
+ * really can't because it does recalculate hashes and do other non-const
+ * things.
+ */
int X509_check_purpose(X509 *x, int id, int ca)
{
- int idx;
- const X509_PURPOSE *pt;
- if(!(x->ex_flags & EXFLAG_SET)) {
- x509v3_cache_extensions(x);
- }
- if(id == -1) return 1;
- idx = X509_PURPOSE_get_by_id(id);
- if(idx == -1) return -1;
- pt = X509_PURPOSE_get0(idx);
- return pt->check_purpose(pt, x, ca);
+ int idx;
+ const X509_PURPOSE *pt;
+ if (!(x->ex_flags & EXFLAG_SET)) {
+ x509v3_cache_extensions(x);
+ }
+ if (id == -1)
+ return 1;
+ idx = X509_PURPOSE_get_by_id(id);
+ if (idx == -1)
+ return -1;
+ pt = X509_PURPOSE_get0(idx);
+ return pt->check_purpose(pt, x, ca);
}
int X509_PURPOSE_set(int *p, int purpose)
{
- if(X509_PURPOSE_get_by_id(purpose) == -1) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
- return 0;
- }
- *p = purpose;
- return 1;
+ if (X509_PURPOSE_get_by_id(purpose) == -1) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
+ return 0;
+ }
+ *p = purpose;
+ return 1;
}
int X509_PURPOSE_get_count(void)
{
- if(!xptable) return X509_PURPOSE_COUNT;
- return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
+ if (!xptable)
+ return X509_PURPOSE_COUNT;
+ return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
}
-X509_PURPOSE * X509_PURPOSE_get0(int idx)
+X509_PURPOSE *X509_PURPOSE_get0(int idx)
{
- if(idx < 0) return NULL;
- if(idx < (int)X509_PURPOSE_COUNT) return xstandard + idx;
- return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
+ if (idx < 0)
+ return NULL;
+ if (idx < (int)X509_PURPOSE_COUNT)
+ return xstandard + idx;
+ return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
}
int X509_PURPOSE_get_by_sname(char *sname)
{
- int i;
- X509_PURPOSE *xptmp;
- for(i = 0; i < X509_PURPOSE_get_count(); i++) {
- xptmp = X509_PURPOSE_get0(i);
- if(!strcmp(xptmp->sname, sname)) return i;
- }
- return -1;
+ int i;
+ X509_PURPOSE *xptmp;
+ for (i = 0; i < X509_PURPOSE_get_count(); i++) {
+ xptmp = X509_PURPOSE_get0(i);
+ if (!strcmp(xptmp->sname, sname))
+ return i;
+ }
+ return -1;
}
int X509_PURPOSE_get_by_id(int purpose)
{
- X509_PURPOSE tmp;
- size_t idx;
-
- if((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
- return purpose - X509_PURPOSE_MIN;
- tmp.purpose = purpose;
- if(!xptable) return -1;
-
- if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp))
- return -1;
- return idx + X509_PURPOSE_COUNT;
+ X509_PURPOSE tmp;
+ size_t idx;
+
+ if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
+ return purpose - X509_PURPOSE_MIN;
+ tmp.purpose = purpose;
+ if (!xptable)
+ return -1;
+
+ if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp))
+ return -1;
+ return idx + X509_PURPOSE_COUNT;
}
int X509_PURPOSE_add(int id, int trust, int flags,
- int (*ck)(const X509_PURPOSE *, const X509 *, int),
- char *name, char *sname, void *arg)
-{
- int idx;
- X509_PURPOSE *ptmp;
- char *name_dup, *sname_dup;
-
- /* This is set according to what we change: application can't set it */
- flags &= ~X509_PURPOSE_DYNAMIC;
- /* This will always be set for application modified trust entries */
- flags |= X509_PURPOSE_DYNAMIC_NAME;
- /* Get existing entry if any */
- idx = X509_PURPOSE_get_by_id(id);
- /* Need a new entry */
- if(idx == -1) {
- if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- ptmp->flags = X509_PURPOSE_DYNAMIC;
- } else ptmp = X509_PURPOSE_get0(idx);
-
- /* Duplicate the supplied names. */
- name_dup = BUF_strdup(name);
- sname_dup = BUF_strdup(sname);
- if (name_dup == NULL || sname_dup == NULL) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- if (name_dup != NULL)
- OPENSSL_free(name_dup);
- if (sname_dup != NULL)
- OPENSSL_free(sname_dup);
- if (idx == -1)
- OPENSSL_free(ptmp);
- return 0;
- }
-
- /* OPENSSL_free existing name if dynamic */
- if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
- OPENSSL_free(ptmp->name);
- OPENSSL_free(ptmp->sname);
- }
- /* dup supplied name */
- ptmp->name = name_dup;
- ptmp->sname = sname_dup;
- /* Keep the dynamic flag of existing entry */
- ptmp->flags &= X509_PURPOSE_DYNAMIC;
- /* Set all other flags */
- ptmp->flags |= flags;
-
- ptmp->purpose = id;
- ptmp->trust = trust;
- ptmp->check_purpose = ck;
- ptmp->usr_data = arg;
-
- /* If its a new entry manage the dynamic table */
- if(idx == -1) {
- if(!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- xptable_free(ptmp);
- return 0;
- }
- if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- xptable_free(ptmp);
- return 0;
- }
- }
- return 1;
+ int (*ck) (const X509_PURPOSE *, const X509 *, int),
+ char *name, char *sname, void *arg)
+{
+ int idx;
+ X509_PURPOSE *ptmp;
+ char *name_dup, *sname_dup;
+
+ /*
+ * This is set according to what we change: application can't set it
+ */
+ flags &= ~X509_PURPOSE_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_PURPOSE_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_PURPOSE_get_by_id(id);
+ /* Need a new entry */
+ if (idx == -1) {
+ if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ptmp->flags = X509_PURPOSE_DYNAMIC;
+ } else
+ ptmp = X509_PURPOSE_get0(idx);
+
+ /* Duplicate the supplied names. */
+ name_dup = BUF_strdup(name);
+ sname_dup = BUF_strdup(sname);
+ if (name_dup == NULL || sname_dup == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ if (name_dup != NULL)
+ OPENSSL_free(name_dup);
+ if (sname_dup != NULL)
+ OPENSSL_free(sname_dup);
+ if (idx == -1)
+ OPENSSL_free(ptmp);
+ return 0;
+ }
+
+ /* OPENSSL_free existing name if dynamic */
+ if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(ptmp->name);
+ OPENSSL_free(ptmp->sname);
+ }
+ /* dup supplied name */
+ ptmp->name = name_dup;
+ ptmp->sname = sname_dup;
+ /* Keep the dynamic flag of existing entry */
+ ptmp->flags &= X509_PURPOSE_DYNAMIC;
+ /* Set all other flags */
+ ptmp->flags |= flags;
+
+ ptmp->purpose = id;
+ ptmp->trust = trust;
+ ptmp->check_purpose = ck;
+ ptmp->usr_data = arg;
+
+ /* If its a new entry manage the dynamic table */
+ if (idx == -1) {
+ if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ xptable_free(ptmp);
+ return 0;
+ }
+ if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ xptable_free(ptmp);
+ return 0;
+ }
+ }
+ return 1;
}
static void xptable_free(X509_PURPOSE *p)
- {
- if(!p) return;
- if (p->flags & X509_PURPOSE_DYNAMIC)
- {
- if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
- OPENSSL_free(p->name);
- OPENSSL_free(p->sname);
- }
- OPENSSL_free(p);
- }
- }
+{
+ if (!p)
+ return;
+ if (p->flags & X509_PURPOSE_DYNAMIC) {
+ if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(p->name);
+ OPENSSL_free(p->sname);
+ }
+ OPENSSL_free(p);
+ }
+}
void X509_PURPOSE_cleanup(void)
{
- unsigned int i;
- sk_X509_PURPOSE_pop_free(xptable, xptable_free);
- for(i = 0; i < X509_PURPOSE_COUNT; i++) xptable_free(xstandard + i);
- xptable = NULL;
+ unsigned int i;
+ sk_X509_PURPOSE_pop_free(xptable, xptable_free);
+ for (i = 0; i < X509_PURPOSE_COUNT; i++)
+ xptable_free(xstandard + i);
+ xptable = NULL;
}
int X509_PURPOSE_get_id(X509_PURPOSE *xp)
{
- return xp->purpose;
+ return xp->purpose;
}
char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
{
- return xp->name;
+ return xp->name;
}
char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
{
- return xp->sname;
+ return xp->sname;
}
int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
{
- return xp->trust;
+ return xp->trust;
}
static int nid_cmp(const void *void_a, const void *void_b)
- {
- const int *a = void_a, *b = void_b;
+{
+ const int *a = void_a, *b = void_b;
- return *a - *b;
- }
+ return *a - *b;
+}
int X509_supported_extension(X509_EXTENSION *ex)
- {
- /* This table is a list of the NIDs of supported extensions:
- * that is those which are used by the verify process. If
- * an extension is critical and doesn't appear in this list
- * then the verify process will normally reject the certificate.
- * The list must be kept in numerical order because it will be
- * searched using bsearch.
- */
-
- static const int supported_nids[] = {
- NID_netscape_cert_type, /* 71 */
- NID_key_usage, /* 83 */
- NID_subject_alt_name, /* 85 */
- NID_basic_constraints, /* 87 */
- NID_certificate_policies, /* 89 */
- NID_ext_key_usage, /* 126 */
- NID_policy_constraints, /* 401 */
- NID_proxyCertInfo, /* 663 */
- NID_name_constraints, /* 666 */
- NID_policy_mappings, /* 747 */
- NID_inhibit_any_policy /* 748 */
- };
-
- int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
-
- if (ex_nid == NID_undef)
- return 0;
-
- if (bsearch(&ex_nid, supported_nids, sizeof(supported_nids)/sizeof(int), sizeof(int), nid_cmp) != NULL)
- return 1;
- return 0;
- }
+{
+ /*
+ * This table is a list of the NIDs of supported extensions: that is
+ * those which are used by the verify process. If an extension is
+ * critical and doesn't appear in this list then the verify process will
+ * normally reject the certificate. The list must be kept in numerical
+ * order because it will be searched using bsearch.
+ */
+
+ static const int supported_nids[] = {
+ NID_netscape_cert_type, /* 71 */
+ NID_key_usage, /* 83 */
+ NID_subject_alt_name, /* 85 */
+ NID_basic_constraints, /* 87 */
+ NID_certificate_policies, /* 89 */
+ NID_ext_key_usage, /* 126 */
+ NID_policy_constraints, /* 401 */
+ NID_proxyCertInfo, /* 663 */
+ NID_name_constraints, /* 666 */
+ NID_policy_mappings, /* 747 */
+ NID_inhibit_any_policy /* 748 */
+ };
+
+ int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+ if (ex_nid == NID_undef)
+ return 0;
+
+ if (bsearch
+ (&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int),
+ sizeof(int), nid_cmp) != NULL)
+ return 1;
+ return 0;
+}
static void setup_dp(X509 *x, DIST_POINT *dp)
- {
- X509_NAME *iname = NULL;
- size_t i;
- if (dp->reasons)
- {
- if (dp->reasons->length > 0)
- dp->dp_reasons = dp->reasons->data[0];
- if (dp->reasons->length > 1)
- dp->dp_reasons |= (dp->reasons->data[1] << 8);
- dp->dp_reasons &= CRLDP_ALL_REASONS;
- }
- else
- dp->dp_reasons = CRLDP_ALL_REASONS;
- if (!dp->distpoint || (dp->distpoint->type != 1))
- return;
- for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
- {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
- if (gen->type == GEN_DIRNAME)
- {
- iname = gen->d.directoryName;
- break;
- }
- }
- if (!iname)
- iname = X509_get_issuer_name(x);
-
- DIST_POINT_set_dpname(dp->distpoint, iname);
-
- }
+{
+ X509_NAME *iname = NULL;
+ size_t i;
+ if (dp->reasons) {
+ if (dp->reasons->length > 0)
+ dp->dp_reasons = dp->reasons->data[0];
+ if (dp->reasons->length > 1)
+ dp->dp_reasons |= (dp->reasons->data[1] << 8);
+ dp->dp_reasons &= CRLDP_ALL_REASONS;
+ } else
+ dp->dp_reasons = CRLDP_ALL_REASONS;
+ if (!dp->distpoint || (dp->distpoint->type != 1))
+ return;
+ for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+ if (gen->type == GEN_DIRNAME) {
+ iname = gen->d.directoryName;
+ break;
+ }
+ }
+ if (!iname)
+ iname = X509_get_issuer_name(x);
+
+ DIST_POINT_set_dpname(dp->distpoint, iname);
+
+}
static void setup_crldp(X509 *x)
- {
- size_t i;
- x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
- for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
- setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
- }
-
-/* g_x509_cache_extensions_lock is used to protect against concurrent calls to
- * |x509v3_cache_extensions|. Ideally this would be done with a |CRYPTO_once_t|
- * in the |X509| structure, but |CRYPTO_once_t| isn't public.
- *
+{
+ size_t i;
+ x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+ for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
+ setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+}
+
+/*
+ * g_x509_cache_extensions_lock is used to protect against concurrent calls
+ * to |x509v3_cache_extensions|. Ideally this would be done with a
+ * |CRYPTO_once_t| in the |X509| structure, but |CRYPTO_once_t| isn't public.
* Note: it's not entirely clear whether this lock is needed. Not all paths to
- * this function took a lock in OpenSSL. */
+ * this function took a lock in OpenSSL.
+ */
static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock =
CRYPTO_STATIC_MUTEX_INIT;
static void x509v3_cache_extensions(X509 *x)
{
- BASIC_CONSTRAINTS *bs;
- PROXY_CERT_INFO_EXTENSION *pci;
- ASN1_BIT_STRING *usage;
- ASN1_BIT_STRING *ns;
- EXTENDED_KEY_USAGE *extusage;
- X509_EXTENSION *ex;
- size_t i;
- int j;
-
- CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
-
- if(x->ex_flags & EXFLAG_SET)
- {
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
- return;
- }
-
- X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
- /* V1 should mean no extensions ... */
- if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
- /* Handle basic constraints */
- if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
- if(bs->ca) x->ex_flags |= EXFLAG_CA;
- if(bs->pathlen) {
- if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
- || !bs->ca) {
- x->ex_flags |= EXFLAG_INVALID;
- x->ex_pathlen = 0;
- } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
- } else x->ex_pathlen = -1;
- BASIC_CONSTRAINTS_free(bs);
- x->ex_flags |= EXFLAG_BCONS;
- }
- /* Handle proxy certificates */
- if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
- if (x->ex_flags & EXFLAG_CA
- || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
- || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- if (pci->pcPathLengthConstraint) {
- x->ex_pcpathlen =
- ASN1_INTEGER_get(pci->pcPathLengthConstraint);
- } else x->ex_pcpathlen = -1;
- PROXY_CERT_INFO_EXTENSION_free(pci);
- x->ex_flags |= EXFLAG_PROXY;
- }
- /* Handle key usage */
- if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
- if(usage->length > 0) {
- x->ex_kusage = usage->data[0];
- if(usage->length > 1)
- x->ex_kusage |= usage->data[1] << 8;
- } else x->ex_kusage = 0;
- x->ex_flags |= EXFLAG_KUSAGE;
- ASN1_BIT_STRING_free(usage);
- }
- x->ex_xkusage = 0;
- if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
- x->ex_flags |= EXFLAG_XKUSAGE;
- for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
- switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) {
- case NID_server_auth:
- x->ex_xkusage |= XKU_SSL_SERVER;
- break;
-
- case NID_client_auth:
- x->ex_xkusage |= XKU_SSL_CLIENT;
- break;
-
- case NID_email_protect:
- x->ex_xkusage |= XKU_SMIME;
- break;
-
- case NID_code_sign:
- x->ex_xkusage |= XKU_CODE_SIGN;
- break;
-
- case NID_ms_sgc:
- case NID_ns_sgc:
- x->ex_xkusage |= XKU_SGC;
- break;
-
- case NID_OCSP_sign:
- x->ex_xkusage |= XKU_OCSP_SIGN;
- break;
-
- case NID_time_stamp:
- x->ex_xkusage |= XKU_TIMESTAMP;
- break;
-
- case NID_dvcs:
- x->ex_xkusage |= XKU_DVCS;
- break;
-
- case NID_anyExtendedKeyUsage:
- x->ex_xkusage |= XKU_ANYEKU;
- break;
- }
- }
- sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
- }
-
- if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
- if(ns->length > 0) x->ex_nscert = ns->data[0];
- else x->ex_nscert = 0;
- x->ex_flags |= EXFLAG_NSCERT;
- ASN1_BIT_STRING_free(ns);
- }
- x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
- x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
- /* Does subject name match issuer ? */
- if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
- {
- x->ex_flags |= EXFLAG_SI;
- /* If SKID matches AKID also indicate self signed */
- if (X509_check_akid(x, x->akid) == X509_V_OK &&
- !ku_reject(x, KU_KEY_CERT_SIGN))
- x->ex_flags |= EXFLAG_SS;
- }
- x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
- x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
- if (!x->nc && (j != -1))
- x->ex_flags |= EXFLAG_INVALID;
- setup_crldp(x);
-
- for (j = 0; j < X509_get_ext_count(x); j++)
- {
- ex = X509_get_ext(x, j);
- if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
- == NID_freshest_crl)
- x->ex_flags |= EXFLAG_FRESHEST;
- if (!X509_EXTENSION_get_critical(ex))
- continue;
- if (!X509_supported_extension(ex))
- {
- x->ex_flags |= EXFLAG_CRITICAL;
- break;
- }
- }
- x->ex_flags |= EXFLAG_SET;
-
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
-}
-
-/* CA checks common to all purposes
- * return codes:
- * 0 not a CA
- * 1 is a CA
- * 2 basicConstraints absent so "maybe" a CA
- * 3 basicConstraints absent but self signed V1.
- * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
+ BASIC_CONSTRAINTS *bs;
+ PROXY_CERT_INFO_EXTENSION *pci;
+ ASN1_BIT_STRING *usage;
+ ASN1_BIT_STRING *ns;
+ EXTENDED_KEY_USAGE *extusage;
+ X509_EXTENSION *ex;
+ size_t i;
+ int j;
+
+ CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
+
+ if (x->ex_flags & EXFLAG_SET) {
+ CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+ return;
+ }
+
+ X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
+ /* V1 should mean no extensions ... */
+ if (!X509_get_version(x))
+ x->ex_flags |= EXFLAG_V1;
+ /* Handle basic constraints */
+ if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
+ if (bs->ca)
+ x->ex_flags |= EXFLAG_CA;
+ if (bs->pathlen) {
+ if ((bs->pathlen->type == V_ASN1_NEG_INTEGER)
+ || !bs->ca) {
+ x->ex_flags |= EXFLAG_INVALID;
+ x->ex_pathlen = 0;
+ } else
+ x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
+ } else
+ x->ex_pathlen = -1;
+ BASIC_CONSTRAINTS_free(bs);
+ x->ex_flags |= EXFLAG_BCONS;
+ }
+ /* Handle proxy certificates */
+ if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
+ if (x->ex_flags & EXFLAG_CA
+ || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
+ || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+ if (pci->pcPathLengthConstraint) {
+ x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
+ } else
+ x->ex_pcpathlen = -1;
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ x->ex_flags |= EXFLAG_PROXY;
+ }
+ /* Handle key usage */
+ if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
+ if (usage->length > 0) {
+ x->ex_kusage = usage->data[0];
+ if (usage->length > 1)
+ x->ex_kusage |= usage->data[1] << 8;
+ } else
+ x->ex_kusage = 0;
+ x->ex_flags |= EXFLAG_KUSAGE;
+ ASN1_BIT_STRING_free(usage);
+ }
+ x->ex_xkusage = 0;
+ if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
+ x->ex_flags |= EXFLAG_XKUSAGE;
+ for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
+ switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
+ case NID_server_auth:
+ x->ex_xkusage |= XKU_SSL_SERVER;
+ break;
+
+ case NID_client_auth:
+ x->ex_xkusage |= XKU_SSL_CLIENT;
+ break;
+
+ case NID_email_protect:
+ x->ex_xkusage |= XKU_SMIME;
+ break;
+
+ case NID_code_sign:
+ x->ex_xkusage |= XKU_CODE_SIGN;
+ break;
+
+ case NID_ms_sgc:
+ case NID_ns_sgc:
+ x->ex_xkusage |= XKU_SGC;
+ break;
+
+ case NID_OCSP_sign:
+ x->ex_xkusage |= XKU_OCSP_SIGN;
+ break;
+
+ case NID_time_stamp:
+ x->ex_xkusage |= XKU_TIMESTAMP;
+ break;
+
+ case NID_dvcs:
+ x->ex_xkusage |= XKU_DVCS;
+ break;
+
+ case NID_anyExtendedKeyUsage:
+ x->ex_xkusage |= XKU_ANYEKU;
+ break;
+ }
+ }
+ sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
+ }
+
+ if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
+ if (ns->length > 0)
+ x->ex_nscert = ns->data[0];
+ else
+ x->ex_nscert = 0;
+ x->ex_flags |= EXFLAG_NSCERT;
+ ASN1_BIT_STRING_free(ns);
+ }
+ x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
+ x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
+ /* Does subject name match issuer ? */
+ if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
+ x->ex_flags |= EXFLAG_SI;
+ /* If SKID matches AKID also indicate self signed */
+ if (X509_check_akid(x, x->akid) == X509_V_OK &&
+ !ku_reject(x, KU_KEY_CERT_SIGN))
+ x->ex_flags |= EXFLAG_SS;
+ }
+ x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
+ if (!x->nc && (j != -1))
+ x->ex_flags |= EXFLAG_INVALID;
+ setup_crldp(x);
+
+ for (j = 0; j < X509_get_ext_count(x); j++) {
+ ex = X509_get_ext(x, j);
+ if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
+ == NID_freshest_crl)
+ x->ex_flags |= EXFLAG_FRESHEST;
+ if (!X509_EXTENSION_get_critical(ex))
+ continue;
+ if (!X509_supported_extension(ex)) {
+ x->ex_flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
+ x->ex_flags |= EXFLAG_SET;
+
+ CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+}
+
+/*
+ * CA checks common to all purposes return codes: 0 not a CA 1 is a CA 2
+ * basicConstraints absent so "maybe" a CA 3 basicConstraints absent but self
+ * signed V1. 4 basicConstraints absent but keyUsage present and keyCertSign
+ * asserted.
*/
static int check_ca(const X509 *x)
{
- /* keyUsage if present should allow cert signing */
- if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0;
- if(x->ex_flags & EXFLAG_BCONS) {
- if(x->ex_flags & EXFLAG_CA) return 1;
- /* If basicConstraints says not a CA then say so */
- else return 0;
- } else {
- /* we support V1 roots for... uh, I don't really know why. */
- if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
- /* If key usage present it must have certSign so tolerate it */
- else if (x->ex_flags & EXFLAG_KUSAGE) return 4;
- /* Older certificates could have Netscape-specific CA types */
- else if (x->ex_flags & EXFLAG_NSCERT
- && x->ex_nscert & NS_ANY_CA) return 5;
- /* can this still be regarded a CA certificate? I doubt it */
- return 0;
- }
+ /* keyUsage if present should allow cert signing */
+ if (ku_reject(x, KU_KEY_CERT_SIGN))
+ return 0;
+ if (x->ex_flags & EXFLAG_BCONS) {
+ if (x->ex_flags & EXFLAG_CA)
+ return 1;
+ /* If basicConstraints says not a CA then say so */
+ else
+ return 0;
+ } else {
+ /* we support V1 roots for... uh, I don't really know why. */
+ if ((x->ex_flags & V1_ROOT) == V1_ROOT)
+ return 3;
+ /*
+ * If key usage present it must have certSign so tolerate it
+ */
+ else if (x->ex_flags & EXFLAG_KUSAGE)
+ return 4;
+ /* Older certificates could have Netscape-specific CA types */
+ else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
+ return 5;
+ /* can this still be regarded a CA certificate? I doubt it */
+ return 0;
+ }
}
int X509_check_ca(X509 *x)
{
- if(!(x->ex_flags & EXFLAG_SET)) {
- x509v3_cache_extensions(x);
- }
+ if (!(x->ex_flags & EXFLAG_SET)) {
+ x509v3_cache_extensions(x);
+ }
- return check_ca(x);
+ return check_ca(x);
}
/* Check SSL CA: common checks for SSL client and server */
static int check_ssl_ca(const X509 *x)
{
- int ca_ret;
- ca_ret = check_ca(x);
- if(!ca_ret) return 0;
- /* check nsCertType if present */
- if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
- else return 0;
+ int ca_ret;
+ ca_ret = check_ca(x);
+ if (!ca_ret)
+ return 0;
+ /* check nsCertType if present */
+ if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA)
+ return ca_ret;
+ else
+ return 0;
}
-
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- if(xku_reject(x,XKU_SSL_CLIENT)) return 0;
- if(ca) return check_ssl_ca(x);
- /* We need to do digital signatures or key agreement */
- if(ku_reject(x,KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) return 0;
- /* nsCertType if present should allow SSL client use */
- if(ns_reject(x, NS_SSL_CLIENT)) return 0;
- return 1;
+ if (xku_reject(x, XKU_SSL_CLIENT))
+ return 0;
+ if (ca)
+ return check_ssl_ca(x);
+ /* We need to do digital signatures or key agreement */
+ if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))
+ return 0;
+ /* nsCertType if present should allow SSL client use */
+ if (ns_reject(x, NS_SSL_CLIENT))
+ return 0;
+ return 1;
}
-/* Key usage needed for TLS/SSL server: digital signature, encipherment or
+
+/*
+ * Key usage needed for TLS/SSL server: digital signature, encipherment or
* key agreement. The ssl code can check this more thoroughly for individual
* key types.
*/
#define KU_TLS \
- KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
+ KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0;
- if(ca) return check_ssl_ca(x);
+ if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
+ return 0;
+ if (ca)
+ return check_ssl_ca(x);
- if(ns_reject(x, NS_SSL_SERVER)) return 0;
- if(ku_reject(x, KU_TLS)) return 0;
-
- return 1;
+ if (ns_reject(x, NS_SSL_SERVER))
+ return 0;
+ if (ku_reject(x, KU_TLS))
+ return 0;
+
+ return 1;
}
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- int ret;
- ret = check_purpose_ssl_server(xp, x, ca);
- if(!ret || ca) return ret;
- /* We need to encipher or Netscape complains */
- if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
- return ret;
+ int ret;
+ ret = check_purpose_ssl_server(xp, x, ca);
+ if (!ret || ca)
+ return ret;
+ /* We need to encipher or Netscape complains */
+ if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+ return 0;
+ return ret;
}
/* common S/MIME checks */
static int purpose_smime(const X509 *x, int ca)
{
- if(xku_reject(x,XKU_SMIME)) return 0;
- if(ca) {
- int ca_ret;
- ca_ret = check_ca(x);
- if(!ca_ret) return 0;
- /* check nsCertType if present */
- if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
- else return 0;
- }
- if(x->ex_flags & EXFLAG_NSCERT) {
- if(x->ex_nscert & NS_SMIME) return 1;
- /* Workaround for some buggy certificates */
- if(x->ex_nscert & NS_SSL_CLIENT) return 2;
- return 0;
- }
- return 1;
+ if (xku_reject(x, XKU_SMIME))
+ return 0;
+ if (ca) {
+ int ca_ret;
+ ca_ret = check_ca(x);
+ if (!ca_ret)
+ return 0;
+ /* check nsCertType if present */
+ if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
+ return ca_ret;
+ else
+ return 0;
+ }
+ if (x->ex_flags & EXFLAG_NSCERT) {
+ if (x->ex_nscert & NS_SMIME)
+ return 1;
+ /* Workaround for some buggy certificates */
+ if (x->ex_nscert & NS_SSL_CLIENT)
+ return 2;
+ return 0;
+ }
+ return 1;
}
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- int ret;
- ret = purpose_smime(x, ca);
- if(!ret || ca) return ret;
- if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0;
- return ret;
+ int ret;
+ ret = purpose_smime(x, ca);
+ if (!ret || ca)
+ return ret;
+ if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
+ return 0;
+ return ret;
}
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- int ret;
- ret = purpose_smime(x, ca);
- if(!ret || ca) return ret;
- if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
- return ret;
+ int ret;
+ ret = purpose_smime(x, ca);
+ if (!ret || ca)
+ return ret;
+ if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+ return 0;
+ return ret;
}
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
{
- if(ca) {
- int ca_ret;
- if((ca_ret = check_ca(x)) != 2) return ca_ret;
- else return 0;
- }
- if(ku_reject(x, KU_CRL_SIGN)) return 0;
- return 1;
+ if (ca) {
+ int ca_ret;
+ if ((ca_ret = check_ca(x)) != 2)
+ return ca_ret;
+ else
+ return 0;
+ }
+ if (ku_reject(x, KU_CRL_SIGN))
+ return 0;
+ return 1;
}
-/* OCSP helper: this is *not* a full OCSP check. It just checks that
- * each CA is valid. Additional checks must be made on the chain.
+/*
+ * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
+ * is valid. Additional checks must be made on the chain.
*/
static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
{
- /* Must be a valid CA. Should we really support the "I don't know"
- value (2)? */
- if(ca) return check_ca(x);
- /* leaf certificate is checked in OCSP_verify() */
- return 1;
+ /*
+ * Must be a valid CA. Should we really support the "I don't know" value
+ * (2)?
+ */
+ if (ca)
+ return check_ca(x);
+ /* leaf certificate is checked in OCSP_verify() */
+ return 1;
}
static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int ca)
{
- int i_ext;
-
- /* If ca is true we must return if this is a valid CA certificate. */
- if (ca) return check_ca(x);
-
- /*
- * Check the optional key usage field:
- * if Key Usage is present, it must be one of digitalSignature
- * and/or nonRepudiation (other values are not consistent and shall
- * be rejected).
- */
- if ((x->ex_flags & EXFLAG_KUSAGE)
- && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
- !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
- return 0;
-
- /* Only time stamp key usage is permitted and it's required. */
- if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
- return 0;
-
- /* Extended Key Usage MUST be critical */
- i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, -1);
- if (i_ext >= 0)
- {
- X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext);
- if (!X509_EXTENSION_get_critical(ext))
- return 0;
- }
-
- return 1;
+ int i_ext;
+
+ /* If ca is true we must return if this is a valid CA certificate. */
+ if (ca)
+ return check_ca(x);
+
+ /*
+ * Check the optional key usage field:
+ * if Key Usage is present, it must be one of digitalSignature
+ * and/or nonRepudiation (other values are not consistent and shall
+ * be rejected).
+ */
+ if ((x->ex_flags & EXFLAG_KUSAGE)
+ && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
+ !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
+ return 0;
+
+ /* Only time stamp key usage is permitted and it's required. */
+ if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
+ return 0;
+
+ /* Extended Key Usage MUST be critical */
+ i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1);
+ if (i_ext >= 0) {
+ X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
+ if (!X509_EXTENSION_get_critical(ext))
+ return 0;
+ }
+
+ return 1;
}
static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
{
- return 1;
+ return 1;
}
-/* Various checks to see if one certificate issued the second.
- * This can be used to prune a set of possible issuer certificates
- * which have been looked up using some simple method such as by
- * subject name.
- * These are:
- * 1. Check issuer_name(subject) == subject_name(issuer)
- * 2. If akid(subject) exists check it matches issuer
- * 3. If key_usage(issuer) exists check it supports certificate signing
- * returns 0 for OK, positive for reason for mismatch, reasons match
- * codes for X509_verify_cert()
+/*
+ * Various checks to see if one certificate issued the second. This can be
+ * used to prune a set of possible issuer certificates which have been looked
+ * up using some simple method such as by subject name. These are: 1. Check
+ * issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists
+ * check it matches issuer 3. If key_usage(issuer) exists check it supports
+ * certificate signing returns 0 for OK, positive for reason for mismatch,
+ * reasons match codes for X509_verify_cert()
*/
int X509_check_issued(X509 *issuer, X509 *subject)
{
- if(X509_NAME_cmp(X509_get_subject_name(issuer),
- X509_get_issuer_name(subject)))
- return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
- x509v3_cache_extensions(issuer);
- x509v3_cache_extensions(subject);
-
- if(subject->akid)
- {
- int ret = X509_check_akid(issuer, subject->akid);
- if (ret != X509_V_OK)
- return ret;
- }
-
- if(subject->ex_flags & EXFLAG_PROXY)
- {
- if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
- return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
- }
- else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
- return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
- return X509_V_OK;
+ if (X509_NAME_cmp(X509_get_subject_name(issuer),
+ X509_get_issuer_name(subject)))
+ return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+ x509v3_cache_extensions(issuer);
+ x509v3_cache_extensions(subject);
+
+ if (subject->akid) {
+ int ret = X509_check_akid(issuer, subject->akid);
+ if (ret != X509_V_OK)
+ return ret;
+ }
+
+ if (subject->ex_flags & EXFLAG_PROXY) {
+ if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
+ return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
+ } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
+ return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
+ return X509_V_OK;
}
int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
- {
-
- if(!akid)
- return X509_V_OK;
-
- /* Check key ids (if present) */
- if(akid->keyid && issuer->skid &&
- ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) )
- return X509_V_ERR_AKID_SKID_MISMATCH;
- /* Check serial number */
- if(akid->serial &&
- ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
- return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
- /* Check issuer name */
- if(akid->issuer)
- {
- /* Ugh, for some peculiar reason AKID includes
- * SEQUENCE OF GeneralName. So look for a DirName.
- * There may be more than one but we only take any
- * notice of the first.
- */
- GENERAL_NAMES *gens;
- GENERAL_NAME *gen;
- X509_NAME *nm = NULL;
- size_t i;
- gens = akid->issuer;
- for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
- {
- gen = sk_GENERAL_NAME_value(gens, i);
- if(gen->type == GEN_DIRNAME)
- {
- nm = gen->d.dirn;
- break;
- }
- }
- if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
- return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
- }
- return X509_V_OK;
- }
+{
+ if (!akid)
+ return X509_V_OK;
+
+ /* Check key ids (if present) */
+ if (akid->keyid && issuer->skid &&
+ ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
+ return X509_V_ERR_AKID_SKID_MISMATCH;
+ /* Check serial number */
+ if (akid->serial &&
+ ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
+ return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+ /* Check issuer name */
+ if (akid->issuer) {
+ /*
+ * Ugh, for some peculiar reason AKID includes SEQUENCE OF
+ * GeneralName. So look for a DirName. There may be more than one but
+ * we only take any notice of the first.
+ */
+ GENERAL_NAMES *gens;
+ GENERAL_NAME *gen;
+ X509_NAME *nm = NULL;
+ size_t i;
+ gens = akid->issuer;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ if (gen->type == GEN_DIRNAME) {
+ nm = gen->d.dirn;
+ break;
+ }
+ }
+ if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
+ return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+ }
+ return X509_V_OK;
+}
diff --git a/src/crypto/x509v3/v3_skey.c b/src/crypto/x509v3/v3_skey.c
index e396f054..65f8287c 100644
--- a/src/crypto/x509v3/v3_skey.c
+++ b/src/crypto/x509v3/v3_skey.c
@@ -1,6 +1,7 @@
/* v3_skey.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -54,7 +55,6 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
-
#include <stdio.h>
#include <string.h>
@@ -63,86 +63,90 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_skey_id = {
-NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
-0,0,0,0,
-(X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
-(X509V3_EXT_S2I)s2i_skey_id,
-0,0,0,0,
-NULL};
-
-char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- ASN1_OCTET_STRING *oct)
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD v3_skey_id = {
+ NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
+ (X509V3_EXT_S2I)s2i_skey_id,
+ 0, 0, 0, 0,
+ NULL
+};
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct)
{
- return hex_to_string(oct->data, oct->length);
+ return hex_to_string(oct->data, oct->length);
}
ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str)
+ X509V3_CTX *ctx, char *str)
{
- ASN1_OCTET_STRING *oct;
- long length;
+ ASN1_OCTET_STRING *oct;
+ long length;
- if(!(oct = M_ASN1_OCTET_STRING_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if (!(oct = M_ASN1_OCTET_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
- if(!(oct->data = string_to_hex(str, &length))) {
- M_ASN1_OCTET_STRING_free(oct);
- return NULL;
- }
+ if (!(oct->data = string_to_hex(str, &length))) {
+ M_ASN1_OCTET_STRING_free(oct);
+ return NULL;
+ }
- oct->length = length;
+ oct->length = length;
- return oct;
+ return oct;
}
static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str)
+ X509V3_CTX *ctx, char *str)
{
- ASN1_OCTET_STRING *oct;
- ASN1_BIT_STRING *pk;
- unsigned char pkey_dig[EVP_MAX_MD_SIZE];
- unsigned int diglen;
-
- if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str);
-
- if(!(oct = M_ASN1_OCTET_STRING_new())) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if(ctx && (ctx->flags == CTX_TEST)) return oct;
-
- if(!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
- goto err;
- }
-
- if(ctx->subject_req)
- pk = ctx->subject_req->req_info->pubkey->public_key;
- else pk = ctx->subject_cert->cert_info->key->public_key;
-
- if(!pk) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
- goto err;
- }
-
- if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL))
- goto err;
-
- if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- return oct;
-
- err:
- M_ASN1_OCTET_STRING_free(oct);
- return NULL;
+ ASN1_OCTET_STRING *oct;
+ ASN1_BIT_STRING *pk;
+ unsigned char pkey_dig[EVP_MAX_MD_SIZE];
+ unsigned int diglen;
+
+ if (strcmp(str, "hash"))
+ return s2i_ASN1_OCTET_STRING(method, ctx, str);
+
+ if (!(oct = M_ASN1_OCTET_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (ctx && (ctx->flags == CTX_TEST))
+ return oct;
+
+ if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
+ goto err;
+ }
+
+ if (ctx->subject_req)
+ pk = ctx->subject_req->req_info->pubkey->public_key;
+ else
+ pk = ctx->subject_cert->cert_info->key->public_key;
+
+ if (!pk) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
+ goto err;
+ }
+
+ if (!EVP_Digest
+ (pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL))
+ goto err;
+
+ if (!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ return oct;
+
+ err:
+ M_ASN1_OCTET_STRING_free(oct);
+ return NULL;
}
diff --git a/src/crypto/x509v3/v3_sxnet.c b/src/crypto/x509v3/v3_sxnet.c
index 4dd5bfc1..51c5a676 100644
--- a/src/crypto/x509v3/v3_sxnet.c
+++ b/src/crypto/x509v3/v3_sxnet.c
@@ -1,6 +1,7 @@
/* v3_sxnet.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -67,200 +68,207 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
-
/* Support for Thawte strong extranet extension */
#define SXNET_TEST
-static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, int indent);
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
+ int indent);
#ifdef SXNET_TEST
-static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
#endif
const X509V3_EXT_METHOD v3_sxnet = {
-NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
-0,0,0,0,
-0,0,
-0,
+ NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
#ifdef SXNET_TEST
-(X509V3_EXT_V2I)sxnet_v2i,
+ (X509V3_EXT_V2I)sxnet_v2i,
#else
-0,
+ 0,
#endif
-(X509V3_EXT_I2R)sxnet_i2r,
-0,
-NULL
+ (X509V3_EXT_I2R)sxnet_i2r,
+ 0,
+ NULL
};
ASN1_SEQUENCE(SXNETID) = {
- ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
- ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
+ ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
+ ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(SXNETID)
IMPLEMENT_ASN1_FUNCTIONS(SXNETID)
ASN1_SEQUENCE(SXNET) = {
- ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
- ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
+ ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
+ ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
} ASN1_SEQUENCE_END(SXNET)
IMPLEMENT_ASN1_FUNCTIONS(SXNET)
static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
- int indent)
+ int indent)
{
- long v;
- char *tmp;
- SXNETID *id;
- size_t i;
- v = ASN1_INTEGER_get(sx->version);
- BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v);
- for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
- id = sk_SXNETID_value(sx->ids, i);
- tmp = i2s_ASN1_INTEGER(NULL, id->zone);
- BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
- OPENSSL_free(tmp);
- M_ASN1_OCTET_STRING_print(out, id->user);
- }
- return 1;
+ long v;
+ char *tmp;
+ SXNETID *id;
+ size_t i;
+ v = ASN1_INTEGER_get(sx->version);
+ BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v);
+ for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ tmp = i2s_ASN1_INTEGER(NULL, id->zone);
+ BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
+ OPENSSL_free(tmp);
+ M_ASN1_OCTET_STRING_print(out, id->user);
+ }
+ return 1;
}
#ifdef SXNET_TEST
-/* NBB: this is used for testing only. It should *not* be used for anything
+/*
+ * NBB: this is used for testing only. It should *not* be used for anything
* else because it will just take static IDs from the configuration file and
* they should really be separate values for each user.
*/
-
-static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
{
- CONF_VALUE *cnf;
- SXNET *sx = NULL;
- size_t i;
- for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if(!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
- return NULL;
- }
- return sx;
+ CONF_VALUE *cnf;
+ SXNET *sx = NULL;
+ size_t i;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
+ return NULL;
+ }
+ return sx;
}
-
-
+
#endif
/* Strong Extranet utility functions */
/* Add an id given the zone as an ASCII number */
-int SXNET_add_id_asc(SXNET **psx, char *zone, char *user,
- int userlen)
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen)
{
- ASN1_INTEGER *izone = NULL;
- if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
- return 0;
- }
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+ ASN1_INTEGER *izone = NULL;
+ if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
}
/* Add an id given the zone as an unsigned long */
int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user,
- int userlen)
+ int userlen)
{
- ASN1_INTEGER *izone = NULL;
- if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- M_ASN1_INTEGER_free(izone);
- return 0;
- }
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
-
+ ASN1_INTEGER *izone = NULL;
+ if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ M_ASN1_INTEGER_free(izone);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+
}
-/* Add an id given the zone as an ASN1_INTEGER.
- * Note this version uses the passed integer and doesn't make a copy so don't
- * free it up afterwards.
+/*
+ * Add an id given the zone as an ASN1_INTEGER. Note this version uses the
+ * passed integer and doesn't make a copy so don't free it up afterwards.
*/
int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user,
- int userlen)
+ int userlen)
{
- SXNET *sx = NULL;
- SXNETID *id = NULL;
- if(!psx || !zone || !user) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
- return 0;
- }
- if(userlen == -1) userlen = strlen(user);
- if(userlen > 64) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_USER_TOO_LONG);
- return 0;
- }
- if(!*psx) {
- if(!(sx = SXNET_new())) goto err;
- if(!ASN1_INTEGER_set(sx->version, 0)) goto err;
- *psx = sx;
- } else sx = *psx;
- if(SXNET_get_id_INTEGER(sx, zone)) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_DUPLICATE_ZONE_ID);
- return 0;
- }
+ SXNET *sx = NULL;
+ SXNETID *id = NULL;
+ if (!psx || !zone || !user) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return 0;
+ }
+ if (userlen == -1)
+ userlen = strlen(user);
+ if (userlen > 64) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_USER_TOO_LONG);
+ return 0;
+ }
+ if (!*psx) {
+ if (!(sx = SXNET_new()))
+ goto err;
+ if (!ASN1_INTEGER_set(sx->version, 0))
+ goto err;
+ *psx = sx;
+ } else
+ sx = *psx;
+ if (SXNET_get_id_INTEGER(sx, zone)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_DUPLICATE_ZONE_ID);
+ return 0;
+ }
+
+ if (!(id = SXNETID_new()))
+ goto err;
+ if (userlen == -1)
+ userlen = strlen(user);
+
+ if (!M_ASN1_OCTET_STRING_set(id->user, user, userlen))
+ goto err;
+ if (!sk_SXNETID_push(sx->ids, id))
+ goto err;
+ id->zone = zone;
+ return 1;
- if(!(id = SXNETID_new())) goto err;
- if(userlen == -1) userlen = strlen(user);
-
- if(!M_ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err;
- if(!sk_SXNETID_push(sx->ids, id)) goto err;
- id->zone = zone;
- return 1;
-
- err:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- SXNETID_free(id);
- SXNET_free(sx);
- *psx = NULL;
- return 0;
+ err:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ SXNETID_free(id);
+ SXNET_free(sx);
+ *psx = NULL;
+ return 0;
}
ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone)
{
- ASN1_INTEGER *izone = NULL;
- ASN1_OCTET_STRING *oct;
- if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
- return NULL;
- }
- oct = SXNET_get_id_INTEGER(sx, izone);
- M_ASN1_INTEGER_free(izone);
- return oct;
+ ASN1_INTEGER *izone = NULL;
+ ASN1_OCTET_STRING *oct;
+ if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ M_ASN1_INTEGER_free(izone);
+ return oct;
}
ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
{
- ASN1_INTEGER *izone = NULL;
- ASN1_OCTET_STRING *oct;
- if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- M_ASN1_INTEGER_free(izone);
- return NULL;
- }
- oct = SXNET_get_id_INTEGER(sx, izone);
- M_ASN1_INTEGER_free(izone);
- return oct;
+ ASN1_INTEGER *izone = NULL;
+ ASN1_OCTET_STRING *oct;
+ if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ M_ASN1_INTEGER_free(izone);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ M_ASN1_INTEGER_free(izone);
+ return oct;
}
ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone)
{
- SXNETID *id;
- size_t i;
- for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
- id = sk_SXNETID_value(sx->ids, i);
- if(!M_ASN1_INTEGER_cmp(id->zone, zone)) return id->user;
- }
- return NULL;
+ SXNETID *id;
+ size_t i;
+ for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ if (!M_ASN1_INTEGER_cmp(id->zone, zone))
+ return id->user;
+ }
+ return NULL;
}
IMPLEMENT_ASN1_SET_OF(SXNETID)
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index 6bcb6dab..a238a20e 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -1,5 +1,6 @@
/* v3_utl.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
@@ -10,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -57,7 +58,6 @@
*/
/* X509 v3 extension utilities */
-
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -72,10 +72,10 @@
#include "../conf/internal.h"
-
static char *strip_spaces(char *name);
static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens);
+static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
+ GENERAL_NAMES *gens);
static void str_free(OPENSSL_STRING str);
static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
@@ -87,1236 +87,1241 @@ static int ipv6_hex(unsigned char *out, const char *in, int inlen);
/* Add a CONF_VALUE name value pair to stack */
int X509V3_add_value(const char *name, const char *value,
- STACK_OF(CONF_VALUE) **extlist)
+ STACK_OF(CONF_VALUE) **extlist)
{
- CONF_VALUE *vtmp = NULL;
- char *tname = NULL, *tvalue = NULL;
- if(name && !(tname = BUF_strdup(name))) goto err;
- if(value && !(tvalue = BUF_strdup(value))) goto err;
- if(!(vtmp = CONF_VALUE_new())) goto err;
- if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
- vtmp->section = NULL;
- vtmp->name = tname;
- vtmp->value = tvalue;
- if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
- return 1;
- err:
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- if(vtmp) OPENSSL_free(vtmp);
- if(tname) OPENSSL_free(tname);
- if(tvalue) OPENSSL_free(tvalue);
- return 0;
+ CONF_VALUE *vtmp = NULL;
+ char *tname = NULL, *tvalue = NULL;
+ if (name && !(tname = BUF_strdup(name)))
+ goto err;
+ if (value && !(tvalue = BUF_strdup(value)))
+ goto err;
+ if (!(vtmp = CONF_VALUE_new()))
+ goto err;
+ if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
+ goto err;
+ vtmp->section = NULL;
+ vtmp->name = tname;
+ vtmp->value = tvalue;
+ if (!sk_CONF_VALUE_push(*extlist, vtmp))
+ goto err;
+ return 1;
+ err:
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ if (vtmp)
+ OPENSSL_free(vtmp);
+ if (tname)
+ OPENSSL_free(tname);
+ if (tvalue)
+ OPENSSL_free(tvalue);
+ return 0;
}
int X509V3_add_value_uchar(const char *name, const unsigned char *value,
- STACK_OF(CONF_VALUE) **extlist)
- {
- return X509V3_add_value(name,(const char *)value,extlist);
- }
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ return X509V3_add_value(name, (const char *)value, extlist);
+}
/* Free function for STACK_OF(CONF_VALUE) */
void X509V3_conf_free(CONF_VALUE *conf)
{
- if(!conf) return;
- if(conf->name) OPENSSL_free(conf->name);
- if(conf->value) OPENSSL_free(conf->value);
- if(conf->section) OPENSSL_free(conf->section);
- OPENSSL_free(conf);
+ if (!conf)
+ return;
+ if (conf->name)
+ OPENSSL_free(conf->name);
+ if (conf->value)
+ OPENSSL_free(conf->value);
+ if (conf->section)
+ OPENSSL_free(conf->section);
+ OPENSSL_free(conf);
}
int X509V3_add_value_bool(const char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist)
+ STACK_OF(CONF_VALUE) **extlist)
{
- if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
- return X509V3_add_value(name, "FALSE", extlist);
+ if (asn1_bool)
+ return X509V3_add_value(name, "TRUE", extlist);
+ return X509V3_add_value(name, "FALSE", extlist);
}
int X509V3_add_value_bool_nf(char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist)
+ STACK_OF(CONF_VALUE) **extlist)
{
- if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
- return 1;
+ if (asn1_bool)
+ return X509V3_add_value(name, "TRUE", extlist);
+ return 1;
}
-
char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
{
- BIGNUM *bntmp = NULL;
- char *strtmp = NULL;
- if(!a) return NULL;
- if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
- !(strtmp = BN_bn2dec(bntmp)) )
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- BN_free(bntmp);
- return strtmp;
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+ if (!a)
+ return NULL;
+ if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
+ !(strtmp = BN_bn2dec(bntmp)))
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
}
char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
{
- BIGNUM *bntmp = NULL;
- char *strtmp = NULL;
- if(!a) return NULL;
- if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
- !(strtmp = BN_bn2dec(bntmp)) )
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- BN_free(bntmp);
- return strtmp;
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+ if (!a)
+ return NULL;
+ if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
+ !(strtmp = BN_bn2dec(bntmp)))
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
}
ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
{
- BIGNUM *bn = NULL;
- ASN1_INTEGER *aint;
- int isneg, ishex;
- int ret;
- if (!value) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
- return 0;
- }
- bn = BN_new();
- if (value[0] == '-') {
- value++;
- isneg = 1;
- } else isneg = 0;
-
- if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
- value += 2;
- ishex = 1;
- } else ishex = 0;
-
- if (ishex) ret = BN_hex2bn(&bn, value);
- else ret = BN_dec2bn(&bn, value);
-
- if (!ret || value[ret]) {
- BN_free(bn);
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR);
- return 0;
- }
-
- if (isneg && BN_is_zero(bn)) isneg = 0;
-
- aint = BN_to_ASN1_INTEGER(bn, NULL);
- BN_free(bn);
- if (!aint) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
- return 0;
- }
- if (isneg) aint->type |= V_ASN1_NEG;
- return aint;
+ BIGNUM *bn = NULL;
+ ASN1_INTEGER *aint;
+ int isneg, ishex;
+ int ret;
+ if (!value) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+ return 0;
+ }
+ bn = BN_new();
+ if (value[0] == '-') {
+ value++;
+ isneg = 1;
+ } else
+ isneg = 0;
+
+ if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
+ value += 2;
+ ishex = 1;
+ } else
+ ishex = 0;
+
+ if (ishex)
+ ret = BN_hex2bn(&bn, value);
+ else
+ ret = BN_dec2bn(&bn, value);
+
+ if (!ret || value[ret]) {
+ BN_free(bn);
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR);
+ return 0;
+ }
+
+ if (isneg && BN_is_zero(bn))
+ isneg = 0;
+
+ aint = BN_to_ASN1_INTEGER(bn, NULL);
+ BN_free(bn);
+ if (!aint) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
+ return 0;
+ }
+ if (isneg)
+ aint->type |= V_ASN1_NEG;
+ return aint;
}
int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
- STACK_OF(CONF_VALUE) **extlist)
+ STACK_OF(CONF_VALUE) **extlist)
{
- char *strtmp;
- int ret;
- if(!aint) return 1;
- if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
- ret = X509V3_add_value(name, strtmp, extlist);
- OPENSSL_free(strtmp);
- return ret;
+ char *strtmp;
+ int ret;
+ if (!aint)
+ return 1;
+ if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
+ return 0;
+ ret = X509V3_add_value(name, strtmp, extlist);
+ OPENSSL_free(strtmp);
+ return ret;
}
int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
{
- char *btmp;
- if(!(btmp = value->value)) goto err;
- if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
- || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
- || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
- *asn1_bool = 0xff;
- return 1;
- } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
- || !strcmp(btmp, "N") || !strcmp(btmp, "n")
- || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
- *asn1_bool = 0;
- return 1;
- }
- err:
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
- X509V3_conf_err(value);
- return 0;
+ char *btmp;
+ if (!(btmp = value->value))
+ goto err;
+ if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
+ || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
+ || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
+ *asn1_bool = 0xff;
+ return 1;
+ } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
+ || !strcmp(btmp, "N") || !strcmp(btmp, "n")
+ || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
+ *asn1_bool = 0;
+ return 1;
+ }
+ err:
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
+ X509V3_conf_err(value);
+ return 0;
}
int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
{
- ASN1_INTEGER *itmp;
- if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
- X509V3_conf_err(value);
- return 0;
- }
- *aint = itmp;
- return 1;
+ ASN1_INTEGER *itmp;
+ if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
+ X509V3_conf_err(value);
+ return 0;
+ }
+ *aint = itmp;
+ return 1;
}
-#define HDR_NAME 1
-#define HDR_VALUE 2
+#define HDR_NAME 1
+#define HDR_VALUE 2
-/*#define DEBUG*/
+/*
+ * #define DEBUG
+ */
STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
{
- char *p, *q, c;
- char *ntmp, *vtmp;
- STACK_OF(CONF_VALUE) *values = NULL;
- char *linebuf;
- int state;
- /* We are going to modify the line so copy it first */
- linebuf = BUF_strdup(line);
- if (linebuf == NULL)
- {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- state = HDR_NAME;
- ntmp = NULL;
- /* Go through all characters */
- for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
-
- switch(state) {
- case HDR_NAME:
- if(c == ':') {
- state = HDR_VALUE;
- *p = 0;
- ntmp = strip_spaces(q);
- if(!ntmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- q = p + 1;
- } else if(c == ',') {
- *p = 0;
- ntmp = strip_spaces(q);
- q = p + 1;
+ char *p, *q, c;
+ char *ntmp, *vtmp;
+ STACK_OF(CONF_VALUE) *values = NULL;
+ char *linebuf;
+ int state;
+ /* We are going to modify the line so copy it first */
+ linebuf = BUF_strdup(line);
+ if (linebuf == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ state = HDR_NAME;
+ ntmp = NULL;
+ /* Go through all characters */
+ for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
+ p++) {
+
+ switch (state) {
+ case HDR_NAME:
+ if (c == ':') {
+ state = HDR_VALUE;
+ *p = 0;
+ ntmp = strip_spaces(q);
+ if (!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ q = p + 1;
+ } else if (c == ',') {
+ *p = 0;
+ ntmp = strip_spaces(q);
+ q = p + 1;
#if 0
- printf("%s\n", ntmp);
+ printf("%s\n", ntmp);
#endif
- if(!ntmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- X509V3_add_value(ntmp, NULL, &values);
- }
- break ;
-
- case HDR_VALUE:
- if(c == ',') {
- state = HDR_NAME;
- *p = 0;
- vtmp = strip_spaces(q);
+ if (!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ X509V3_add_value(ntmp, NULL, &values);
+ }
+ break;
+
+ case HDR_VALUE:
+ if (c == ',') {
+ state = HDR_NAME;
+ *p = 0;
+ vtmp = strip_spaces(q);
#if 0
- printf("%s\n", ntmp);
+ printf("%s\n", ntmp);
#endif
- if(!vtmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
- goto err;
- }
- X509V3_add_value(ntmp, vtmp, &values);
- ntmp = NULL;
- q = p + 1;
- }
-
- }
- }
-
- if(state == HDR_VALUE) {
- vtmp = strip_spaces(q);
+ if (!vtmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ X509V3_add_value(ntmp, vtmp, &values);
+ ntmp = NULL;
+ q = p + 1;
+ }
+
+ }
+ }
+
+ if (state == HDR_VALUE) {
+ vtmp = strip_spaces(q);
#if 0
- printf("%s=%s\n", ntmp, vtmp);
+ printf("%s=%s\n", ntmp, vtmp);
#endif
- if(!vtmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
- goto err;
- }
- X509V3_add_value(ntmp, vtmp, &values);
- } else {
- ntmp = strip_spaces(q);
+ if (!vtmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ X509V3_add_value(ntmp, vtmp, &values);
+ } else {
+ ntmp = strip_spaces(q);
#if 0
- printf("%s\n", ntmp);
+ printf("%s\n", ntmp);
#endif
- if(!ntmp) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- X509V3_add_value(ntmp, NULL, &values);
- }
-OPENSSL_free(linebuf);
-return values;
-
-err:
-OPENSSL_free(linebuf);
-sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
-return NULL;
+ if (!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ X509V3_add_value(ntmp, NULL, &values);
+ }
+ OPENSSL_free(linebuf);
+ return values;
+
+ err:
+ OPENSSL_free(linebuf);
+ sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
+ return NULL;
}
/* Delete leading and trailing spaces from a string */
static char *strip_spaces(char *name)
{
- char *p, *q;
- /* Skip over leading spaces */
- p = name;
- while(*p && isspace((unsigned char)*p)) p++;
- if(!*p) return NULL;
- q = p + strlen(p) - 1;
- while((q != p) && isspace((unsigned char)*q)) q--;
- if(p != q) q[1] = 0;
- if(!*p) return NULL;
- return p;
+ char *p, *q;
+ /* Skip over leading spaces */
+ p = name;
+ while (*p && isspace((unsigned char)*p))
+ p++;
+ if (!*p)
+ return NULL;
+ q = p + strlen(p) - 1;
+ while ((q != p) && isspace((unsigned char)*q))
+ q--;
+ if (p != q)
+ q[1] = 0;
+ if (!*p)
+ return NULL;
+ return p;
}
/* hex string utilities */
-/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
- * hex representation
- * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
+/*
+ * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation @@@ (Contents of buffer are always kept in ASCII, also
+ * on EBCDIC machines)
*/
char *hex_to_string(const unsigned char *buffer, long len)
{
- char *tmp, *q;
- const unsigned char *p;
- int i;
- static const char hexdig[] = "0123456789ABCDEF";
- if(!buffer || !len) return NULL;
- if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- q = tmp;
- for(i = 0, p = buffer; i < len; i++,p++) {
- *q++ = hexdig[(*p >> 4) & 0xf];
- *q++ = hexdig[*p & 0xf];
- *q++ = ':';
- }
- q[-1] = 0;
-
- return tmp;
+ char *tmp, *q;
+ const unsigned char *p;
+ int i;
+ static const char hexdig[] = "0123456789ABCDEF";
+ if (!buffer || !len)
+ return NULL;
+ if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ q = tmp;
+ for (i = 0, p = buffer; i < len; i++, p++) {
+ *q++ = hexdig[(*p >> 4) & 0xf];
+ *q++ = hexdig[*p & 0xf];
+ *q++ = ':';
+ }
+ q[-1] = 0;
+
+ return tmp;
}
-/* Give a string of hex digits convert to
- * a buffer
+/*
+ * Give a string of hex digits convert to a buffer
*/
unsigned char *string_to_hex(const char *str, long *len)
{
- unsigned char *hexbuf, *q;
- unsigned char ch, cl, *p;
- if(!str) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
- return NULL;
- }
- if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
- for(p = (unsigned char *)str, q = hexbuf; *p;) {
- ch = *p++;
- if(ch == ':') continue;
- cl = *p++;
- if(!cl) {
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS);
- OPENSSL_free(hexbuf);
- return NULL;
- }
- if(isupper(ch)) ch = tolower(ch);
- if(isupper(cl)) cl = tolower(cl);
-
- if((ch >= '0') && (ch <= '9')) ch -= '0';
- else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
- else goto badhex;
-
- if((cl >= '0') && (cl <= '9')) cl -= '0';
- else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
- else goto badhex;
-
- *q++ = (ch << 4) | cl;
- }
-
- if(len) *len = q - hexbuf;
-
- return hexbuf;
-
- err:
- if(hexbuf) OPENSSL_free(hexbuf);
- OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
- return NULL;
-
- badhex:
- OPENSSL_free(hexbuf);
- OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
- return NULL;
+ unsigned char *hexbuf, *q;
+ unsigned char ch, cl, *p;
+ if (!str) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
+ goto err;
+ for (p = (unsigned char *)str, q = hexbuf; *p;) {
+ ch = *p++;
+ if (ch == ':')
+ continue;
+ cl = *p++;
+ if (!cl) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS);
+ OPENSSL_free(hexbuf);
+ return NULL;
+ }
+ if (isupper(ch))
+ ch = tolower(ch);
+ if (isupper(cl))
+ cl = tolower(cl);
+
+ if ((ch >= '0') && (ch <= '9'))
+ ch -= '0';
+ else if ((ch >= 'a') && (ch <= 'f'))
+ ch -= 'a' - 10;
+ else
+ goto badhex;
+
+ if ((cl >= '0') && (cl <= '9'))
+ cl -= '0';
+ else if ((cl >= 'a') && (cl <= 'f'))
+ cl -= 'a' - 10;
+ else
+ goto badhex;
+
+ *q++ = (ch << 4) | cl;
+ }
+
+ if (len)
+ *len = q - hexbuf;
+
+ return hexbuf;
+
+ err:
+ if (hexbuf)
+ OPENSSL_free(hexbuf);
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+
+ badhex:
+ OPENSSL_free(hexbuf);
+ OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
+ return NULL;
}
-/* V2I name comparison function: returns zero if 'name' matches
- * cmp or cmp.*
+/*
+ * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
*/
int name_cmp(const char *name, const char *cmp)
{
- int len, ret;
- char c;
- len = strlen(cmp);
- if((ret = strncmp(name, cmp, len))) return ret;
- c = name[len];
- if(!c || (c=='.')) return 0;
- return 1;
+ int len, ret;
+ char c;
+ len = strlen(cmp);
+ if ((ret = strncmp(name, cmp, len)))
+ return ret;
+ c = name[len];
+ if (!c || (c == '.'))
+ return 0;
+ return 1;
}
static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
{
- return strcmp(*a, *b);
+ return strcmp(*a, *b);
}
STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
{
- GENERAL_NAMES *gens;
- STACK_OF(OPENSSL_STRING) *ret;
+ GENERAL_NAMES *gens;
+ STACK_OF(OPENSSL_STRING) *ret;
- gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
- ret = get_email(X509_get_subject_name(x), gens);
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return ret;
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return ret;
}
STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
{
- AUTHORITY_INFO_ACCESS *info;
- STACK_OF(OPENSSL_STRING) *ret = NULL;
- size_t i;
-
- info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
- if (!info)
- return NULL;
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
- {
- ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
- if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
- {
- if (ad->location->type == GEN_URI)
- {
- if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
- break;
- }
- }
- }
- AUTHORITY_INFO_ACCESS_free(info);
- return ret;
+ AUTHORITY_INFO_ACCESS *info;
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ size_t i;
+
+ info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+ if (!info)
+ return NULL;
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+ if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
+ if (ad->location->type == GEN_URI) {
+ if (!append_ia5
+ (&ret, ad->location->d.uniformResourceIdentifier))
+ break;
+ }
+ }
+ }
+ AUTHORITY_INFO_ACCESS_free(info);
+ return ret;
}
STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
{
- GENERAL_NAMES *gens;
- STACK_OF(X509_EXTENSION) *exts;
- STACK_OF(OPENSSL_STRING) *ret;
-
- exts = X509_REQ_get_extensions(x);
- gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
- ret = get_email(X509_REQ_get_subject_name(x), gens);
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
- return ret;
+ GENERAL_NAMES *gens;
+ STACK_OF(X509_EXTENSION) *exts;
+ STACK_OF(OPENSSL_STRING) *ret;
+
+ exts = X509_REQ_get_extensions(x);
+ gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_REQ_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ return ret;
}
-
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
+static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
+ GENERAL_NAMES *gens)
{
- STACK_OF(OPENSSL_STRING) *ret = NULL;
- X509_NAME_ENTRY *ne;
- ASN1_IA5STRING *email;
- GENERAL_NAME *gen;
- int i;
- size_t j;
- /* Now add any email address(es) to STACK */
- i = -1;
- /* First supplied X509_NAME */
- while((i = X509_NAME_get_index_by_NID(name,
- NID_pkcs9_emailAddress, i)) >= 0) {
- ne = X509_NAME_get_entry(name, i);
- email = X509_NAME_ENTRY_get_data(ne);
- if(!append_ia5(&ret, email)) return NULL;
- }
- for(j = 0; j < sk_GENERAL_NAME_num(gens); j++)
- {
- gen = sk_GENERAL_NAME_value(gens, j);
- if(gen->type != GEN_EMAIL) continue;
- if(!append_ia5(&ret, gen->d.ia5)) return NULL;
- }
- return ret;
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ X509_NAME_ENTRY *ne;
+ ASN1_IA5STRING *email;
+ GENERAL_NAME *gen;
+ int i;
+ size_t j;
+ /* Now add any email address(es) to STACK */
+ i = -1;
+ /* First supplied X509_NAME */
+ while ((i = X509_NAME_get_index_by_NID(name,
+ NID_pkcs9_emailAddress, i)) >= 0) {
+ ne = X509_NAME_get_entry(name, i);
+ email = X509_NAME_ENTRY_get_data(ne);
+ if (!append_ia5(&ret, email))
+ return NULL;
+ }
+ for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
+ gen = sk_GENERAL_NAME_value(gens, j);
+ if (gen->type != GEN_EMAIL)
+ continue;
+ if (!append_ia5(&ret, gen->d.ia5))
+ return NULL;
+ }
+ return ret;
}
static void str_free(OPENSSL_STRING str)
{
- OPENSSL_free(str);
+ OPENSSL_free(str);
}
static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
{
- char *emtmp;
- /* First some sanity checks */
- if(email->type != V_ASN1_IA5STRING) return 1;
- if(!email->data || !email->length) return 1;
- if(!*sk) *sk = sk_OPENSSL_STRING_new(sk_strcmp);
- if(!*sk) return 0;
- /* Don't add duplicates */
- if(sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data)) return 1;
- emtmp = BUF_strdup((char *)email->data);
- if(!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
- X509_email_free(*sk);
- *sk = NULL;
- return 0;
- }
- return 1;
+ char *emtmp;
+ /* First some sanity checks */
+ if (email->type != V_ASN1_IA5STRING)
+ return 1;
+ if (!email->data || !email->length)
+ return 1;
+ if (!*sk)
+ *sk = sk_OPENSSL_STRING_new(sk_strcmp);
+ if (!*sk)
+ return 0;
+ /* Don't add duplicates */
+ if (sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data))
+ return 1;
+ emtmp = BUF_strdup((char *)email->data);
+ if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
+ X509_email_free(*sk);
+ *sk = NULL;
+ return 0;
+ }
+ return 1;
}
void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
{
- sk_OPENSSL_STRING_pop_free(sk, str_free);
+ sk_OPENSSL_STRING_pop_free(sk, str_free);
}
-typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags);
+typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags);
/* Skip pattern prefix to match "wildcard" subject */
static void skip_prefix(const unsigned char **p, size_t *plen,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
- {
- const unsigned char *pattern = *p;
- size_t pattern_len = *plen;
-
- /*
- * If subject starts with a leading '.' followed by more octets, and
- * pattern is longer, compare just an equal-length suffix with the
- * full subject (starting at the '.'), provided the prefix contains
- * no NULs.
- */
- if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
- return;
-
- while (pattern_len > subject_len && *pattern)
- {
- if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
- *pattern == '.')
- break;
- ++pattern;
- --pattern_len;
- }
-
- /* Skip if entire prefix acceptable */
- if (pattern_len == subject_len)
- {
- *p = pattern;
- *plen = pattern_len;
- }
- }
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *pattern = *p;
+ size_t pattern_len = *plen;
+
+ /*
+ * If subject starts with a leading '.' followed by more octets, and
+ * pattern is longer, compare just an equal-length suffix with the
+ * full subject (starting at the '.'), provided the prefix contains
+ * no NULs.
+ */
+ if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
+ return;
+
+ while (pattern_len > subject_len && *pattern) {
+ if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
+ *pattern == '.')
+ break;
+ ++pattern;
+ --pattern_len;
+ }
+
+ /* Skip if entire prefix acceptable */
+ if (pattern_len == subject_len) {
+ *p = pattern;
+ *plen = pattern_len;
+ }
+}
/* Compare while ASCII ignoring case. */
static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
- {
- skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
- if (pattern_len != subject_len)
- return 0;
- while (pattern_len)
- {
- unsigned char l = *pattern;
- unsigned char r = *subject;
- /* The pattern must not contain NUL characters. */
- if (l == 0)
- return 0;
- if (l != r)
- {
- if ('A' <= l && l <= 'Z')
- l = (l - 'A') + 'a';
- if ('A' <= r && r <= 'Z')
- r = (r - 'A') + 'a';
- if (l != r)
- return 0;
- }
- ++pattern;
- ++subject;
- --pattern_len;
- }
- return 1;
- }
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ while (pattern_len) {
+ unsigned char l = *pattern;
+ unsigned char r = *subject;
+ /* The pattern must not contain NUL characters. */
+ if (l == 0)
+ return 0;
+ if (l != r) {
+ if ('A' <= l && l <= 'Z')
+ l = (l - 'A') + 'a';
+ if ('A' <= r && r <= 'Z')
+ r = (r - 'A') + 'a';
+ if (l != r)
+ return 0;
+ }
+ ++pattern;
+ ++subject;
+ --pattern_len;
+ }
+ return 1;
+}
/* Compare using memcmp. */
static int equal_case(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
{
- skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
- if (pattern_len != subject_len)
- return 0;
- return !memcmp(pattern, subject, pattern_len);
+ skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ return !memcmp(pattern, subject, pattern_len);
}
-/* RFC 5280, section 7.5, requires that only the domain is compared in
- a case-insensitive manner. */
+/*
+ * RFC 5280, section 7.5, requires that only the domain is compared in a
+ * case-insensitive manner.
+ */
static int equal_email(const unsigned char *a, size_t a_len,
- const unsigned char *b, size_t b_len,
- unsigned int unused_flags)
- {
- size_t i = a_len;
- if (a_len != b_len)
- return 0;
- /* We search backwards for the '@' character, so that we do
- not have to deal with quoted local-parts. The domain part
- is compared in a case-insensitive manner. */
- while (i > 0)
- {
- --i;
- if (a[i] == '@' || b[i] == '@')
- {
- if (!equal_nocase(a + i, a_len - i,
- b + i, a_len - i, 0))
- return 0;
- break;
- }
- }
- if (i == 0)
- i = a_len;
- return equal_case(a, i, b, i, 0);
- }
-
-/* Compare the prefix and suffix with the subject, and check that the
- characters in-between are valid. */
+ const unsigned char *b, size_t b_len,
+ unsigned int unused_flags)
+{
+ size_t i = a_len;
+ if (a_len != b_len)
+ return 0;
+ /*
+ * We search backwards for the '@' character, so that we do not have to
+ * deal with quoted local-parts. The domain part is compared in a
+ * case-insensitive manner.
+ */
+ while (i > 0) {
+ --i;
+ if (a[i] == '@' || b[i] == '@') {
+ if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
+ return 0;
+ break;
+ }
+ }
+ if (i == 0)
+ i = a_len;
+ return equal_case(a, i, b, i, 0);
+}
+
+/*
+ * Compare the prefix and suffix with the subject, and check that the
+ * characters in-between are valid.
+ */
static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
- const unsigned char *suffix, size_t suffix_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
- {
- const unsigned char *wildcard_start;
- const unsigned char *wildcard_end;
- const unsigned char *p;
- int allow_multi = 0;
- int allow_idna = 0;
-
- if (subject_len < prefix_len + suffix_len)
- return 0;
- if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
- return 0;
- wildcard_start = subject + prefix_len;
- wildcard_end = subject + (subject_len - suffix_len);
- if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
- return 0;
- /*
- * If the wildcard makes up the entire first label, it must match at
- * least one character.
- */
- if (prefix_len == 0 && *suffix == '.')
- {
- if (wildcard_start == wildcard_end)
- return 0;
- allow_idna = 1;
- if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
- allow_multi = 1;
- }
- /* IDNA labels cannot match partial wildcards */
- if (!allow_idna &&
- subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
- return 0;
- /* The wildcard may match a literal '*' */
- if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
- return 1;
- /*
- * Check that the part matched by the wildcard contains only
- * permitted characters and only matches a single label unless
- * allow_multi is set.
- */
- for (p = wildcard_start; p != wildcard_end; ++p)
- if (!(('0' <= *p && *p <= '9') ||
- ('A' <= *p && *p <= 'Z') ||
- ('a' <= *p && *p <= 'z') ||
- *p == '-' || (allow_multi && *p == '.')))
- return 0;
- return 1;
- }
-
-#define LABEL_START (1 << 0)
-#define LABEL_END (1 << 1)
-#define LABEL_HYPHEN (1 << 2)
-#define LABEL_IDNA (1 << 3)
+ const unsigned char *suffix, size_t suffix_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *wildcard_start;
+ const unsigned char *wildcard_end;
+ const unsigned char *p;
+ int allow_multi = 0;
+ int allow_idna = 0;
+
+ if (subject_len < prefix_len + suffix_len)
+ return 0;
+ if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
+ return 0;
+ wildcard_start = subject + prefix_len;
+ wildcard_end = subject + (subject_len - suffix_len);
+ if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
+ return 0;
+ /*
+ * If the wildcard makes up the entire first label, it must match at
+ * least one character.
+ */
+ if (prefix_len == 0 && *suffix == '.') {
+ if (wildcard_start == wildcard_end)
+ return 0;
+ allow_idna = 1;
+ if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
+ allow_multi = 1;
+ }
+ /* IDNA labels cannot match partial wildcards */
+ if (!allow_idna &&
+ subject_len >= 4
+ && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
+ return 0;
+ /* The wildcard may match a literal '*' */
+ if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
+ return 1;
+ /*
+ * Check that the part matched by the wildcard contains only
+ * permitted characters and only matches a single label unless
+ * allow_multi is set.
+ */
+ for (p = wildcard_start; p != wildcard_end; ++p)
+ if (!(('0' <= *p && *p <= '9') ||
+ ('A' <= *p && *p <= 'Z') ||
+ ('a' <= *p && *p <= 'z') ||
+ *p == '-' || (allow_multi && *p == '.')))
+ return 0;
+ return 1;
+}
+
+#define LABEL_START (1 << 0)
+#define LABEL_END (1 << 1)
+#define LABEL_HYPHEN (1 << 2)
+#define LABEL_IDNA (1 << 3)
static const unsigned char *valid_star(const unsigned char *p, size_t len,
- unsigned int flags)
- {
- const unsigned char *star = 0;
- size_t i;
- int state = LABEL_START;
- int dots = 0;
- for (i = 0; i < len; ++i)
- {
- /*
- * Locate first and only legal wildcard, either at the start
- * or end of a non-IDNA first and not final label.
- */
- if (p[i] == '*')
- {
- int atstart = (state & LABEL_START);
- int atend = (i == len - 1 || p[i+1] == '.');
- /*
- * At most one wildcard per pattern.
- * No wildcards in IDNA labels.
- * No wildcards after the first label.
- */
- if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
- return NULL;
- /* Only full-label '*.example.com' wildcards? */
- if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
- && (!atstart || !atend))
- return NULL;
- /* No 'foo*bar' wildcards */
- if (!atstart && !atend)
- return NULL;
- star = &p[i];
- state &= ~LABEL_START;
- }
- else if ((state & LABEL_START) != 0)
- {
- /*
- * At the start of a label, skip any "xn--" and
- * remain in the LABEL_START state, but set the
- * IDNA label state
- */
- if ((state & LABEL_IDNA) == 0 && len - i >= 4
- && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
- {
- i += 3;
- state |= LABEL_IDNA;
- continue;
- }
- /* Labels must start with a letter or digit */
- state &= ~LABEL_START;
- if (('a' <= p[i] && p[i] <= 'z')
- || ('A' <= p[i] && p[i] <= 'Z')
- || ('0' <= p[i] && p[i] <= '9'))
- continue;
- return NULL;
- }
- else if (('a' <= p[i] && p[i] <= 'z')
- || ('A' <= p[i] && p[i] <= 'Z')
- || ('0' <= p[i] && p[i] <= '9'))
- {
- state &= LABEL_IDNA;
- continue;
- }
- else if (p[i] == '.')
- {
- if (state & (LABEL_HYPHEN | LABEL_START))
- return NULL;
- state = LABEL_START;
- ++dots;
- }
- else if (p[i] == '-')
- {
- if (state & LABEL_HYPHEN)
- return NULL;
- state |= LABEL_HYPHEN;
- }
- else
- return NULL;
- }
-
- /*
- * The final label must not end in a hyphen or ".", and
- * there must be at least two dots after the star.
- */
- if ((state & (LABEL_START | LABEL_HYPHEN)) != 0
- || dots < 2)
- return NULL;
- return star;
- }
+ unsigned int flags)
+{
+ const unsigned char *star = 0;
+ size_t i;
+ int state = LABEL_START;
+ int dots = 0;
+ for (i = 0; i < len; ++i) {
+ /*
+ * Locate first and only legal wildcard, either at the start
+ * or end of a non-IDNA first and not final label.
+ */
+ if (p[i] == '*') {
+ int atstart = (state & LABEL_START);
+ int atend = (i == len - 1 || p[i + 1] == '.');
+ /*
+ * At most one wildcard per pattern.
+ * No wildcards in IDNA labels.
+ * No wildcards after the first label.
+ */
+ if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
+ return NULL;
+ /* Only full-label '*.example.com' wildcards? */
+ if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
+ && (!atstart || !atend))
+ return NULL;
+ /* No 'foo*bar' wildcards */
+ if (!atstart && !atend)
+ return NULL;
+ star = &p[i];
+ state &= ~LABEL_START;
+ } else if ((state & LABEL_START) != 0) {
+ /*
+ * At the start of a label, skip any "xn--" and
+ * remain in the LABEL_START state, but set the
+ * IDNA label state
+ */
+ if ((state & LABEL_IDNA) == 0 && len - i >= 4
+ && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) {
+ i += 3;
+ state |= LABEL_IDNA;
+ continue;
+ }
+ /* Labels must start with a letter or digit */
+ state &= ~LABEL_START;
+ if (('a' <= p[i] && p[i] <= 'z')
+ || ('A' <= p[i] && p[i] <= 'Z')
+ || ('0' <= p[i] && p[i] <= '9'))
+ continue;
+ return NULL;
+ } else if (('a' <= p[i] && p[i] <= 'z')
+ || ('A' <= p[i] && p[i] <= 'Z')
+ || ('0' <= p[i] && p[i] <= '9')) {
+ state &= LABEL_IDNA;
+ continue;
+ } else if (p[i] == '.') {
+ if (state & (LABEL_HYPHEN | LABEL_START))
+ return NULL;
+ state = LABEL_START;
+ ++dots;
+ } else if (p[i] == '-') {
+ /* no domain/subdomain starts with '-' */
+ if ((state & LABEL_START) != 0)
+ return NULL;
+ state |= LABEL_HYPHEN;
+ } else
+ return NULL;
+ }
+
+ /*
+ * The final label must not end in a hyphen or ".", and
+ * there must be at least two dots after the star.
+ */
+ if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
+ return NULL;
+ return star;
+}
/* Compare using wildcards. */
static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
- {
- const unsigned char *star = NULL;
-
- /*
- * Subject names starting with '.' can only match a wildcard pattern
- * via a subject sub-domain pattern suffix match.
- */
- if (!(subject_len > 1 && subject[0] == '.'))
- star = valid_star(pattern, pattern_len, flags);
- if (star == NULL)
- return equal_nocase(pattern, pattern_len,
- subject, subject_len, flags);
- return wildcard_match(pattern, star - pattern,
- star + 1, (pattern + pattern_len) - star - 1,
- subject, subject_len, flags);
- }
-
-/* Compare an ASN1_STRING to a supplied string. If they match
- * return 1. If cmp_type > 0 only compare if string matches the
- * type, otherwise convert it to UTF8.
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *star = NULL;
+
+ /*
+ * Subject names starting with '.' can only match a wildcard pattern
+ * via a subject sub-domain pattern suffix match.
+ */
+ if (!(subject_len > 1 && subject[0] == '.'))
+ star = valid_star(pattern, pattern_len, flags);
+ if (star == NULL)
+ return equal_nocase(pattern, pattern_len,
+ subject, subject_len, flags);
+ return wildcard_match(pattern, star - pattern,
+ star + 1, (pattern + pattern_len) - star - 1,
+ subject, subject_len, flags);
+}
+
+/*
+ * Compare an ASN1_STRING to a supplied string. If they match return 1. If
+ * cmp_type > 0 only compare if string matches the type, otherwise convert it
+ * to UTF8.
*/
static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
- unsigned int flags, const char *b, size_t blen,
- char **peername)
- {
- int rv = 0;
-
- if (!a->data || !a->length)
- return 0;
- if (cmp_type > 0)
- {
- if (cmp_type != a->type)
- return 0;
- if (cmp_type == V_ASN1_IA5STRING)
- rv = equal(a->data, a->length,
- (unsigned char *)b, blen, flags);
- else if (a->length == (int)blen && !memcmp(a->data, b, blen))
- rv = 1;
- if (rv > 0 && peername)
- *peername = BUF_strndup((char *)a->data, a->length);
- }
- else
- {
- int astrlen;
- unsigned char *astr;
- astrlen = ASN1_STRING_to_UTF8(&astr, a);
- if (astrlen < 0)
- return -1;
- rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
- if (rv > 0 && peername)
- *peername = BUF_strndup((char *)astr, astrlen);
- OPENSSL_free(astr);
- }
- return rv;
- }
+ unsigned int flags, const char *b, size_t blen,
+ char **peername)
+{
+ int rv = 0;
+
+ if (!a->data || !a->length)
+ return 0;
+ if (cmp_type > 0) {
+ if (cmp_type != a->type)
+ return 0;
+ if (cmp_type == V_ASN1_IA5STRING)
+ rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
+ else if (a->length == (int)blen && !memcmp(a->data, b, blen))
+ rv = 1;
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)a->data, a->length);
+ } else {
+ int astrlen;
+ unsigned char *astr;
+ astrlen = ASN1_STRING_to_UTF8(&astr, a);
+ if (astrlen < 0)
+ return -1;
+ rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)astr, astrlen);
+ OPENSSL_free(astr);
+ }
+ return rv;
+}
static int do_x509_check(X509 *x, const char *chk, size_t chklen,
- unsigned int flags, int check_type,
- char **peername)
- {
- GENERAL_NAMES *gens = NULL;
- X509_NAME *name = NULL;
- size_t i;
- int j;
- int cnid = NID_undef;
- int alt_type;
- int san_present = 0;
- int rv = 0;
- equal_fn equal;
-
- /* See below, this flag is internal-only */
- flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
- if (check_type == GEN_EMAIL)
- {
- cnid = NID_pkcs9_emailAddress;
- alt_type = V_ASN1_IA5STRING;
- equal = equal_email;
- }
- else if (check_type == GEN_DNS)
- {
- cnid = NID_commonName;
- /* Implicit client-side DNS sub-domain pattern */
- if (chklen > 1 && chk[0] == '.')
- flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
- alt_type = V_ASN1_IA5STRING;
- if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
- equal = equal_nocase;
- else
- equal = equal_wildcard;
- }
- else
- {
- alt_type = V_ASN1_OCTET_STRING;
- equal = equal_case;
- }
-
- gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
- if (gens)
- {
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
- {
- GENERAL_NAME *gen;
- ASN1_STRING *cstr;
- gen = sk_GENERAL_NAME_value(gens, i);
- if (gen->type != check_type)
- continue;
- san_present = 1;
- if (check_type == GEN_EMAIL)
- cstr = gen->d.rfc822Name;
- else if (check_type == GEN_DNS)
- cstr = gen->d.dNSName;
- else
- cstr = gen->d.iPAddress;
- /* Positive on success, negative on error! */
- if ((rv = do_check_string(cstr, alt_type, equal, flags,
- chk, chklen, peername)) != 0)
- break;
- }
- GENERAL_NAMES_free(gens);
- if (rv != 0)
- return rv;
- if (cnid == NID_undef
- || (san_present
- && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
- return 0;
- }
-
- /* We're done if CN-ID is not pertinent */
- if (cnid == NID_undef)
- return 0;
-
- j = -1;
- name = X509_get_subject_name(x);
- while((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0)
- {
- X509_NAME_ENTRY *ne;
- ASN1_STRING *str;
- ne = X509_NAME_get_entry(name, j);
- str = X509_NAME_ENTRY_get_data(ne);
- /* Positive on success, negative on error! */
- if ((rv = do_check_string(str, -1, equal, flags,
- chk, chklen, peername)) != 0)
- return rv;
- }
- return 0;
- }
+ unsigned int flags, int check_type, char **peername)
+{
+ GENERAL_NAMES *gens = NULL;
+ X509_NAME *name = NULL;
+ size_t i;
+ int j;
+ int cnid = NID_undef;
+ int alt_type;
+ int san_present = 0;
+ int rv = 0;
+ equal_fn equal;
+
+ /* See below, this flag is internal-only */
+ flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ if (check_type == GEN_EMAIL) {
+ cnid = NID_pkcs9_emailAddress;
+ alt_type = V_ASN1_IA5STRING;
+ equal = equal_email;
+ } else if (check_type == GEN_DNS) {
+ cnid = NID_commonName;
+ /* Implicit client-side DNS sub-domain pattern */
+ if (chklen > 1 && chk[0] == '.')
+ flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ alt_type = V_ASN1_IA5STRING;
+ if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
+ equal = equal_nocase;
+ else
+ equal = equal_wildcard;
+ } else {
+ alt_type = V_ASN1_OCTET_STRING;
+ equal = equal_case;
+ }
+
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ if (gens) {
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ GENERAL_NAME *gen;
+ ASN1_STRING *cstr;
+ gen = sk_GENERAL_NAME_value(gens, i);
+ if (gen->type != check_type)
+ continue;
+ san_present = 1;
+ if (check_type == GEN_EMAIL)
+ cstr = gen->d.rfc822Name;
+ else if (check_type == GEN_DNS)
+ cstr = gen->d.dNSName;
+ else
+ cstr = gen->d.iPAddress;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(cstr, alt_type, equal, flags,
+ chk, chklen, peername)) != 0)
+ break;
+ }
+ GENERAL_NAMES_free(gens);
+ if (rv != 0)
+ return rv;
+ if (cnid == NID_undef
+ || (san_present
+ && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
+ return 0;
+ }
+
+ /* We're done if CN-ID is not pertinent */
+ if (cnid == NID_undef)
+ return 0;
+
+ j = -1;
+ name = X509_get_subject_name(x);
+ while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
+ X509_NAME_ENTRY *ne;
+ ASN1_STRING *str;
+ ne = X509_NAME_get_entry(name, j);
+ str = X509_NAME_ENTRY_get_data(ne);
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(str, -1, equal, flags,
+ chk, chklen, peername)) != 0)
+ return rv;
+ }
+ return 0;
+}
int X509_check_host(X509 *x, const char *chk, size_t chklen,
- unsigned int flags, char **peername)
- {
- if (chk == NULL)
- return -2;
- if (memchr(chk, '\0', chklen))
- return -2;
- return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
- }
+ unsigned int flags, char **peername)
+{
+ if (chk == NULL)
+ return -2;
+ if (memchr(chk, '\0', chklen))
+ return -2;
+ return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
+}
int X509_check_email(X509 *x, const char *chk, size_t chklen,
- unsigned int flags)
- {
- if (chk == NULL)
- return -2;
- if (memchr(chk, '\0', chklen))
- return -2;
- return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
- }
+ unsigned int flags)
+{
+ if (chk == NULL)
+ return -2;
+ if (memchr(chk, '\0', chklen))
+ return -2;
+ return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
+}
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
- {
- if (chk == NULL)
- return -2;
- return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
- }
+ unsigned int flags)
+{
+ if (chk == NULL)
+ return -2;
+ return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
+}
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
- {
- unsigned char ipout[16];
- size_t iplen;
-
- if (ipasc == NULL)
- return -2;
- iplen = (size_t) a2i_ipadd(ipout, ipasc);
- if (iplen == 0)
- return -2;
- return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
- }
-
-/* Convert IP addresses both IPv4 and IPv6 into an
- * OCTET STRING compatible with RFC3280.
+{
+ unsigned char ipout[16];
+ size_t iplen;
+
+ if (ipasc == NULL)
+ return -2;
+ iplen = (size_t)a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return -2;
+ return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
+}
+
+/*
+ * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
+ * with RFC3280.
*/
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
- {
- unsigned char ipout[16];
- ASN1_OCTET_STRING *ret;
- int iplen;
+{
+ unsigned char ipout[16];
+ ASN1_OCTET_STRING *ret;
+ int iplen;
- /* If string contains a ':' assume IPv6 */
+ /* If string contains a ':' assume IPv6 */
- iplen = a2i_ipadd(ipout, ipasc);
+ iplen = a2i_ipadd(ipout, ipasc);
- if (!iplen)
- return NULL;
+ if (!iplen)
+ return NULL;
- ret = ASN1_OCTET_STRING_new();
- if (!ret)
- return NULL;
- if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
- {
- ASN1_OCTET_STRING_free(ret);
- return NULL;
- }
- return ret;
- }
+ ret = ASN1_OCTET_STRING_new();
+ if (!ret)
+ return NULL;
+ if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
+ ASN1_OCTET_STRING_free(ret);
+ return NULL;
+ }
+ return ret;
+}
ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
- {
- ASN1_OCTET_STRING *ret = NULL;
- unsigned char ipout[32];
- char *iptmp = NULL, *p;
- int iplen1, iplen2;
- p = strchr(ipasc,'/');
- if (!p)
- return NULL;
- iptmp = BUF_strdup(ipasc);
- if (!iptmp)
- return NULL;
- p = iptmp + (p - ipasc);
- *p++ = 0;
-
- iplen1 = a2i_ipadd(ipout, iptmp);
-
- if (!iplen1)
- goto err;
-
- iplen2 = a2i_ipadd(ipout + iplen1, p);
-
- OPENSSL_free(iptmp);
- iptmp = NULL;
-
- if (!iplen2 || (iplen1 != iplen2))
- goto err;
-
- ret = ASN1_OCTET_STRING_new();
- if (!ret)
- goto err;
- if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
- goto err;
-
- return ret;
-
- err:
- if (iptmp)
- OPENSSL_free(iptmp);
- if (ret)
- ASN1_OCTET_STRING_free(ret);
- return NULL;
- }
-
+{
+ ASN1_OCTET_STRING *ret = NULL;
+ unsigned char ipout[32];
+ char *iptmp = NULL, *p;
+ int iplen1, iplen2;
+ p = strchr(ipasc, '/');
+ if (!p)
+ return NULL;
+ iptmp = BUF_strdup(ipasc);
+ if (!iptmp)
+ return NULL;
+ p = iptmp + (p - ipasc);
+ *p++ = 0;
+
+ iplen1 = a2i_ipadd(ipout, iptmp);
+
+ if (!iplen1)
+ goto err;
+
+ iplen2 = a2i_ipadd(ipout + iplen1, p);
+
+ OPENSSL_free(iptmp);
+ iptmp = NULL;
+
+ if (!iplen2 || (iplen1 != iplen2))
+ goto err;
+
+ ret = ASN1_OCTET_STRING_new();
+ if (!ret)
+ goto err;
+ if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+ goto err;
+
+ return ret;
+
+ err:
+ if (iptmp)
+ OPENSSL_free(iptmp);
+ if (ret)
+ ASN1_OCTET_STRING_free(ret);
+ return NULL;
+}
int a2i_ipadd(unsigned char *ipout, const char *ipasc)
- {
- /* If string contains a ':' assume IPv6 */
-
- if (strchr(ipasc, ':'))
- {
- if (!ipv6_from_asc(ipout, ipasc))
- return 0;
- return 16;
- }
- else
- {
- if (!ipv4_from_asc(ipout, ipasc))
- return 0;
- return 4;
- }
- }
+{
+ /* If string contains a ':' assume IPv6 */
+
+ if (strchr(ipasc, ':')) {
+ if (!ipv6_from_asc(ipout, ipasc))
+ return 0;
+ return 16;
+ } else {
+ if (!ipv4_from_asc(ipout, ipasc))
+ return 0;
+ return 4;
+ }
+}
static int ipv4_from_asc(unsigned char *v4, const char *in)
- {
- int a0, a1, a2, a3;
- if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
- return 0;
- if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
- || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
- return 0;
- v4[0] = a0;
- v4[1] = a1;
- v4[2] = a2;
- v4[3] = a3;
- return 1;
- }
+{
+ int a0, a1, a2, a3;
+ if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
+ return 0;
+ if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
+ || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
+ return 0;
+ v4[0] = a0;
+ v4[1] = a1;
+ v4[2] = a2;
+ v4[3] = a3;
+ return 1;
+}
typedef struct {
- /* Temporary store for IPV6 output */
- unsigned char tmp[16];
- /* Total number of bytes in tmp */
- int total;
- /* The position of a zero (corresponding to '::') */
- int zero_pos;
- /* Number of zeroes */
- int zero_cnt;
- } IPV6_STAT;
-
+ /* Temporary store for IPV6 output */
+ unsigned char tmp[16];
+ /* Total number of bytes in tmp */
+ int total;
+ /* The position of a zero (corresponding to '::') */
+ int zero_pos;
+ /* Number of zeroes */
+ int zero_cnt;
+} IPV6_STAT;
static int ipv6_from_asc(unsigned char *v6, const char *in)
- {
- IPV6_STAT v6stat;
- v6stat.total = 0;
- v6stat.zero_pos = -1;
- v6stat.zero_cnt = 0;
- /* Treat the IPv6 representation as a list of values
- * separated by ':'. The presence of a '::' will parse
- * as one, two or three zero length elements.
- */
- if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
- return 0;
-
- /* Now for some sanity checks */
-
- if (v6stat.zero_pos == -1)
- {
- /* If no '::' must have exactly 16 bytes */
- if (v6stat.total != 16)
- return 0;
- }
- else
- {
- /* If '::' must have less than 16 bytes */
- if (v6stat.total == 16)
- return 0;
- /* More than three zeroes is an error */
- if (v6stat.zero_cnt > 3)
- return 0;
- /* Can only have three zeroes if nothing else present */
- else if (v6stat.zero_cnt == 3)
- {
- if (v6stat.total > 0)
- return 0;
- }
- /* Can only have two zeroes if at start or end */
- else if (v6stat.zero_cnt == 2)
- {
- if ((v6stat.zero_pos != 0)
- && (v6stat.zero_pos != v6stat.total))
- return 0;
- }
- else
- /* Can only have one zero if *not* start or end */
- {
- if ((v6stat.zero_pos == 0)
- || (v6stat.zero_pos == v6stat.total))
- return 0;
- }
- }
-
- /* Format result */
-
- if (v6stat.zero_pos >= 0)
- {
- /* Copy initial part */
- memcpy(v6, v6stat.tmp, v6stat.zero_pos);
- /* Zero middle */
- memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
- /* Copy final part */
- if (v6stat.total != v6stat.zero_pos)
- memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
- v6stat.tmp + v6stat.zero_pos,
- v6stat.total - v6stat.zero_pos);
- }
- else
- memcpy(v6, v6stat.tmp, 16);
-
- return 1;
- }
+{
+ IPV6_STAT v6stat;
+ v6stat.total = 0;
+ v6stat.zero_pos = -1;
+ v6stat.zero_cnt = 0;
+ /*
+ * Treat the IPv6 representation as a list of values separated by ':'.
+ * The presence of a '::' will parse as one, two or three zero length
+ * elements.
+ */
+ if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
+ return 0;
+
+ /* Now for some sanity checks */
+
+ if (v6stat.zero_pos == -1) {
+ /* If no '::' must have exactly 16 bytes */
+ if (v6stat.total != 16)
+ return 0;
+ } else {
+ /* If '::' must have less than 16 bytes */
+ if (v6stat.total == 16)
+ return 0;
+ /* More than three zeroes is an error */
+ if (v6stat.zero_cnt > 3)
+ return 0;
+ /* Can only have three zeroes if nothing else present */
+ else if (v6stat.zero_cnt == 3) {
+ if (v6stat.total > 0)
+ return 0;
+ }
+ /* Can only have two zeroes if at start or end */
+ else if (v6stat.zero_cnt == 2) {
+ if ((v6stat.zero_pos != 0)
+ && (v6stat.zero_pos != v6stat.total))
+ return 0;
+ } else
+ /* Can only have one zero if *not* start or end */
+ {
+ if ((v6stat.zero_pos == 0)
+ || (v6stat.zero_pos == v6stat.total))
+ return 0;
+ }
+ }
+
+ /* Format result */
+
+ if (v6stat.zero_pos >= 0) {
+ /* Copy initial part */
+ memcpy(v6, v6stat.tmp, v6stat.zero_pos);
+ /* Zero middle */
+ memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
+ /* Copy final part */
+ if (v6stat.total != v6stat.zero_pos)
+ memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
+ v6stat.tmp + v6stat.zero_pos,
+ v6stat.total - v6stat.zero_pos);
+ } else
+ memcpy(v6, v6stat.tmp, 16);
+
+ return 1;
+}
static int ipv6_cb(const char *elem, int len, void *usr)
- {
- IPV6_STAT *s = usr;
- /* Error if 16 bytes written */
- if (s->total == 16)
- return 0;
- if (len == 0)
- {
- /* Zero length element, corresponds to '::' */
- if (s->zero_pos == -1)
- s->zero_pos = s->total;
- /* If we've already got a :: its an error */
- else if (s->zero_pos != s->total)
- return 0;
- s->zero_cnt++;
- }
- else
- {
- /* If more than 4 characters could be final a.b.c.d form */
- if (len > 4)
- {
- /* Need at least 4 bytes left */
- if (s->total > 12)
- return 0;
- /* Must be end of string */
- if (elem[len])
- return 0;
- if (!ipv4_from_asc(s->tmp + s->total, elem))
- return 0;
- s->total += 4;
- }
- else
- {
- if (!ipv6_hex(s->tmp + s->total, elem, len))
- return 0;
- s->total += 2;
- }
- }
- return 1;
- }
-
-/* Convert a string of up to 4 hex digits into the corresponding
- * IPv6 form.
+{
+ IPV6_STAT *s = usr;
+ /* Error if 16 bytes written */
+ if (s->total == 16)
+ return 0;
+ if (len == 0) {
+ /* Zero length element, corresponds to '::' */
+ if (s->zero_pos == -1)
+ s->zero_pos = s->total;
+ /* If we've already got a :: its an error */
+ else if (s->zero_pos != s->total)
+ return 0;
+ s->zero_cnt++;
+ } else {
+ /* If more than 4 characters could be final a.b.c.d form */
+ if (len > 4) {
+ /* Need at least 4 bytes left */
+ if (s->total > 12)
+ return 0;
+ /* Must be end of string */
+ if (elem[len])
+ return 0;
+ if (!ipv4_from_asc(s->tmp + s->total, elem))
+ return 0;
+ s->total += 4;
+ } else {
+ if (!ipv6_hex(s->tmp + s->total, elem, len))
+ return 0;
+ s->total += 2;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
*/
static int ipv6_hex(unsigned char *out, const char *in, int inlen)
- {
- unsigned char c;
- unsigned int num = 0;
- if (inlen > 4)
- return 0;
- while(inlen--)
- {
- c = *in++;
- num <<= 4;
- if ((c >= '0') && (c <= '9'))
- num |= c - '0';
- else if ((c >= 'A') && (c <= 'F'))
- num |= c - 'A' + 10;
- else if ((c >= 'a') && (c <= 'f'))
- num |= c - 'a' + 10;
- else
- return 0;
- }
- out[0] = num >> 8;
- out[1] = num & 0xff;
- return 1;
- }
-
-
-int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
- unsigned long chtype)
- {
- CONF_VALUE *v;
- int mval;
- size_t i;
- char *p, *type;
- if (!nm)
- return 0;
-
- for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
- {
- v=sk_CONF_VALUE_value(dn_sk,i);
- type=v->name;
- /* Skip past any leading X. X: X, etc to allow for
- * multiple instances
- */
- for(p = type; *p ; p++)
- if ((*p == ':') || (*p == ',') || (*p == '.'))
- {
- p++;
- if(*p) type = p;
- break;
- }
- if (*type == '+')
- {
- mval = -1;
- type++;
- }
- else
- mval = 0;
- if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
- (unsigned char *) v->value,-1,-1,mval))
- return 0;
-
- }
- return 1;
- }
+{
+ unsigned char c;
+ unsigned int num = 0;
+ if (inlen > 4)
+ return 0;
+ while (inlen--) {
+ c = *in++;
+ num <<= 4;
+ if ((c >= '0') && (c <= '9'))
+ num |= c - '0';
+ else if ((c >= 'A') && (c <= 'F'))
+ num |= c - 'A' + 10;
+ else if ((c >= 'a') && (c <= 'f'))
+ num |= c - 'a' + 10;
+ else
+ return 0;
+ }
+ out[0] = num >> 8;
+ out[1] = num & 0xff;
+ return 1;
+}
+
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF (CONF_VALUE) * dn_sk,
+ unsigned long chtype)
+{
+ CONF_VALUE *v;
+ int mval;
+ size_t i;
+ char *p, *type;
+ if (!nm)
+ return 0;
+
+ for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
+ v = sk_CONF_VALUE_value(dn_sk, i);
+ type = v->name;
+ /*
+ * Skip past any leading X. X: X, etc to allow for multiple instances
+ */
+ for (p = type; *p; p++)
+ if ((*p == ':') || (*p == ',') || (*p == '.')) {
+ p++;
+ if (*p)
+ type = p;
+ break;
+ }
+ if (*type == '+') {
+ mval = -1;
+ type++;
+ } else
+ mval = 0;
+ if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
+ (unsigned char *)v->value, -1, -1,
+ mval))
+ return 0;
+
+ }
+ return 1;
+}
diff --git a/src/crypto/x509v3/v3name_test.c b/src/crypto/x509v3/v3name_test.c
index f9f70871..dadf488f 100644
--- a/src/crypto/x509v3/v3name_test.c
+++ b/src/crypto/x509v3/v3name_test.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
/* ====================================================================
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
*
@@ -8,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -60,363 +62,349 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
-static const char *const names[] =
- {
- "a", "b", ".", "*", "@",
- ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
- "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
- "*@example.com", "test@*.example.com", "example.com", "www.example.com",
- "test.www.example.com", "*.example.com", "*.www.example.com",
- "test.*.example.com", "www.*.com",
- ".www.example.com", "*www.example.com",
- "example.net", "xn--rger-koa.example.com",
- "a.example.com", "b.example.com",
- "postmaster@example.com", "Postmaster@example.com",
- "postmaster@EXAMPLE.COM",
- NULL
- };
-
-static const char *const exceptions[] =
- {
- "set CN: host: [*.example.com] matches [a.example.com]",
- "set CN: host: [*.example.com] matches [b.example.com]",
- "set CN: host: [*.example.com] matches [www.example.com]",
- "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
- "set CN: host: [*.www.example.com] matches [test.www.example.com]",
- "set CN: host: [*.www.example.com] matches [.www.example.com]",
- "set CN: host: [*www.example.com] matches [www.example.com]",
- "set CN: host: [test.www.example.com] matches [.www.example.com]",
- "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
- "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
- "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
- "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
- "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
- "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
- "set dnsName: host: [*.example.com] matches [www.example.com]",
- "set dnsName: host: [*.example.com] matches [a.example.com]",
- "set dnsName: host: [*.example.com] matches [b.example.com]",
- "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
- "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
- "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
- "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
- "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
- "set dnsName: host: [*www.example.com] matches [www.example.com]",
- "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
- "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
- "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
- "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
- "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
- NULL
- };
+static const char *const names[] = {
+ "a", "b", ".", "*", "@",
+ ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
+ "-example.com", "example-.com",
+ "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
+ "*@example.com", "test@*.example.com", "example.com", "www.example.com",
+ "test.www.example.com", "*.example.com", "*.www.example.com",
+ "test.*.example.com", "www.*.com",
+ ".www.example.com", "*www.example.com",
+ "example.net", "xn--rger-koa.example.com",
+ "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
+ "*.good--example.com", "www.good--example.com",
+ "*.xn--bar.com", "xn--foo.xn--bar.com",
+ "a.example.com", "b.example.com",
+ "postmaster@example.com", "Postmaster@example.com",
+ "postmaster@EXAMPLE.COM",
+ NULL
+};
+
+static const char *const exceptions[] = {
+ "set CN: host: [*.example.com] matches [a.example.com]",
+ "set CN: host: [*.example.com] matches [b.example.com]",
+ "set CN: host: [*.example.com] matches [www.example.com]",
+ "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
+ "set CN: host: [*.www.example.com] matches [test.www.example.com]",
+ "set CN: host: [*.www.example.com] matches [.www.example.com]",
+ "set CN: host: [*www.example.com] matches [www.example.com]",
+ "set CN: host: [test.www.example.com] matches [.www.example.com]",
+ "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set CN: host: [*.good--example.com] matches [www.good--example.com]",
+ "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+ "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+ "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+ "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+ "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+ "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+ "set dnsName: host: [*.example.com] matches [www.example.com]",
+ "set dnsName: host: [*.example.com] matches [a.example.com]",
+ "set dnsName: host: [*.example.com] matches [b.example.com]",
+ "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
+ "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
+ "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+ "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*www.example.com] matches [www.example.com]",
+ "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
+ "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+ "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+ "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+ "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+ NULL
+};
static int is_exception(const char *msg)
- {
- const char *const *p;
- for (p = exceptions; *p; ++p)
- if (strcmp(msg, *p) == 0)
- return 1;
- return 0;
- }
+{
+ const char *const *p;
+ for (p = exceptions; *p; ++p)
+ if (strcmp(msg, *p) == 0)
+ return 1;
+ return 0;
+}
static int set_cn(X509 *crt, ...)
- {
- int ret = 0;
- X509_NAME *n = NULL;
- va_list ap;
- va_start(ap, crt);
- n = X509_NAME_new();
- if (n == NULL)
- goto out;
- while (1) {
- int nid;
- const char *name;
- nid = va_arg(ap, int);
- if (nid == 0)
- break;
- name = va_arg(ap, const char *);
- if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
- (unsigned char *)name,
- -1, -1, 1))
- goto out;
- }
- if (!X509_set_subject_name(crt, n))
- goto out;
- ret = 1;
+{
+ int ret = 0;
+ X509_NAME *n = NULL;
+ va_list ap;
+ va_start(ap, crt);
+ n = X509_NAME_new();
+ if (n == NULL)
+ goto out;
+ while (1) {
+ int nid;
+ const char *name;
+ nid = va_arg(ap, int);
+ if (nid == 0)
+ break;
+ name = va_arg(ap, const char *);
+ if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
+ (unsigned char *)name, -1, -1, 1))
+ goto out;
+ }
+ if (!X509_set_subject_name(crt, n))
+ goto out;
+ ret = 1;
out:
- X509_NAME_free(n);
- va_end(ap);
- return ret;
- }
+ X509_NAME_free(n);
+ va_end(ap);
+ return ret;
+}
/*
-int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
-X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
- int nid, int crit, ASN1_OCTET_STRING *data);
-int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
-*/
+ * int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); X509_EXTENSION
+ * *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit,
+ * ASN1_OCTET_STRING *data); int X509_add_ext(X509 *x, X509_EXTENSION *ex,
+ * int loc);
+ */
static int set_altname(X509 *crt, ...)
- {
- int ret = 0;
- GENERAL_NAMES *gens = NULL;
- GENERAL_NAME *gen = NULL;
- ASN1_IA5STRING *ia5 = NULL;
- va_list ap;
- va_start(ap, crt);
- gens = sk_GENERAL_NAME_new_null();
- if (gens == NULL)
- goto out;
- while (1) {
- int type;
- const char *name;
- type = va_arg(ap, int);
- if (type == 0)
- break;
- name = va_arg(ap, const char *);
-
- gen = GENERAL_NAME_new();
- if (gen == NULL)
- goto out;
- ia5 = ASN1_IA5STRING_new();
- if (ia5 == NULL)
- goto out;
- if (!ASN1_STRING_set(ia5, name, -1))
- goto out;
- switch (type)
- {
- case GEN_EMAIL:
- case GEN_DNS:
- GENERAL_NAME_set0_value(gen, type, ia5);
- ia5 = NULL;
- break;
- default:
- abort();
- }
- sk_GENERAL_NAME_push(gens, gen);
- gen = NULL;
- }
- if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
- goto out;
- ret = 1;
+{
+ int ret = 0;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ASN1_IA5STRING *ia5 = NULL;
+ va_list ap;
+ va_start(ap, crt);
+ gens = sk_GENERAL_NAME_new_null();
+ if (gens == NULL)
+ goto out;
+ while (1) {
+ int type;
+ const char *name;
+ type = va_arg(ap, int);
+ if (type == 0)
+ break;
+ name = va_arg(ap, const char *);
+
+ gen = GENERAL_NAME_new();
+ if (gen == NULL)
+ goto out;
+ ia5 = ASN1_IA5STRING_new();
+ if (ia5 == NULL)
+ goto out;
+ if (!ASN1_STRING_set(ia5, name, -1))
+ goto out;
+ switch (type) {
+ case GEN_EMAIL:
+ case GEN_DNS:
+ GENERAL_NAME_set0_value(gen, type, ia5);
+ ia5 = NULL;
+ break;
+ default:
+ abort();
+ }
+ sk_GENERAL_NAME_push(gens, gen);
+ gen = NULL;
+ }
+ if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
+ goto out;
+ ret = 1;
out:
- ASN1_IA5STRING_free(ia5);
- GENERAL_NAME_free(gen);
- GENERAL_NAMES_free(gens);
- va_end(ap);
- return ret;
- }
+ ASN1_IA5STRING_free(ia5);
+ GENERAL_NAME_free(gen);
+ GENERAL_NAMES_free(gens);
+ va_end(ap);
+ return ret;
+}
static int set_cn1(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_commonName, name, 0);
- }
-
+{
+ return set_cn(crt, NID_commonName, name, 0);
+}
static int set_cn_and_email(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_commonName, name,
- NID_pkcs9_emailAddress, "dummy@example.com", 0);
- }
+{
+ return set_cn(crt, NID_commonName, name,
+ NID_pkcs9_emailAddress, "dummy@example.com", 0);
+}
static int set_cn2(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_commonName, "dummy value",
- NID_commonName, name, 0);
- }
+{
+ return set_cn(crt, NID_commonName, "dummy value",
+ NID_commonName, name, 0);
+}
static int set_cn3(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_commonName, name,
- NID_commonName, "dummy value", 0);
- }
+{
+ return set_cn(crt, NID_commonName, name,
+ NID_commonName, "dummy value", 0);
+}
static int set_email1(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
- }
+{
+ return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
+}
static int set_email2(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
- NID_pkcs9_emailAddress, name, 0);
- }
+{
+ return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
+ NID_pkcs9_emailAddress, name, 0);
+}
static int set_email3(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_pkcs9_emailAddress, name,
- NID_pkcs9_emailAddress, "dummy@example.com", 0);
- }
+{
+ return set_cn(crt, NID_pkcs9_emailAddress, name,
+ NID_pkcs9_emailAddress, "dummy@example.com", 0);
+}
static int set_email_and_cn(X509 *crt, const char *name)
- {
- return set_cn(crt, NID_pkcs9_emailAddress, name,
- NID_commonName, "www.example.org", 0);
- }
+{
+ return set_cn(crt, NID_pkcs9_emailAddress, name,
+ NID_commonName, "www.example.org", 0);
+}
static int set_altname_dns(X509 *crt, const char *name)
- {
- return set_altname(crt, GEN_DNS, name, 0);
- }
+{
+ return set_altname(crt, GEN_DNS, name, 0);
+}
static int set_altname_email(X509 *crt, const char *name)
- {
- return set_altname(crt, GEN_EMAIL, name, 0);
- }
-
-struct set_name_fn
- {
- int (*fn)(X509 *, const char *);
- const char *name;
- int host;
- int email;
- };
-
-static const struct set_name_fn name_fns[] =
- {
- {set_cn1, "set CN", 1, 0},
- {set_cn2, "set CN", 1, 0},
- {set_cn3, "set CN", 1, 0},
- {set_cn_and_email, "set CN", 1, 0},
- {set_email1, "set emailAddress", 0, 1},
- {set_email2, "set emailAddress", 0, 1},
- {set_email3, "set emailAddress", 0, 1},
- {set_email_and_cn, "set emailAddress", 0, 1},
- {set_altname_dns, "set dnsName", 1, 0},
- {set_altname_email, "set rfc822Name", 0, 1},
- {NULL, NULL, 0, 0},
- };
+{
+ return set_altname(crt, GEN_EMAIL, name, 0);
+}
+
+struct set_name_fn {
+ int (*fn) (X509 *, const char *);
+ const char *name;
+ int host;
+ int email;
+};
+
+static const struct set_name_fn name_fns[] = {
+ {set_cn1, "set CN", 1, 0},
+ {set_cn2, "set CN", 1, 0},
+ {set_cn3, "set CN", 1, 0},
+ {set_cn_and_email, "set CN", 1, 0},
+ {set_email1, "set emailAddress", 0, 1},
+ {set_email2, "set emailAddress", 0, 1},
+ {set_email3, "set emailAddress", 0, 1},
+ {set_email_and_cn, "set emailAddress", 0, 1},
+ {set_altname_dns, "set dnsName", 1, 0},
+ {set_altname_email, "set rfc822Name", 0, 1},
+ {NULL, NULL, 0, 0},
+};
static X509 *make_cert(void)
- {
- X509 *ret = NULL;
- X509 *crt = NULL;
- X509_NAME *issuer = NULL;
- crt = X509_new();
- if (crt == NULL)
- goto out;
- if (!X509_set_version(crt, 3))
- goto out;
- ret = crt;
- crt = NULL;
+{
+ X509 *ret = NULL;
+ X509 *crt = NULL;
+ X509_NAME *issuer = NULL;
+ crt = X509_new();
+ if (crt == NULL)
+ goto out;
+ if (!X509_set_version(crt, 3))
+ goto out;
+ ret = crt;
+ crt = NULL;
out:
- X509_NAME_free(issuer);
- return ret;
- }
+ X509_NAME_free(issuer);
+ return ret;
+}
static int errors;
static void check_message(const struct set_name_fn *fn, const char *op,
- const char *nameincert, int match, const char *name)
- {
- char msg[1024];
- if (match < 0)
- return;
- BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
- fn->name, op, nameincert,
- match ? "matches" : "does not match", name);
- if (is_exception(msg))
- return;
- puts(msg);
- ++errors;
- }
+ const char *nameincert, int match, const char *name)
+{
+ char msg[1024];
+ if (match < 0)
+ return;
+ BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
+ fn->name, op, nameincert,
+ match ? "matches" : "does not match", name);
+ if (is_exception(msg))
+ return;
+ puts(msg);
+ ++errors;
+}
static void run_cert(X509 *crt, const char *nameincert,
- const struct set_name_fn *fn)
- {
- const char *const *pname = names;
- while (*pname)
- {
- int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
- size_t namelen = strlen(*pname);
- char *name = malloc(namelen);
- int match, ret;
- memcpy(name, *pname, namelen);
-
- ret = X509_check_host(crt, name, namelen, 0, NULL);
- match = -1;
- if (ret < 0)
- {
- fprintf(stderr, "internal error in X509_check_host");
- ++errors;
- }
- else if (fn->host)
- {
- if (ret == 1 && !samename)
- match = 1;
- if (ret == 0 && samename)
- match = 0;
- }
- else if (ret == 1)
- match = 1;
- check_message(fn, "host", nameincert, match, *pname);
-
- ret = X509_check_host(crt, name, namelen,
- X509_CHECK_FLAG_NO_WILDCARDS, NULL);
- match = -1;
- if (ret < 0)
- {
- fprintf(stderr, "internal error in X509_check_host");
- ++errors;
- }
- else if (fn->host)
- {
- if (ret == 1 && !samename)
- match = 1;
- if (ret == 0 && samename)
- match = 0;
- }
- else if (ret == 1)
- match = 1;
- check_message(fn, "host-no-wildcards",
- nameincert, match, *pname);
-
- ret = X509_check_email(crt, name, namelen, 0);
- match = -1;
- if (fn->email)
- {
- if (ret && !samename)
- match = 1;
- if (!ret && samename && strchr(nameincert, '@') != NULL)
- match = 0;
- }
- else if (ret)
- match = 1;
- check_message(fn, "email", nameincert, match, *pname);
- ++pname;
- free(name);
- }
- }
-
-int
-main(void)
- {
- CRYPTO_library_init();
-
- const struct set_name_fn *pfn = name_fns;
- while (pfn->name) {
- const char *const *pname = names;
- while (*pname)
- {
- X509 *crt = make_cert();
- if (crt == NULL)
- {
- fprintf(stderr, "make_cert failed\n");
- return 1;
- }
- if (!pfn->fn(crt, *pname))
- {
- fprintf(stderr, "X509 name setting failed\n");
- return 1;
- }
- run_cert(crt, *pname, pfn);
- X509_free(crt);
- ++pname;
- }
- ++pfn;
- }
- if (errors == 0) {
- printf("PASS\n");
- }
- return errors > 0 ? 1 : 0;
- }
+ const struct set_name_fn *fn)
+{
+ const char *const *pname = names;
+ while (*pname) {
+ int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
+ size_t namelen = strlen(*pname);
+ char *name = malloc(namelen);
+ int match, ret;
+ memcpy(name, *pname, namelen);
+
+ ret = X509_check_host(crt, name, namelen, 0, NULL);
+ match = -1;
+ if (ret < 0) {
+ fprintf(stderr, "internal error in X509_check_host");
+ ++errors;
+ } else if (fn->host) {
+ if (ret == 1 && !samename)
+ match = 1;
+ if (ret == 0 && samename)
+ match = 0;
+ } else if (ret == 1)
+ match = 1;
+ check_message(fn, "host", nameincert, match, *pname);
+
+ ret = X509_check_host(crt, name, namelen,
+ X509_CHECK_FLAG_NO_WILDCARDS, NULL);
+ match = -1;
+ if (ret < 0) {
+ fprintf(stderr, "internal error in X509_check_host");
+ ++errors;
+ } else if (fn->host) {
+ if (ret == 1 && !samename)
+ match = 1;
+ if (ret == 0 && samename)
+ match = 0;
+ } else if (ret == 1)
+ match = 1;
+ check_message(fn, "host-no-wildcards", nameincert, match, *pname);
+
+ ret = X509_check_email(crt, name, namelen, 0);
+ match = -1;
+ if (fn->email) {
+ if (ret && !samename)
+ match = 1;
+ if (!ret && samename && strchr(nameincert, '@') != NULL)
+ match = 0;
+ } else if (ret)
+ match = 1;
+ check_message(fn, "email", nameincert, match, *pname);
+ ++pname;
+ free(name);
+ }
+}
+
+int main(void)
+{
+ CRYPTO_library_init();
+
+ const struct set_name_fn *pfn = name_fns;
+ while (pfn->name) {
+ const char *const *pname = names;
+ while (*pname) {
+ X509 *crt = make_cert();
+ if (crt == NULL) {
+ fprintf(stderr, "make_cert failed\n");
+ return 1;
+ }
+ if (!pfn->fn(crt, *pname)) {
+ fprintf(stderr, "X509 name setting failed\n");
+ return 1;
+ }
+ run_cert(crt, *pname, pfn);
+ X509_free(crt);
+ ++pname;
+ }
+ ++pfn;
+ }
+ if (errors == 0) {
+ printf("PASS\n");
+ }
+ return errors > 0 ? 1 : 0;
+}