Compare commits

..

282 Commits

Author SHA1 Message Date
David Benjamin 6f04ac1c4d Suppress C4701 on 2661 branch.
p256-x86_64.c can't build in MSVC 2013 in debug mode along because of
ecp_nistz256_points_mul's very awkward calling convention (at least one of
g_scalar/p_scalar must be non-NULL).

MSVC 2015 seems to be okay with it, but this branch doesn't build with 2015 yet
and is currently used by gRPC folks. Later they'll move to a branch that builds
with 2015, so the issue won't be pressing. Though the EC_METHOD mul calling
convention is still a little screwy.

The simplest immediate option is to suppress the warning on this branch. The
warning will be left alive on master (which now requires 2015 anyway), but we
should add release-mode builders.

Change-Id: Ia9274887f49dbe8f53c44c046b6f1323425702b0
Reviewed-on: https://boringssl-review.googlesource.com/7987
Reviewed-by: Adam Langley <agl@google.com>
2016-05-19 17:36:58 +00:00
David Benjamin c880e42ba1 ASN1_get_object should not accept large universal tags.
The high bits of the type get used for the V_ASN1_NEG bit, so when used with
ASN1_ANY/ASN1_TYPE, universal tags become ambiguous. This allows one to create
a negative zero, which should be impossible. Impose an upper bound on universal
tags accepted by crypto/asn1 and add a test.

BUG=590615

Change-Id: I363e01ebfde621c8865101f5bcbd5f323fb59e79
Reviewed-on: https://boringssl-review.googlesource.com/7238
Reviewed-by: Adam Langley <agl@google.com>
2016-03-03 15:14:15 -05:00
Adam Langley c02d05fe19 Fix encoding bug in i2c_ASN1_INTEGER
(Imported from upstream's 3661bb4e7934668bd99ca777ea8b30eedfafa871.)

Fix bug where i2c_ASN1_INTEGER mishandles zero if it is marked as
negative.

Thanks to Huzaifa Sidhpurwala <huzaifas@redhat.com> and Hanno Böck
<hanno@hboeck.de> for reporting this issue.

BUG=590615

Change-Id: I8959e8ae01510a5924862a3f353be23130eee554
Reviewed-on: https://boringssl-review.googlesource.com/7199
Reviewed-by: David Benjamin <davidben@google.com>
2016-03-03 15:14:14 -05:00
Brian Smith 6d49157929 Restore |xmm7| correctly on Win64 in aesni-gcm-x86_64.
See OpenSSL df057ea6c8a20e4babc047689507dfafde59ffd6.

Change-Id: Ife10dc13ca335cd51434d7769ff85c6929f10226
Reviewed-on: https://boringssl-review.googlesource.com/7172
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-18 15:50:46 +00:00
Adam Langley e976e4349d Don't read uninitialised data for short session IDs.
While it's always safe to read |SSL_MAX_SSL_SESSION_ID_LENGTH| bytes
from an |SSL_SESSION|'s |session_id| array, the hash function would do
so with without considering if all those bytes had been written to.

This change checks |session_id_length| before possibly reading
uninitialised memory. Since the result of the hash function was already
attacker controlled, and since a lookup of a short session ID will
always fail, it doesn't appear that this is anything more than a clean
up.

BUG=586800

Change-Id: I5f59f245b51477d6d4fa2cdc20d40bb6b4a3eae7
Reviewed-on: https://boringssl-review.googlesource.com/7150
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-18 15:45:48 +00:00
David Benjamin f48fcaf901 Have fuzz/cert.cc also call X509_get_pubkey.
crypto/x509 parses the SPKI on-demand, so we weren't actually exercising the
SPKI code.

Change-Id: I2e16045bd35dbe04d4b8d8b45939c8885e09a550
Reviewed-on: https://boringssl-review.googlesource.com/7161
Reviewed-by: Adam Langley <agl@google.com>
2016-02-18 00:10:15 +00:00
David Benjamin de94238217 Fix SSL_get_{read,write}_sequence.
I switched up the endianness. Add some tests to make sure those work right.

Also tweak the DTLS semantics. SSL_get_read_sequence should return the highest
sequence number received so far. Include the epoch number in both so we don't
need a second API for it.

Change-Id: I9901a1665b41224c46fadb7ce0b0881dcb466bcc
Reviewed-on: https://boringssl-review.googlesource.com/7141
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 22:05:29 +00:00
David Benjamin d3a49953d8 Add missing " in comment.
Change-Id: If33d3a11a0b48403fc009688b9300c92e5494d94
Reviewed-on: https://boringssl-review.googlesource.com/7160
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 21:17:26 +00:00
David Benjamin f4ef9b517e otherPrimeInfos is not optional in version 1 RSAPrivateKeys.
Currently, we correctly refuse to parse version 0 multi-prime keys, but we
still parse version 1 two-prime keys. Both should be rejected.

I missed an additional clause in the spec originally. It seems otherPrimeInfos
is marked OPTIONAL not because it is actually optional, but because they wanted
the two RSAPrivateKey forms to share one definition. The prose rules following
the definition imply that otherPrimeInfos' presence is entirely determined by
the version:

    * version is the version number, for compatibility with future
      revisions of this document.  It shall be 0 for this version of the
      document, unless multi-prime is used, in which case it shall be 1.

            Version ::= INTEGER { two-prime(0), multi(1) }
               (CONSTRAINED BY
               {-- version must be multi if otherPrimeInfos present --})

and:

    * otherPrimeInfos contains the information for the additional primes
      r_3, ..., r_u, in order.  It shall be omitted if version is 0 and
      shall contain at least one instance of OtherPrimeInfo if version
      is 1.

Change-Id: I458232a2e20ed68fddcc39c4c45333f33441f70b
Reviewed-on: https://boringssl-review.googlesource.com/7143
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 18:28:05 +00:00
David Benjamin 9cd7fbdac6 Remove support for blocks in file_test.h.
That was probably more complexity than we needed. Nothing uses it
anymore, now that getting to the PKCS#8 logic isn't especially tedious.

Change-Id: I4f0393b1bd75e71664f65e3722c14c483c13c5cf
Reviewed-on: https://boringssl-review.googlesource.com/6867
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 17:24:57 +00:00
David Benjamin e30a09e604 Implement new PKCS#8 parsers.
As with SPKI parsers, the intent is make EVP_PKEY capture the key's
constraints in full fidelity, so we'd have to add new types or store the
information in the underlying key object if people introduce variant key
types with weird constraints on them.

Note that because PKCS#8 has a space for arbitrary attributes, this
parser must admit a hole. I'm assuming for now that we don't need an API
that enforces no attributes and just ignore trailing data in the
structure for simplicity.

BUG=499653

Change-Id: I6fc641355e87136c7220f5d7693566d1144a68e8
Reviewed-on: https://boringssl-review.googlesource.com/6866
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 17:24:10 +00:00
David Benjamin 440f103771 Remove support for mis-encoded PKCS#8 DSA keys.
Previously, OpenSSL supported many different DSA PKCS#8 encodings. Only
support the standard format. One of the workaround formats (SEQUENCE of
private key and public key) seems to be a workaround for an old Netscape
bug. From inspection, NSS seems to have fixed this from the first open
source commit.

Change-Id: I1e097b675145954b4d7a0bed8733e5a25c25fd8e
Reviewed-on: https://boringssl-review.googlesource.com/7074
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 16:32:31 +00:00
David Benjamin 239a0abfd5 Slightly simplify and deprecate i2d_{Public,Private}Key.
There are all the type-specific serializations rather than something
tagged with a type. i2d_PrivateKey's PKCS#8 codepath was unreachable
because every EVP_PKEY type has an old_priv_encode function.

To prune EVP_PKEY_ASN1_METHOD further, replace i2d_PrivateKey into a
switch case so we don't need to keep old_priv_encode around. This cuts
down on a case of outside modules reaching into crypto/evp method
tables.

Change-Id: I30db2eed836d560056ba9d1425b960d0602c3cf2
Reviewed-on: https://boringssl-review.googlesource.com/6865
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 16:31:26 +00:00
David Benjamin 32fdc512ca Remove param_decode and param_encode EVP_PKEY hooks.
They're only used by a pair of PEM functions, which are never used.

BUG=499653

Change-Id: I89731485c66ca328c634efbdb7e182a917f2a963
Reviewed-on: https://boringssl-review.googlesource.com/6863
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 16:30:29 +00:00
David Benjamin 68772b31b0 Implement new SPKI parsers.
Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each
with different ways to set signature parameters. SPKIs themselves can
get complex with id-RSASSA-PSS keys which come with various constraints
in the key parameters. This suggests we want a common in-library
representation of an SPKI.

This adds two new functions EVP_parse_public_key and
EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and
implements X509_PUBKEY functions with them. EVP_PKEY seems to have been
intended to be able to express the supported SPKI types with
full-fidelity, so these APIs will continue this.

This means future support for id-RSASSA-PSS would *not* repurpose
EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies
acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and
the data pointer would be some (exposed, so the caller may still check
key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX
implementation would enforce the key constraints. If RSA_PSS_KEY would
later need its own API, that code would move there, but that seems
unlikely.

Ideally we'd have a 1:1 correspondence with key OID, although we may
have to fudge things if mistakes happen in standardization. (Whether or
not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate
EVP_PKEY type.)

DSA parsing hooks are still implemented, missing parameters and all for
now. This isn't any worse than before.

Decoupling from the giant crypto/obj OID table will be a later task.

BUG=522228

Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c
Reviewed-on: https://boringssl-review.googlesource.com/6861
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 16:28:07 +00:00
David Benjamin 2dc469e066 Remove dead header file.
There's nothing in here.

Change-Id: I3a501389e7e237b2e6907f27d2eb788a298d6c03
Reviewed-on: https://boringssl-review.googlesource.com/6877
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 01:34:15 +00:00
David Benjamin df98a7ad3a Reimplement DSA_size without crypto/asn1.
BUG=499653

Change-Id: I16963fb198609d7fc0df6c57923cda3e13350753
Reviewed-on: https://boringssl-review.googlesource.com/6875
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 01:02:51 +00:00
David Benjamin fda22a7573 Reimplement DSA parsing logic with crypto/asn1.
Functions which lose object reuse and need auditing:
- d2i_DSA_SIG
- d2i_DSAPublicKey
- d2i_DSAPrivateKey
- d2i_DSAparams

BUG=499653

Change-Id: I1cc2ae10e1e77eb57da3a858ac8734a95715ce4b
Reviewed-on: https://boringssl-review.googlesource.com/7022
Reviewed-by: Adam Langley <agl@google.com>
2016-02-17 00:26:01 +00:00
David Benjamin 3cadf63c68 Remove DSA write_params.
This imports upstream's ea6b07b54c1f8fc2275a121cdda071e2df7bd6c1 along
with a bugfix in 987157f6f63fa70dbeffca3c8bc62f26e9767ff2.

In an SPKI, a DSA key is only an INTEGER, with the group information in
the AlgorithmIdentifier. But a standalone DSAPublicKey is more complex
(and apparently made up by OpenSSL). OpenSSL implemented this with a
write_params boolean and making DSAPublicKey a CHOICE.

Instead, have p_dsa_asn1.c encode an INTEGER directly. d2i_DSAPublicKey
only parses the standalone form. (That code will be replaced later, but
first do this in preparation for rewriting the DSA ASN.1 code.)

Change-Id: I6fbe298d2723b9816806e9c196c724359b9ffd63
Reviewed-on: https://boringssl-review.googlesource.com/7021
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 23:54:38 +00:00
David Benjamin 985da09340 Remove flags field from EC_KEY.
It doesn't do anything.

Change-Id: Ifcc2c824faf6012d2a442208b8204a32e141a650
Reviewed-on: https://boringssl-review.googlesource.com/7073
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 23:51:53 +00:00
David Benjamin 2f6410ba4e Rewrite ECPrivateKey serialization.
Functions which lose object reuse and need auditing:
- d2i_ECParameters
- d2i_ECPrivateKey

This adds a handful of bytestring-based APIs to handle EC key
serialization. Deprecate all the old serialization APIs. Notes:

- An EC_KEY has additional state that controls its encoding, enc_flags
  and conv_form. conv_form is left alone, but enc_flags in the new API
  is an explicit parameter.

- d2i_ECPrivateKey interpreted its T** argument unlike nearly every
  other d2i function. This is an explicit EC_GROUP parameter in the new
  function.

- The new specified curve code is much stricter and should parse enough
  to uniquely identify the curve.

- I've not bothered with a new version of i2d_ECParameters. It just
  writes an OID. This may change later when decoupling from the giant
  OID table.

- Likewise, I've not bothered with new APIs for the public key since the
  EC_POINT APIs should suffice.

- Previously, d2i_ECPrivateKey would not call EC_KEY_check_key and it
  was possible for the imported public and private key to mismatch. It
  now calls it.

BUG=499653

Change-Id: I30b4dd2841ae76c56ab0e1808360b2628dee0615
Reviewed-on: https://boringssl-review.googlesource.com/6859
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 23:51:09 +00:00
David Benjamin 666973b8e9 Add tests for EC keys with specified curves.
In c0d9484902, we had to add support for
recognizing specified versions of named curves. I believe the motivation
was an ECPrivateKey encoded by OpenSSL without the EC_KEY's asn1_flag
set to OPENSSL_EC_NAMED_CURVE. Annoyingly, it appears OpenSSL's API
defaulted to the specified form while the tool defaulted to the named
form.

Add tests for this at the ECPrivateKey and the PKCS#8 level. The latter
was taken from Chromium's ec_private_key_unittest.cc which was the
original impetus for this.

Change-Id: I53a80c842c3fc9598f2e0ee7bf2d86b2add9e6c4
Reviewed-on: https://boringssl-review.googlesource.com/7072
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 21:51:32 +00:00
Adam Langley 815b12ece6 ed25519: Don't negate output when decoding.
The function |ge_frombytes_negate_vartime|, as the name suggests,
negates its output. This change converts it to |ge_frombytes_vartime|
and, instead, does the negation explicitly when verifying signatures.
The latter function is more generally useful.

Change-Id: I465f8bdf5edb101a80ab1835909ae0ff41d3e295
Reviewed-on: https://boringssl-review.googlesource.com/7142
Reviewed-by: Arnar Birgisson <arnarb@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-16 21:07:44 +00:00
David Benjamin bd42603943 Add a convenience function for i2d compatibility wrappers.
An i2d compatibility function is rather long, so add CBB_finish_i2d for
part of it. It takes a CBB as input so only a 'marshal' function is
needed, rather than a 'to_bytes' one.

Also replace the *inp d2i update pattern with a slightly shorter one.

Change-Id: Ibb41059c9532f6a8ce33460890cc1afe26adc97c
Reviewed-on: https://boringssl-review.googlesource.com/6868
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 19:40:53 +00:00
David Benjamin 375124b162 Parse BER for PKCS#12 more accurately.
CBS_asn1_ber_to_der currently uses heuristics because implicitly-tagged
constructed strings in BER are ambiguous with implicitly-tagged sequences. It's
not possible to convert BER to DER without knowing the schema.

Fortunately, implicitly tagged strings don't appear often so instead split the
job up: CBS_asn1_ber_to_der fixes indefinite-length elements and constructed
strings it can see. Implicitly-tagged strings it leaves uncoverted, but they
will only nest one level down (because BER kindly allows one to nest
constructed strings arbitrarily!).

CBS_get_asn1_implicit_string then performs the final concatenation at parse
time. This isn't much more complex and lets us parse BER more accurately and
also reject a number of mis-encoded values (e.g. constructed INTEGERs are not a
thing) we'd previously let through. The downside is the post-conversion parsing
code must be aware of this limitation of CBS_asn1_ber_to_der. Fortunately,
there's only one implicitly-tagged string in our PKCS#12 code.

(In the category of things that really really don't matter, but I had spare
cycles and the old BER converter is weird.)

Change-Id: Iebdd13b08559fa158b308ef83a5bb07bfdf80ae8
Reviewed-on: https://boringssl-review.googlesource.com/7052
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 19:32:50 +00:00
David Benjamin fb974e6cb3 Use initializer lists to specify cipher rule tests.
This is significantly less of a nuisance than having to explicitly type out
kRule5, kExpected5.

Change-Id: I61820c26a159c71e09000fbe0bf91e30da42205e
Reviewed-on: https://boringssl-review.googlesource.com/7000
Reviewed-by: Adam Langley <agl@google.com>
2016-02-16 18:42:07 +00:00
Brian Smith 894a47df24 Clarify some confusing casts involving |size_t|.
Change-Id: I7af2c87fe6e7513aa2603d5e845a4db87ab14fcc
Reviewed-on: https://boringssl-review.googlesource.com/7101
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-12 15:37:15 +00:00
Brian Smith 11676a7399 Use |kSizeTWithoutLower4Bits| in crypto/modes/gcm.c.
Some instances were missed in eca509c8da.

Change-Id: I53a6bd944fbf0df439b8e6f9db761f61d7237ba2
Reviewed-on: https://boringssl-review.googlesource.com/7103
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-11 22:08:42 +00:00
Brian Smith 5ba06897be Don't cast |OPENSSL_malloc|/|OPENSSL_realloc| result.
C has implicit conversion of |void *| to other pointer types so these
casts are unnecessary. Clean them up to make the code easier to read
and to make it easier to find dangerous casts.

Change-Id: I26988a672e8ed4d69c75cfbb284413999b475464
Reviewed-on: https://boringssl-review.googlesource.com/7102
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-11 22:07:56 +00:00
Brian Smith 46a4d6d705 Remove out-of-date and misleading comment in |bn_blinding_st|.
I guess the comment "just a reference" was intended to mean that the
|mod| member is a weak reference to a |BIGNUM| owned by something else.
However, it is actually owned by the |bn_blinding_st|, as one can see
by reading |BN_BLINDING_new| and |BN_BLINDING_free|.

Change-Id: If2a681fc9d9db536170e0efb11fdab93e4f0baba
Reviewed-on: https://boringssl-review.googlesource.com/7112
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-11 22:01:14 +00:00
David Benjamin 3ab3e3db6e Mark ARM assembly globals hidden uniformly in arm-xlate.pl.
We'd manually marked some of them hidden, but missed some. Do it in the perlasm
driver instead since we will never expose an asm symbol directly. This reduces
some of our divergence from upstream on these files (and indeed we'd
accidentally lose some .hiddens at one point).

BUG=586141

Change-Id: Ie1bfc6f38ba73d33f5c56a8a40c2bf1668562e7e
Reviewed-on: https://boringssl-review.googlesource.com/7140
Reviewed-by: Adam Langley <agl@google.com>
2016-02-11 17:28:03 +00:00
David Benjamin 5acc423517 Add a CONTRIBUTING.md file.
Change-Id: I4e1ed0aaddf4dc516a81155ef62dba138f8495ae
Reviewed-on: https://boringssl-review.googlesource.com/7120
Reviewed-by: Adam Langley <agl@google.com>
2016-02-10 21:38:19 +00:00
nmittler 042e8f721a Updating BUILDING.md for windows.
Updating the Perl docs to describe behavior of Strawberry Perl and possible
interaction with CMake on Windows.

Also adding a few other links and instructions for using CMake/Ninja to build
release mode with position independent code, since this seems generally useful.

Change-Id: I616c0d267da749fe90673bc9e8bde9ec181fec25
Reviewed-on: https://boringssl-review.googlesource.com/7113
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-10 17:42:36 +00:00
Brian Smith 642b0b825e Remove unused bits of RSA blinding code.
The |_ex| versions of these functions are unnecessary because when they
are used, they are always passed |NULL| for |r|, which is what the
non-|_ex| versions do. Just use the non-|_ex| versions instead and
remove the |_ex| versions.

Also, drop the unused flags mechanism.

Change-Id: Ida4cb5a2d4c89d9cd318e06f71867aea98408d0d
Reviewed-on: https://boringssl-review.googlesource.com/7110
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-09 16:45:13 +00:00
Brian Smith a051bdd6cd Remove dead non-|BN_ULLONG|, non-64-bit-MSVC code in crypto/bn.
It is always the case that either |BN_ULLONG| is defined or
|BN_UMULT_LOHI| is defined because |BN_ULLONG| is defined everywhere
except 64-bit MSVC, and BN_UMULT_LOHI is defined for 64-bit MSVC.

Change-Id: I85e5d621458562501af1af65d587c0b8d937ba3b
Reviewed-on: https://boringssl-review.googlesource.com/7044
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-09 16:21:41 +00:00
Brian Smith 767e1210e0 Remove unused Simics code in crypto/bn/asm/x86_64-gcc.c.
Change-Id: If9c5031855c0acfafb73caba169e146f0e16f706
Reviewed-on: https://boringssl-review.googlesource.com/7093
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 23:41:47 +00:00
Brian Smith b121a26736 Remove unused |ec_GFp_simple_group_check_discriminant|.
Change-Id: I995a445fea1de7f85ec917694abb8273a82339d3
Reviewed-on: https://boringssl-review.googlesource.com/7092
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 18:33:09 +00:00
Brian Smith 4862b3b93c Remove useless and out-of-date comments in crypto/ec/internal.h.
Change-Id: Ia80372316e67822d44b8b90f7983f3ef773ed0fd
Reviewed-on: https://boringssl-review.googlesource.com/7091
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 18:32:20 +00:00
Brian Smith fce7604350 Remove duplicative ECC |group_init| and |group_set_curve| methods.
|a_is_minus_3| is calculated in |ec_GFp_simple_group_set_curve|, so
the custom |group_init| functions are unnecessary. Just as in
commit 9f1f04f313, it is never the case
that custom parameters are passed to the |group_set_curve| method for
these curves.

Change-Id: I18a38b104bc332e44cc2053c465cf234f4c5163b
Reviewed-on: https://boringssl-review.googlesource.com/7090
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 18:31:46 +00:00
Brian Smith aadf1ee77f Minimize the scope of the |BN_*_SIZE_*| constants.
mul.c is the only file that uses these values.

Change-Id: I50a685cbff0f26357229e742f42e014434e9cebe
Reviewed-on: https://boringssl-review.googlesource.com/7061
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 18:28:31 +00:00
Brian Smith 8c5ea1338a Remove unused |bn_mul_low_normal| and related #defines.
Change-Id: I2e3745f5dd5132a48dcbf472bca3638324dfc7a3
Reviewed-on: https://boringssl-review.googlesource.com/7060
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-08 18:25:23 +00:00
David Benjamin 2c71ce135c Update some URLs in BUILDING.md.
Change-Id: Ic7aa22b10d2d69bdc3a548273640574203e93012
Reviewed-on: https://boringssl-review.googlesource.com/7071
Reviewed-by: Adam Langley <agl@google.com>
2016-02-08 18:12:56 +00:00
David Benjamin 6b34d54945 Prefer MSVC over GCC if both are in %PATH%.
Notably, putting Strawberry Perl in %PATH% will usually end up putting a copy
of gcc in %PATH%, which trips up people trying to build on Windows.

This is arguably misusing the variable (normally set by the generator), but it
should work.

Change-Id: I13a011eb33688ae928a56cce266edd2759a3cb32
Reviewed-on: https://boringssl-review.googlesource.com/7070
Reviewed-by: Adam Langley <agl@google.com>
2016-02-08 18:12:36 +00:00
David Benjamin 089cba090c No-op change to kick the bots again.
Infra fixed some stuff. Let's try again.

Change-Id: Ib5f3d7e94091655ee5893ae19e5e0bfbfe888b3d
2016-02-05 21:44:56 -05:00
Brian Smith f98be21fad Remove dead platform-specific code in |BN_div|.
It is always the case that |BN_ULLONG| is defined or we're building for
64-bit MSVC. Lots of code is trying to handle impossible cases where
neither of those is true.

Change-Id: Ie337adda1dfb453843c6e0999807dfa1afb1ed89
Reviewed-on: https://boringssl-review.googlesource.com/7043
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-05 23:12:11 +00:00
David Benjamin a37fc70175 Another no-op change.
I did that too quickly. The machines hadn't picked up the new recipe yet.

Change-Id: Ie63c8f022049ba72106b0a31bc35b20819514707
2016-02-05 17:59:15 -05:00
David Benjamin fcde5aa74d No-op change to kick the bots.
Windows build failures seem to have been a CMake statefulness problem. Recipes
were changed to do clean builds each run.

Change-Id: Id5aefa53aead7e82e095d7dccbf88ad89a678c62
2016-02-05 17:52:28 -05:00
Brian Smith 926f2194df Enable MSVC 128-bit multiplication regardless of OPENSSL_NO_ASM.
This allows much code to be subsequently simplified and removed.

Change-Id: I0ac256957c6eae9f35a70508bd454cb44f3f8653
Reviewed-on: https://boringssl-review.googlesource.com/7042
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-05 00:30:34 +00:00
David Benjamin 11aac10987 Fix theoretical memory leak on malloc error in CBS_asn1_ber_to_der.
On failure, CBB_finish doesn't call CBB_cleanup. Also chain more of the ||s
together now that CBB_cleanup after failed CBB_init is legal.

(I don't think this is actually reachable because the CBB is guaranteed to be
flushed by this point.)

Change-Id: Ib16a0a185f15e13675ac2550c5e8e0926ceb7957
Reviewed-on: https://boringssl-review.googlesource.com/7051
Reviewed-by: Adam Langley <agl@google.com>
2016-02-04 17:23:28 +00:00
Brian Smith 168297e870 Test |ECDSA_SIG_to_bytes| using the P-521 order size, not 512-bits.
There was a test for 512 bit orders but not one for 521-bit orders.
Test 521-bit orders instead.

Change-Id: I61a76d02637ca55d8ae21834085311dd84fd870f
Reviewed-on: https://boringssl-review.googlesource.com/7011
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-03 23:26:42 +00:00
Adam Langley d057454f90 Changes to support node.js's use of PKCS#12.
node.js uses a memory BIO in the wrong mode which, for now, we work
around. It also passes in NULL (rather than empty) strings and a
non-NULL out-arg for |d2i_PKCS12_bio|.

Change-Id: Ib565b4a202775bb32fdcb76db8a4e8c54268c052
Reviewed-on: https://boringssl-review.googlesource.com/7012
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 19:21:59 +00:00
David Benjamin e66148a18f Drop dh->q in bssl_shim when -use-sparse-dh-prime is passed.
Otherwise it still thinks this is an RFC 5114 prime and kicks in the (now
incorrect) validity check.

Change-Id: Ie78514211927f1f2d2549958621cb7896f68b5ce
Reviewed-on: https://boringssl-review.googlesource.com/7050
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 19:18:27 +00:00
David Benjamin 6014ea6248 Add EC_POINT_point2cbb.
This slightly simplifies the SSL_ECDH code and will be useful later on
in reimplementing the key parsing logic.

Change-Id: Ie41ea5fd3a9a734b3879b715fbf57bd991e23799
Reviewed-on: https://boringssl-review.googlesource.com/6858
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 19:04:33 +00:00
Adam Langley dd31c4eba2 Update some comments in bn_test.c in light of acb24518.
Change acb24518 renamed some functions, but there were some dangling
references in bn_test.c. Thanks to Brian Smith for noticing.

This change has no semantic effect.

Change-Id: Id149505090566583834be3abce2cee28b8c248e2
Reviewed-on: https://boringssl-review.googlesource.com/7040
Reviewed-by: David Benjamin <davidben@google.com>
2016-02-02 18:22:19 +00:00
David Benjamin 47ebec1210 Validate DH public keys for RFC 5114 groups.
This is CVE-2016-0701 for OpenSSL, reported by Antonio Sanso. It is a no-op for
us as we'd long removed SSL_OP_DH_SINGLE_USE and static DH cipher suites. (We
also do not parse or generate X9.42 DH parameters.)

However, we do still have the APIs which return RFC 5114 groups, so we should
perform the necessary checks in case later consumers reuse keys.

Unlike groups we generate, RFC 5114 groups do not use "safe primes" and have
many small subgroups. In those cases, the subprime q is available. Before using
a public key, ensure its order is q by checking y^q = 1 (mod p). (q is assumed
to be prime and the existing range checks ensure y is not 1.)

(Imported from upstream's 878e2c5b13010329c203f309ed0c8f2113f85648 and
75374adf8a6ff69d6718952121875a491ed2cd29, but with some bugs fixed. See
RT4278.)

Change-Id: Ib18c3e84819002fa36a127ac12ca00ee33ea018a
Reviewed-on: https://boringssl-review.googlesource.com/7001
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 16:44:38 +00:00
David Benjamin 43946d44ae Update references to the extended master secret draft.
It's now an RFC too.

Change-Id: I2aa7a862bf51ff01215455e87b16f259fc468490
Reviewed-on: https://boringssl-review.googlesource.com/7028
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 16:37:55 +00:00
David Benjamin 4e3d17a7e7 Remove redundant logic to compute EC public key.
d2i_ECPrivateKey already computes it as of
9f5a314d35.

Change-Id: Ie48b2319ee7d96d09c8e4f13d99de38bfa89be76
Reviewed-on: https://boringssl-review.googlesource.com/6857
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 16:23:05 +00:00
David Benjamin 4aafe6a3af Document the d2i object reuse changes in PORTING.md.
Change-Id: I1875c5246c7da19af13683ca36c737c188a97d18
Reviewed-on: https://boringssl-review.googlesource.com/6984
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 16:21:20 +00:00
William Hesse bf3335c621 Add #ifdef guards to crypto/curve25519 assembly files.
Add guards for the architecture and OPENSSL_NO_ASM to
the assembly-language files in crypto/curve25519/asm.
The Dart compilation of BoringSSL includes all files,
because the architecture is not known when gyp is run.

Change-Id: I66f5ae525266b63b0fe3a929012b771d545779b5
Reviewed-on: https://boringssl-review.googlesource.com/7030
Reviewed-by: Adam Langley <agl@google.com>
2016-02-02 16:03:33 +00:00
David Benjamin 72f7e21087 Stop allowing SHA-224 in TLS 1.2.
Take the mappings for MD5 and SHA-224 values out of the code altogether. This
aligns with the current TLS 1.3 draft.

For MD5, this is a no-op. It is not currently possible to configure accepted
signature algorithms, MD5 wasn't in the hardcoded list, and we already had a
test ensuring we enforced our preferences correctly. MD5 also wasn't in the
default list of hashes our keys could sign and no one overrides it with a
different hash.

For SHA-224, this is not quite a no-op. The hardcoded accepted signature
algorithms list included SHA-224, so this will break servers relying on that.
However, Chrome's metrics have zero data points of servers picking SHA-224 and
no other major browser includes it. Thus that should be safe.

SHA-224 was also in the default list of hashes we are willing to sign. For
client certificates, Chromium's abstractions already did not allow signing
SHA-224, so this is a no-op there. For servers, this will break any clients
which only accept SHA-224. But no major browsers do this and I am not aware of
any client implementation which does such ridiculous thing.

(SHA-1's still in there. Getting rid of that one is going to take more effort.)

Change-Id: I6a765fdeea9e19348e409d58a0eac770b318e599
Reviewed-on: https://boringssl-review.googlesource.com/7020
Reviewed-by: Adam Langley <agl@google.com>
2016-01-29 21:30:00 +00:00
Brian Smith 5fa8f5bc9a Fix |-Werror=old-style-declaration| violations in poly1305_vec.c.
The |inline| must appear before the type.

Change-Id: Iecebbcc50024a846d7804228a858acfc33d68efd
Reviewed-on: https://boringssl-review.googlesource.com/7010
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-28 23:58:45 +00:00
David Benjamin 2cdf398773 Remove pkey_base_id.
This is never accessed.

Change-Id: I4cade5e907ad4c03e9de7634b53ef965f7240087
Reviewed-on: https://boringssl-review.googlesource.com/6864
Reviewed-by: Adam Langley <agl@google.com>
2016-01-28 15:55:24 +00:00
David Benjamin 415564fe2c Update draft-irtf-cfrg-curves-11 references to RFC 7748.
Change-Id: I6148df93a1748754ee6be9e2b98cc8afd38746cb
Reviewed-on: https://boringssl-review.googlesource.com/6960
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:53:26 +00:00
David Benjamin 4f6acaf0da Use more C++11 features.
Finally, we can stick ScopedFOO in containers.

Change-Id: I3ed166575822af9f182e8be8f4db723e1f08ea31
Reviewed-on: https://boringssl-review.googlesource.com/6553
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:52:37 +00:00
David Benjamin c3774c1187 Fix some indentation.
Change-Id: I3507be754b489a99a04c0dea888cb1f3652e68c3
Reviewed-on: https://boringssl-review.googlesource.com/6854
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:51:45 +00:00
David Benjamin 0a2c9938a5 Don't allow the specifiedCurve form of ECParameters in SPKIs.
Although RFC 3279 allows both, per RFC 5912, keys must use a named curve
rather than spelling out the curve parameters. Although we do not allow
arbitrary curves, we do have to (pretty hackishly) recognize built-in
curves in ECPrivateKeys.

It seems the cause of this was that OpenSSL, unless you set asn1_flag on
the EC_GROUP, likes to encode keys by spelling out the parameters. This
is in violation of RFC 5915, though probably not in violation of one of
the other redundant ECC specifications. For more fun, it appears
asn1_flag defaults to *off* in the API and *on* in the command-line
tools.

I think the original cause was these defaults meant the pre-BoringSSL
Android/OpenSSL Chromium port wrote out Channel ID keys in this format.
By now this should no longer by an issue, but it'll warrant a bit more
investigation to be sure we can drop it.

For now, keep this logic out of SPKIs by not calling d2i_ECParameters.
d2i_ECParameters is a fairly pointless function when only named curves
are allowed. In testing other implementations, none of Firefox, Safari,
or IE11/Win will parse such certificates (i.e. the error is fatal and
unbypassable). Likewise, because Mac and Windows' underlying libraries
reject this, Chrome on Mac and Windows already rejects such things. Thus
this change should be compatible.

The following is the certificate and key I constructed to test with:

-----BEGIN CERTIFICATE-----
MIICwjCCAmqgAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
dCBXaWRnaXRzIFB0eSBMdGQwggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjO
PQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAA
AAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQaw
zFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i8
5uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2
QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAE
5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyD
SNsWGhz1HX7xlC1Lz3IiwaNQME4wHQYDVR0OBBYEFKuE0qyrlfCCThZ4B1VXX+Qm
jYLRMB8GA1UdIwQYMBaAFKuE0qyrlfCCThZ4B1VXX+QmjYLRMAwGA1UdEwQFMAMB
Af8wCQYHKoZIzj0EAQNHADBEAiBATB6aVJxDD6YAxEM4vf6Sbg2Ty334ldXpkNwc
TF+SngIgZ/f59kgDLf6YA04iLw1fUv5Wf1nLYJWwgrRFON5+zvw=
-----END CERTIFICATE-----
-----BEGIN EC PARAMETERS-----
MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////
/////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6
k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+
kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK
fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz
ucrC/GMlUQIBAQ==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAcPCHJ61KBKnN1ZyU2JaHcItW/JXTB3DujRyc4Ki7RqoAoGCCqGSM49
AwEHoUQDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY
+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQ==
-----END EC PRIVATE KEY-----

BUG=522228

Change-Id: I3723411a633dc07c4640027de07500293f8f7913
Reviewed-on: https://boringssl-review.googlesource.com/6853
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:51:14 +00:00
David Benjamin f6094e05ef Don't allow EVP_PKEY_RSA2.
OpenSSL accepts both OID 2.5.8.1.1 and OID 1.2.840.113549.1.1.1 for RSA
public keys. The latter comes from RFC 3279 and is widely implemented.
The former comes from the ITU-T version of X.509. Interestingly,
2.5.8.1.1 actually has a parameter, which OpenSSL ignores:

  rsa ALGORITHM ::= {
     KeySize
     IDENTIFIED BY id-ea-rsa
  }
  KeySize ::= INTEGER

Remove support for 2.5.8.1.1 completely. In tests with a self-signed
certificate and code inspection:

- IE11 on Win8 does not accept the certificate in a TLS handshake at
  all. Such a certificate is fatal and unbypassable. However Microsoft's
  libraries do seem to parse it, so Chrome on Windows allows one to
  click through the error. I'm guessing either the X.509 stack accepts
  it while the TLS stack doesn't recognize it as RSA or the X.509 stack
  is able to lightly parse it but not actually understand the key. (The
  system certificate UI didn't display it as an RSA key, so probably the
  latter?)

- Apple's certificate library on 10.11.2 does not parse the certificate
  at all. Both Safari and Chrome on Mac treat it as a fatal and
  unbypassable error.

- mozilla::pkix, from code inspection, does not accept such
  certificates. However, Firefox does allow clicking through the error.
  This is likely a consequence of mozilla::pkix and NSS having different
  ASN.1 stacks. I did not test this, but I expect this means Chrome on
  Linux also accepts it.

Given IE and Safari's results, it should be safe to simply remove this.
Firefox's data point is weak (perhaps someone is relying on being able
to click-through a self-signed 2.5.8.1.1 certificate), but it does
further ensure no valid certificate could be doing this.

The following is the 2.5.8.1.1 certificate I constructed to test with.
The private key is key.pem from ssl/test/runner:

-----BEGIN CERTIFICATE-----
MIICVTCCAb6gAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGcMAoGBFUIAQECAgQAA4GNADCBiQKBgQDY
K8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLciHnAj
kXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfVW28t
Q+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNVHQ4E
FgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4fZbf6
Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAIZuUICtYv
w3cbpCGX6HNCtyI0guOfbytcdwzRkQaCsYNSDrTxrSSWxHwqg3Dl/RlvS+T3Yaua
Xkioadstwt7GDP6MwpIpdbjchh0XZd3kjdJWqXSvihUDpRePNjNS2LmJW8GWfB3c
F6UVyNK+wcApRY+goREIhyYupAHUexR7FQ==
-----END CERTIFICATE-----

BUG=522228

Change-Id: I031d03c0f53a16cbc749c4a5d8be6efca50dc863
Reviewed-on: https://boringssl-review.googlesource.com/6852
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:43:37 +00:00
David Benjamin c612e61e1d Fix minor stylistic problem.
Normally this would be pretty scary:
  if (...) {
  } if (...) {
  }
But it's an early return anyway.

Change-Id: I0a8965b5e294d3aaa803be47f4006ea0311c431d
Reviewed-on: https://boringssl-review.googlesource.com/6851
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:35:35 +00:00
David Benjamin 719594e512 Un-const EVP_PKEY_CTX_set0_rsa_oaep_label and fix overflow check.
It takes ownership of the buffer, so it's not actually const. The
const-ness gets dropped once it transits through EVP_PKEY_CTX_ctrl.

Also compare against INT_MAX explicitly for the overflow check. I'm not sure
whether the casting version is undefined, but comparing against INT_MAX matches
the rest of the codebase when transiting in and out of signed ints.

Change-Id: I131165a4b5f0ebe02c6db3e7e3e0d1af5b771710
Reviewed-on: https://boringssl-review.googlesource.com/6850
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:34:38 +00:00
David Benjamin b6155e60f3 Remove app_data from EVP_PKEY_CTX.
It's never used. It's not clear why one would want such a thing.
EVP_PKEY_CTX has no way for callers to register callbacks, which means
there shouldn't be a way for the library to present you an EVP_PKEY_CTX
out-of-context. (Whereas app_data/ex_data makes sense on SSL because of
its numerous callbacks or RSA because of RSA_METHOD.)

Change-Id: I55af537ab101682677af34f6ac1f2c27b5899a89
Reviewed-on: https://boringssl-review.googlesource.com/6849
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:29:34 +00:00
David Benjamin 4e98e5c903 Implement pkey_ec_keygen with EC_KEY APIs.
This removes the last caller of EVP_PKEY_copy_parameters within the
library.

Change-Id: I6af138d364973b18f52baf55c36c50a24a56bd44
Reviewed-on: https://boringssl-review.googlesource.com/6848
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:28:43 +00:00
David Benjamin 692878a5f4 Remove EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID.
This is never exposed.

Change-Id: I332bc45f724eb42d68a0839e72b21593d01005ee
Reviewed-on: https://boringssl-review.googlesource.com/6847
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:27:42 +00:00
David Benjamin 8ac35f0274 Remove unused EVP_PKEY_METHOD hooks.
foo_init hooks are never implemented. Even upstream never uses them. The
flags member is also never used. We also don't expose paramgen, so
remove it.

Change-Id: I51d9439316c5163520ab7168693c457f33e59417
Reviewed-on: https://boringssl-review.googlesource.com/6846
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:23:46 +00:00
David Benjamin 9bf1b1b440 Remove group_clear_finish EC_GROUP hooks.
These are never called. Group parameters are not secret anyway. This is
a remnant of upstream's EC_GROUP_clear_free.

Change-Id: I23a4076eae8e4561abddbe74d0ba72641532f229
Reviewed-on: https://boringssl-review.googlesource.com/6823
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-28 00:17:43 +00:00
David Benjamin acb2451807 Rename the BIGNUM ASN.1 functions.
There's many ways to serialize a BIGNUM, so not including asn1 in the name is
confusing (and collides with BN_bn2cbb_padded). Since BN_asn12bn looks
ridiculous, match the parse/marshal naming scheme of other modules instead.

Change-Id: I53d22ae0537a98e223ed943e943c48cb0743cf51
Reviewed-on: https://boringssl-review.googlesource.com/6822
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 22:37:44 +00:00
David Benjamin 647cd02e59 Fix 32-bit build.
__uint128_t and friends don't exist in 32-bit. (Build fix for
https://boringssl-review.googlesource.com/#/c/6975/.)

Change-Id: I959a1f23c8cb3f11344f1da50cecd82d3080e3a0
Reviewed-on: https://boringssl-review.googlesource.com/6983
Reviewed-by: Adam Langley <agl@google.com>
2016-01-27 22:29:52 +00:00
David Benjamin b04c905da9 Remove the arch-specific HOST_c2l/HOST_l2c implementations.
These do not appear to have much discernable effect on performance. Three
comparison runs:

Before:
Did 5414000 SHA-1 (16 bytes) operations in 1000009us (5413951.3 ops/sec): 86.6 MB/s
Did 1607000 SHA-1 (256 bytes) operations in 1000403us (1606352.6 ops/sec): 411.2 MB/s
Did 70000 SHA-1 (8192 bytes) operations in 1014426us (69004.5 ops/sec): 565.3 MB/s
Did 2991000 SHA-256 (16 bytes) operations in 1000204us (2990390.0 ops/sec): 47.8 MB/s
Did 741000 SHA-256 (256 bytes) operations in 1000371us (740725.2 ops/sec): 189.6 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1019327us (30412.2 ops/sec): 249.1 MB/s
Did 2340000 SHA-512 (16 bytes) operations in 1000312us (2339270.1 ops/sec): 37.4 MB/s
Did 880000 SHA-512 (256 bytes) operations in 1000879us (879227.2 ops/sec): 225.1 MB/s
Did 44000 SHA-512 (8192 bytes) operations in 1013355us (43420.1 ops/sec): 355.7 MB/s
After:
Did 5259000 SHA-1 (16 bytes) operations in 1000013us (5258931.6 ops/sec): 84.1 MB/s
Did 1547000 SHA-1 (256 bytes) operations in 1000011us (1546983.0 ops/sec): 396.0 MB/s
Did 69000 SHA-1 (8192 bytes) operations in 1001089us (68924.9 ops/sec): 564.6 MB/s
Did 2984000 SHA-256 (16 bytes) operations in 1000207us (2983382.4 ops/sec): 47.7 MB/s
Did 734000 SHA-256 (256 bytes) operations in 1000317us (733767.4 ops/sec): 187.8 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1021065us (30360.5 ops/sec): 248.7 MB/s
Did 2324000 SHA-512 (16 bytes) operations in 1000116us (2323730.4 ops/sec): 37.2 MB/s
Did 828000 SHA-512 (256 bytes) operations in 1001046us (827134.8 ops/sec): 211.7 MB/s
Did 43000 SHA-512 (8192 bytes) operations in 1003381us (42855.1 ops/sec): 351.1 MB/s

---

Before:
Did 5415000 SHA-1 (16 bytes) operations in 1000055us (5414702.2 ops/sec): 86.6 MB/s
Did 1604000 SHA-1 (256 bytes) operations in 1000524us (1603159.9 ops/sec): 410.4 MB/s
Did 71000 SHA-1 (8192 bytes) operations in 1007686us (70458.5 ops/sec): 577.2 MB/s
Did 2984000 SHA-256 (16 bytes) operations in 1000472us (2982592.2 ops/sec): 47.7 MB/s
Did 738000 SHA-256 (256 bytes) operations in 1000885us (737347.4 ops/sec): 188.8 MB/s
Did 30000 SHA-256 (8192 bytes) operations in 1020475us (29398.1 ops/sec): 240.8 MB/s
Did 2297000 SHA-512 (16 bytes) operations in 1000391us (2296102.2 ops/sec): 36.7 MB/s
Did 882000 SHA-512 (256 bytes) operations in 1000389us (881657.0 ops/sec): 225.7 MB/s
Did 43000 SHA-512 (8192 bytes) operations in 1001313us (42943.6 ops/sec): 351.8 MB/s
After:
Did 5228000 SHA-1 (16 bytes) operations in 1000035us (5227817.0 ops/sec): 83.6 MB/s
Did 1575000 SHA-1 (256 bytes) operations in 1000410us (1574354.5 ops/sec): 403.0 MB/s
Did 69000 SHA-1 (8192 bytes) operations in 1004180us (68712.8 ops/sec): 562.9 MB/s
Did 2884000 SHA-256 (16 bytes) operations in 1000093us (2883731.8 ops/sec): 46.1 MB/s
Did 718000 SHA-256 (256 bytes) operations in 1000413us (717703.6 ops/sec): 183.7 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1030257us (30089.6 ops/sec): 246.5 MB/s
Did 2286000 SHA-512 (16 bytes) operations in 1000172us (2285606.9 ops/sec): 36.6 MB/s
Did 979000 SHA-512 (256 bytes) operations in 1000384us (978624.2 ops/sec): 250.5 MB/s
Did 47000 SHA-512 (8192 bytes) operations in 1017846us (46175.9 ops/sec): 378.3 MB/s

---

Before:
Did 5429000 SHA-1 (16 bytes) operations in 1000104us (5428435.4 ops/sec): 86.9 MB/s
Did 1604000 SHA-1 (256 bytes) operations in 1000473us (1603241.7 ops/sec): 410.4 MB/s
Did 69000 SHA-1 (8192 bytes) operations in 1002621us (68819.6 ops/sec): 563.8 MB/s
Did 3021000 SHA-256 (16 bytes) operations in 1000152us (3020540.9 ops/sec): 48.3 MB/s
Did 735000 SHA-256 (256 bytes) operations in 1000048us (734964.7 ops/sec): 188.2 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1019902us (30395.1 ops/sec): 249.0 MB/s
Did 2301000 SHA-512 (16 bytes) operations in 1000207us (2300523.8 ops/sec): 36.8 MB/s
Did 881000 SHA-512 (256 bytes) operations in 1001122us (880012.6 ops/sec): 225.3 MB/s
Did 44000 SHA-512 (8192 bytes) operations in 1015313us (43336.4 ops/sec): 355.0 MB/s
After:
Did 5264000 SHA-1 (16 bytes) operations in 1000061us (5263678.9 ops/sec): 84.2 MB/s
Did 1587000 SHA-1 (256 bytes) operations in 1000293us (1586535.1 ops/sec): 406.2 MB/s
Did 71000 SHA-1 (8192 bytes) operations in 1007587us (70465.4 ops/sec): 577.3 MB/s
Did 2967000 SHA-256 (16 bytes) operations in 1000240us (2966288.1 ops/sec): 47.5 MB/s
Did 737000 SHA-256 (256 bytes) operations in 1000874us (736356.4 ops/sec): 188.5 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1019630us (30403.2 ops/sec): 249.1 MB/s
Did 2326000 SHA-512 (16 bytes) operations in 1000413us (2325039.8 ops/sec): 37.2 MB/s
Did 885000 SHA-512 (256 bytes) operations in 1000253us (884776.2 ops/sec): 226.5 MB/s
Did 44000 SHA-512 (8192 bytes) operations in 1013216us (43426.1 ops/sec): 355.7 MB/s

Change-Id: Ifd4500f4e9f41ffc0f73542141e8888b4d7f1e0b
Reviewed-on: https://boringssl-review.googlesource.com/6652
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 22:26:32 +00:00
David Benjamin 8f2d4e344c Fix documentation string.
SSL_CTX_set_retain_only_sha256_of_client_certs's comment wasn't quite right.

Change-Id: I40527eebf2988d117cd8bd544bb5f16936c2cbfb
Reviewed-on: https://boringssl-review.googlesource.com/6982
Reviewed-by: Adam Langley <agl@google.com>
2016-01-27 22:20:32 +00:00
Brian Smith 87c7640773 Use |inline| in crypto/poly1305/poly1305_vec.c.
The code was using `#define INLINE` instead, but we have `inline` so
use it.

Change-Id: Id05eaec4720061c5d9a7278e20127c2bebcb2495
Reviewed-on: https://boringssl-review.googlesource.com/6976
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-27 22:15:34 +00:00
Brian Smith 24e428899b Define int128_t and uint128_t in one place.
Change-Id: Ia93130aadf319eaba1b6f2ec2896a4c50d9e8ede
Reviewed-on: https://boringssl-review.googlesource.com/6975
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-27 22:15:04 +00:00
Brian Smith f547007332 Use |alignas| more in crypto/chacha/chacha_vec.c.
Commit 75a64c08fc missed one case where
the GCC syntax should have been replaced with |alignas|.

Change-Id: Iebdaa9c9a2c0aff171f0b5d4daac607e351a4b7e
Reviewed-on: https://boringssl-review.googlesource.com/6974
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-27 22:12:22 +00:00
Brian Smith 9333d6df11 Fix data <-> function pointer casts in thread_win.c.
The uses of |memcpy| to cast pointer-to-function to pointer-to-data and
back again did not have well-defined semantics. Use a union instead to
avoid the need for such a conversion get well-defined semantics.

Change-Id: I8ee54a83ba75440f7bc78c194eb55e2cf09b05d8
Reviewed-on: https://boringssl-review.googlesource.com/6972
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-27 22:08:26 +00:00
Brian Smith f5f4be8fac Fix pointer-to-non-volatile cast in thread_win.c.
Casting a pointer-to-non-volatile to pointer-to-volatile can be a no-op
as the compiler only requires volatile semantics when the pointed-to
object is a volatile object and there are no pointers-to-non-volatile
involved. This probably doesn't matter unless building with the MSVC
-volatile:iso flag, and maybe not even then, but it is good practice
anyway.

Change-Id: I94900d3dc61de3b8ce2ddecab2811907a9a7adbf
Reviewed-on: https://boringssl-review.googlesource.com/6973
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-27 22:06:11 +00:00
Adam Langley 54a8d7c14f Use Barrett reduction in CBC processing rather than tricks.
Division isn't constant-time on Intel chips so the code was adding a
large multiple of md_size to try and force the operation to always take
the maximum amount of time.

I'm less convinced, these days, that compilers aren't going to get smart
enough to optimise that away so use Barrett reduction instead.

Change-Id: Ib8c514192682a2fcb4b1fb7e7c6dd1301d9888d0
Reviewed-on: https://boringssl-review.googlesource.com/6906
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 22:05:01 +00:00
David Benjamin 91b2501f02 Add functions for accessing read_sequence and write_sequence.
OpenSSL 1.1.0 doesn't seem to have these two, so this isn't based on anything.
Have them return uint64_t in preparation for switching the internal
representation to uint64_t so ssl_record_sequence_update can go away.

Change-Id: I21d55e9a29861c992f409ed293e0930a7aaef7a3
Reviewed-on: https://boringssl-review.googlesource.com/6941
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 22:03:57 +00:00
David Benjamin cdd0b7e775 Add SSL_CTX_set_retain_only_sha256_of_client_certs.
We have the hook on the SSL_CTX, but it should be possible to set it without
reaching into SSL_CTX.

Change-Id: I93db070c7c944be374543442a8de3ce655a28928
Reviewed-on: https://boringssl-review.googlesource.com/6880
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 22:02:53 +00:00
David Benjamin 4b9205b583 Align SSL_CTX_set1_tls_channel_id with SSL_set1_tls_channel_id.
They should use the same P-256 check.

Change-Id: I66dd63663e638cba35b8f70f9cf119c718af4aec
Reviewed-on: https://boringssl-review.googlesource.com/6845
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 21:51:39 +00:00
David Benjamin b83003ebc6 Don't initialize enc_method before version negotiation.
Move it into ssl->s3 so it automatically behaves correctly on SSL_clear.
ssl->version is still a mess though.

Change-Id: I17a692a04a845886ec4f8de229fa6cf99fa7e24a
Reviewed-on: https://boringssl-review.googlesource.com/6844
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 21:38:12 +00:00
David Benjamin a565d29ce6 Remove alert mapping machinery.
For TLS, this machinery only exists to swallow no_certificate alerts
which only get sent in an SSL 3.0 codepath anyway. It's much less a
no-op for SSL 3.0 which, strictly speaking, has only a subset of TLS's
alerts.

This gets messy around version negotiation because of the complex
relationship between enc_method, have_version, and version which all get
set at different times. Given that SSL 3.0 is nearly dead and all these
alerts are fatal to the connection anyway, this doesn't seem worth
carrying around. (It doesn't work very well anyway. An SSLv3-only server
may still send a record_overflow alert before version negotiation.)

This removes the last place enc_method is accessed prior to version
negotiation.

Change-Id: I79a704259fca69e4df76bd5a6846c9373f46f5a9
Reviewed-on: https://boringssl-review.googlesource.com/6843
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 21:28:48 +00:00
David Benjamin a1e9cabd8b Replace enc_flags with normalized version checks.
This removes the various non-PRF checks from SSL3_ENC_METHOD so that can
have a clearer purpose. It also makes TLS 1.0 through 1.2's
SSL3_ENC_METHOD tables identical and gives us an assert to ensure
nothing accesses the version bits before version negotiation.
Accordingly, ssl_needs_record_splitting was reordered slightly so we
don't rely on enc_method being initialized to TLS 1.2
pre-version-negotiation.

This leaves alert_value as the only part of SSL3_ENC_METHOD which may be
accessed before version negotiation.

Change-Id: If9e299e2ef5511b5fa442b2af654eed054c3e675
Reviewed-on: https://boringssl-review.googlesource.com/6842
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-27 21:17:55 +00:00
Adam Langley ef7dba6ac7 Fix error in ce9d85ee.
I used a size_t out of habit, but |RSA_public_decrypt| is an old-style
function.

Change-Id: Ibd94d03743fe0099d61578ec15c19fa5333127db
2016-01-26 15:31:23 -08:00
Adam Langley ce9d85eedd Tweaks for node.js
node.js is, effectively, another bindings library. However, it's better
written than most and, with these changes, only a couple of tiny fixes
are needed in node.js. Some of these changes are a little depressing
however so we'll need to push node.js to use APIs where possible.

Changes:
  ∙ Support verify_recover. This is very obscure and the motivation
    appears to be https://github.com/nodejs/node/issues/477 – where it's
    not clear that anyone understands what it means :(
  ∙ Add a few, no-op #defines
  ∙ Add some members to |SSL_CTX| and |SSL| – node.js needs to not
    reach into these structs in the future.
  ∙ Add EC_get_builtin_curves.
  ∙ Add EVP_[CIPHER|MD]_do_all_sorted – these functions are limited to
    decrepit.

Change-Id: I9a3566054260d6c4db9d430beb7c46cc970a9d46
Reviewed-on: https://boringssl-review.googlesource.com/6952
Reviewed-by: Adam Langley <agl@google.com>
2016-01-26 23:23:42 +00:00
Adam Langley eac0ce09d8 Have doc.go parse struct comments.
In code, structs that happened to have a '(' somewhere in their body
would cause the parser to go wrong. This change fixes that and updates
the comments on a number of structs.

Change-Id: Ia76ead266615a3d5875b64a0857a0177fec2bd00
Reviewed-on: https://boringssl-review.googlesource.com/6970
Reviewed-by: Adam Langley <agl@google.com>
2016-01-26 23:23:23 +00:00
David Benjamin 241ae837f0 Add some tests to ensure we ignore bogus curves and ciphers.
We haven't had problems with this, but make sure it stays that way.
Bogus signature algorithms are already covered.

Change-Id: I085350d89d79741dba3f30fc7c9f92de16bf242a
Reviewed-on: https://boringssl-review.googlesource.com/6910
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-26 21:51:55 +00:00
David Benjamin f6494f4928 Add a SSL_get_pending_cipher API.
Conscrypt needs to, in the certificate verification callback, know the key
exchange + auth method of the current cipher suite to pass into
X509TrustManager.checkServerTrusted. Currently it reaches into the struct to
get it. Add an API for this.

Change-Id: Ib4e0a1fbf1d9ea24e0114f760b7524e1f7bafe33
Reviewed-on: https://boringssl-review.googlesource.com/6881
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-26 21:51:02 +00:00
David Benjamin 7027d25c6b Also add a no-op stub for OPENSSL_config.
Apparently OpenSSL's API is made entirely of initialization functions.
Some external libraries like to initialize with OPENSSL_config instead.

Change-Id: I28efe97fc5eb21309f560c84112b80e947f8bb17
Reviewed-on: https://boringssl-review.googlesource.com/6981
Reviewed-by: Adam Langley <agl@google.com>
2016-01-26 15:48:51 +00:00
David Benjamin e5aa791a1c Add a few more no-op stubs for cURL compatibility.
With these stubs, cURL should not need any BoringSSL #ifdefs at all,
except for their OCSP #ifdefs (which can switch to the more generally
useful OPENSSL_NO_OCSP) and the workaround for wincrypt.h macro
collisions. That we intentionally leave to the consumer rather than add
a partial hack that makes the build sensitive to include order.

(I'll send them a patch upstream once this cycles in.)

Change-Id: I815fe67e51e80e9aafa9b91ae68867ca1ff1d623
Reviewed-on: https://boringssl-review.googlesource.com/6980
Reviewed-by: Adam Langley <agl@google.com>
2016-01-26 15:48:41 +00:00
David Benjamin 5aae776ede Remove calls to ERR_load_crypto_strings.
Since the error string logic was rewritten, this hasn't done anything.

Change-Id: Icb73dca65e852bb3c7d04c260d591906ec72c15f
Reviewed-on: https://boringssl-review.googlesource.com/6961
Reviewed-by: Adam Langley <agl@google.com>
2016-01-25 23:09:08 +00:00
Adam Langley 75a64c08fc Remove some mingw support cruft.
This was needed for Android, but “the new version of mingw has moved all
of time_s.h into time.h” [1].

[1] https://android-review.googlesource.com/#/c/196597/

Change-Id: I17e66ed93606f3e6a774af3290c15b5ca151449f
Reviewed-on: https://boringssl-review.googlesource.com/6971
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-25 23:05:45 +00:00
Brian Smith 7cae9f5b6c Use |alignas| for alignment.
MSVC doesn't have stdalign.h and so doesn't support |alignas| in C
code. Define |alignas(x)| as a synonym for |__decltype(align(x))|
instead for it.

This also fixes -Wcast-qual warnings in rsaz_exp.c.

Change-Id: Ifce9031724cb93f5a4aa1f567e7af61b272df9d5
Reviewed-on: https://boringssl-review.googlesource.com/6924
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-25 23:05:04 +00:00
Brian Smith 34749f47da Remove unnecessary assignment of |e| in |rsa_setup_blinding|.
After its initial assignment, |e| is immediately reassigned another
value and so the initial assignment from |BN_CTX_get| is useless. If
that were not the case, then the |BN_free(e)| at the end of the
function would be very bad.

Change-Id: Id63a172073501c8ac157db9188a22f55ee36b205
Reviewed-on: https://boringssl-review.googlesource.com/6951
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-23 17:08:23 +00:00
David Benjamin 232127d245 Fold EC_GROUP_new_curve_GFp and EC_GROUP_set_generator into a EC_GROUP_new_arbitrary.
This is only for Conscrypt which always calls the pair in succession. (Indeed
it wouldn't make any sense to not call it.) Remove those two APIs and replace
with a single merged API. This way incomplete EC_GROUPs never escape outside
our API boundary and EC_GROUPs may *finally* be made immutable.

Also add a test for this to make sure I didn't mess it up.

Add a temporary BORINGSSL_201512 define to ease the transition for Conscrypt.
Conscrypt requires https://android-review.googlesource.com/#/c/187801/ before
picking up this change.

Change-Id: I3706c2ceac31ed2313175ba5ee724bd5c74ef6e1
Reviewed-on: https://boringssl-review.googlesource.com/6550
Reviewed-by: Adam Langley <agl@google.com>
2016-01-21 22:35:46 +00:00
David Benjamin 95219feafd Fix some documentation comments.
The new OPENSSL_PRINTF_FORMAT_FUNC macro let doc.go catch a few problems. It
also confuses doc.go, but this CL doesn't address that. At some point we
probably need to give it a real C parser.

Change-Id: I39f945df04520d1e0a0ba390cac7b308baae0622
Reviewed-on: https://boringssl-review.googlesource.com/6940
Reviewed-by: Adam Langley <agl@google.com>
2016-01-21 22:12:08 +00:00
Brian Smith d3a4e280db Fix trivial -Wcast-qual violations.
Fix casts from const to non-const where dropping the constness is
completely unnecessary. The changes to chacha_vec.c don't result in any
changes to chacha_vec_arm.S.

Change-Id: I2f10081fd0e73ff5db746347c5971f263a5221a6
Reviewed-on: https://boringssl-review.googlesource.com/6923
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 21:06:02 +00:00
Brian Smith a646258c14 Enable stronger format string checking |-Wformat=2|.
Also, factor out flags based to both the C and C++ compiler into a
single variable.

Change-Id: I432de0cc516e95a0d48146fae2dda8b7b3b38d4b
Reviewed-on: https://boringssl-review.googlesource.com/6922
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 21:00:31 +00:00
Brian Smith d92f1d39a8 Fix |sscanf| format string in cpu-intel.c.
Fix the signness of the format flag in the |sscanf| call in cpu-intel.c.

Change-Id: I31251d79aa146bf9c78be47020ee83d30864a3d2
Reviewed-on: https://boringssl-review.googlesource.com/6921
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 20:59:35 +00:00
Brian Smith 8d3c43e4b1 Annotate |ERR_add_error_dataf| as |OPENSSL_PRINTF_FORMAT_FUNC|.
Besides being a good idea anyway, this avoids clang warning about using
a non-literal format string when |ERR_add_error_dataf| calls
|BIO_vsnprintf|.

Change-Id: Iebc84d9c9d85e08e93010267d473387b661717a5
Reviewed-on: https://boringssl-review.googlesource.com/6920
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 20:59:18 +00:00
Brian Smith 061332f216 Define |OPENSSL_PRINTF_FORMAT_FUNC| for format string annotations.
This centralizes the conditional logic into openssl/base.h so that it
doesn't have to be repeated. The name |OPENSSL_PRINTF_FORMAT_FUNC| was
chosen in anticipation of eventually defining an
|OPENSSL_PRINTF_FORMAT_ARG| for MSVC-style parameter annotations.

Change-Id: I273e6eddd209e696dc9f82099008c35b6d477cdb
Reviewed-on: https://boringssl-review.googlesource.com/6909
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 20:58:51 +00:00
Brian Smith 0687bdfc12 Fix -Wformat-nonliteral violation in ssl_cipher.c.
Besides avoiding the -Wformat-nonliteral warning, it is easier to
review (changes to) the code when the format string is passed to the
function as a literal.

Change-Id: I5093ad4494d5ebeea3f2671509b916cd6c5fb173
Reviewed-on: https://boringssl-review.googlesource.com/6908
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-21 20:56:59 +00:00
David Benjamin 6c22f542f4 Fix build of x509_test.
Some combination of Chromium's copy of clang and Chromium's Linux sysroot
doesn't like syntax. It complains that "chosen constructor is explicit in
copy-initialization".

Change-Id: Ied6bc17b19421998f926483742510c81f732566b
Reviewed-on: https://boringssl-review.googlesource.com/6930
Reviewed-by: Adam Langley <agl@google.com>
2016-01-20 23:08:03 +00:00
David Benjamin fc6e5a7372 Drop the silly 'ECDH_' prefix on X25519.
I got that from the TLS 1.3 draft, but it's kind of silly-looking. X25519
already refers to a Diffie-Hellman primitive.

Also hopefully the WG will split NamedGroups and SignatureAlgorithms per the
recent proposal, so it won't be needed anyway. (Most chatter is about what
hashes should be allowed with what NIST curves, so it seems like people like
the split itself? We'll see.)

Change-Id: I7bb713190001199a3ebd30b67df2c00d29132431
Reviewed-on: https://boringssl-review.googlesource.com/6912
Reviewed-by: Adam Langley <agl@google.com>
2016-01-20 17:26:13 +00:00
David Benjamin d2f0ce80a2 Enable X25519 by default in TLS.
BUG=571231

Change-Id: I73e39411ccdc817f172c7a94b7f70c448eed938f
Reviewed-on: https://boringssl-review.googlesource.com/6911
Reviewed-by: Adam Langley <agl@google.com>
2016-01-20 17:26:02 +00:00
Adam Langley 3a39b06011 Import “altchains” support.
This change imports the following changes from upstream:

6281abc79623419eae6a64768c478272d5d3a426
dfd3322d72a2d49f597b86dab6f37a8cf0f26dbf
f34b095fab1569d093b639bfcc9a77d6020148ff
21376d8ae310cf0455ca2b73c8e9f77cafeb28dd
25efcb44ac88ab34f60047e16a96c9462fad39c1
56353962e7da7e385c3d577581ccc3015ed6d1dc
39c76ceb2d3e51eaff95e04d6e4448f685718f8d
a3d74afcae435c549de8dbaa219fcb30491c1bfb

These contain the “altchains” functionality which allows OpenSSL to
backtrack when chain building.

Change-Id: I8d4bc2ac67b90091f9d46e7355cae878b4ccf37d
Reviewed-on: https://boringssl-review.googlesource.com/6905
Reviewed-by: Adam Langley <agl@google.com>
2016-01-19 17:02:31 +00:00
Adam Langley 57707c70dc OpenSSL reformat x509/, x509v3/, pem/ and asn1/.
OpenSSL upstream did a bulk reformat. We still have some files that have
the old OpenSSL style and this makes applying patches to them more
manual, and thus more error-prone, than it should be.

This change is the result of running
  util/openssl-format-source -v -c .
in the enumerated directories. A few files were in BoringSSL style and
have not been touched.

This change should be formatting only; no semantic difference.

Change-Id: I75ced2970ae22b9facb930a79798350a09c5111e
Reviewed-on: https://boringssl-review.googlesource.com/6904
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2016-01-19 17:01:51 +00:00
Adam Langley 62882187c9 Update comments to better document in-place semantics.
(Comment-only change; no functional difference.)

Some code was broken by the |d2i_ECDSA_SIG| change in 87897a8c. It was
passing in a pointer to an existing |ECDSA_SIG| as the first argument
and then simply assuming that the structure would be updated in place.
The comments on the function suggested that this was reasonable.

This change updates the comments that use similar wording to either note
that the function will never update in-place, or else to note that
depending on that is a bad idea for the future.

I've also audited all the uses of these functions that I can find and,
in addition to the one case with |d2i_ECDSA_SIG|, there are several
users of |d2i_PrivateKey| that could become a problem in the future.
I'll try to fix them before it does become an issue.

Change-Id: I769f7b2e0b5308d09ea07dd447e02fc161795071
Reviewed-on: https://boringssl-review.googlesource.com/6902
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2016-01-19 17:01:37 +00:00
David Benjamin b8ba65a73a Fix arm perlasm trailing newline.
Change-Id: I1119fd8d5a0e03832644cb4b8128eed8ed9acb9e
Reviewed-on: https://boringssl-review.googlesource.com/6890
Reviewed-by: Adam Langley <agl@google.com>
2016-01-19 16:35:20 +00:00
Matt Braithwaite 0b553eb531 Remove a trailing ^M (DOS newline).
Change-Id: Iacce453dc55847e0d35a7a25c5997a3a46bb4c9a
Reviewed-on: https://boringssl-review.googlesource.com/6907
Reviewed-by: Adam Langley <agl@google.com>
2016-01-16 04:08:14 +00:00
David Benjamin b9e4fa5e02 Add a helper function to normalize the current version.
We have need to normalize other versions during version negotiation, but
almost all will be post-negotiation. Hopefully later this can be
replaced with a value explicitly stored on the object and we do away
with ssl->version.

Change-Id: I595db9163d0af2e7c083b9a09310179aaa9ac812
Reviewed-on: https://boringssl-review.googlesource.com/6841
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:17:00 +00:00
David Benjamin 23b0a65df1 Move some functions to file scope.
The various SSL3_ENC_METHODs ought to be defined in the same file their
functions are defined in, so they can be static.

Change-Id: I34a1d3437e8e61d4d50f2be70312e4630ea89c19
Reviewed-on: https://boringssl-review.googlesource.com/6840
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:14:39 +00:00
David Benjamin 928f32a492 Add APIs to extract the SSL key block.
This is a companion to SSL_get_rc4_state and SSL_get_ivs which doesn't
require poking at internal state. Partly since it aligns with the
current code and partly the off chance we ever need to get
wpa_supplicant's EAP-FAST code working, the API allows one to generate
more key material than is actually in the key block.

Change-Id: I58bc3f2b017482dbb8567dcd0cd754947a95397f
Reviewed-on: https://boringssl-review.googlesource.com/6839
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:09:24 +00:00
David Benjamin baa1216ac0 Prune finished labels from SSL3_ENC_METHOD.
There's not much point in putting those in the interface as the
final_finished_mac implementation is itself different between SSL 3.0
and TLS.

Change-Id: I76528a88d255c451ae008f1a34e51c3cb57d3073
Reviewed-on: https://boringssl-review.googlesource.com/6838
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:04:53 +00:00
David Benjamin f8d807176a Remove a few unnecessary SSL3_ENC_METHOD hooks.
As things stand now, they don't actually do anything.

Change-Id: I9f8b4cbf38a0dffabfc5265805c52bb8d7a8fb0d
Reviewed-on: https://boringssl-review.googlesource.com/6837
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:02:30 +00:00
David Benjamin b35d68483c Minor cleanup.
Mostly alg_k and alg_a variables had the wrong type.

Change-Id: I66ad4046b1f5a4e3e58bc407096d95870b42b9dd
Reviewed-on: https://boringssl-review.googlesource.com/6836
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 22:01:28 +00:00
David Benjamin 79978df4ec Move aead_{read,write}_ctx and next_proto_negotiated into ssl->s3.
Both are connection state rather than configuration state. Notably this
cuts down more of SSL_clear that can't just use ssl_free + ssl_new.

Change-Id: I3c05b3ae86d4db8bd75f1cd21656f57fc5b55ca9
Reviewed-on: https://boringssl-review.googlesource.com/6835
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 21:40:25 +00:00
David Benjamin 57997da8ee Simplify the ChangeCipherSpec logic.
It's the same between TLS and SSL 3.0. There's also no need for the
do_change_cipher_spec wrapper (it no longer needs checks to ensure it
isn't called at a bad place). Finally fold the setup_key_block call into
change_cipher_spec.

Change-Id: I7917f48e1a322f5fbafcf1dfb8ad53f66565c314
Reviewed-on: https://boringssl-review.googlesource.com/6834
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 21:33:57 +00:00
David Benjamin 0623bceb25 Fill in ssl->session->cipher when resumption is resolved.
Doing it at ChangeCipherSpec makes it be set twice and, more
importantly, causes us to touch SSL_SESSION objects on resumption. (With
a no-op change, but this still isn't a good idea.)

This should actually let us get rid of ssl->s3->tmp.new_cipher but some
of external code accesses that field directly.

Change-Id: Ia6b7e0964c1b430f963ad0b1a5417b339b7b19d3
Reviewed-on: https://boringssl-review.googlesource.com/6833
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 20:46:45 +00:00
David Benjamin 4119d42e7c Tidy up keyblock and CCS logic slightly.
Move the actual SSL_AEAD_CTX swap into the record layer. Also revise the
intermediate state we store between setup_key_block and
change_cipher_state. With SSL_AEAD_CTX_new abstracted out, keeping the
EVP_AEAD around doesn't make much sense. Just store enough to partition
the key block.

Change-Id: I773fb46a2cb78fa570f00c0a89339c15bbb1d719
Reviewed-on: https://boringssl-review.googlesource.com/6832
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 20:40:44 +00:00
David Benjamin 1db2156ce8 Move ssl3_record_sequence_update with the other record-layer bits.
Change-Id: I045a4d3e304872b8c97231dcde5bca7753a878fb
Reviewed-on: https://boringssl-review.googlesource.com/6831
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 20:15:55 +00:00
David Benjamin 96ba15fc69 Add SSL_get_client_random and SSL_get_server_random.
wpa_supplicant needs to get at the client and server random. OpenSSL
1.1.0 added these APIs, so match their semantics.

Change-Id: I2b71ba850ac63e574c9ea79012d1d0efec5a979a
Reviewed-on: https://boringssl-review.googlesource.com/6830
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 20:15:29 +00:00
David Benjamin ef1b009344 Consider session if the client supports tickets but offered a session ID.
This is a minor regression from
https://boringssl-review.googlesource.com/5235.

If the client, for whatever reason, had an ID-based session but also
supports tickets, it will send non-empty ID + empty ticket extension.
If the ticket extension is non-empty, then the ID is not an ID but a
dummy signaling value, so 5235 avoided looking it up. But if it is
present and empty, the ID is still an ID and should be looked up.

This shouldn't have any practical consequences, except if a server
switched from not supporting tickets and then started supporting it,
while keeping the session cache fixed.

Add a test for this case, and tighten up existing ID vs ticket tests so
they fail if we resume with the wrong type.

Change-Id: Id4d08cd809af00af30a2b67fe3a971078e404c75
Reviewed-on: https://boringssl-review.googlesource.com/6554
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 20:08:52 +00:00
Adam Langley dd1f6f4fba Rename the curve25519 precomputed tables.
These symbols can show up in lists of large symbols but, so I
understand, these lists might not include the filename path. Thus |base|
as a symbol name is rather unhelpful.

This change renames the two precomputated tables to have slightly more
greppable names.

Change-Id: I77059250cfce4fa9eceb64e260b45db552b63255
Reviewed-on: https://boringssl-review.googlesource.com/6813
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <alangley@gmail.com>
2016-01-15 19:51:05 +00:00
Matt Braithwaite e021a245bf Add curve25519/asm/x25519-asm-x86_64.S.
Change-Id: I5feff96d8d80981e72a8b3aa3fd90e3202dff39e
Reviewed-on: https://boringssl-review.googlesource.com/6903
Reviewed-by: Adam Langley <agl@google.com>
2016-01-14 22:36:58 +00:00
Brian Smith 625475f3e3 Fix bits vs. bytes confusion in RSA encryption.
rsa_default_encrypt allowed an RSA modulus 8 times larger than the
intended maximum size due to bits vs. bytes confusion.

Further, as |rsa_default_encrypt| got this wrong while
|rsa_default_verify_raw| got it right, factor out the duplicated logic
so that such inconsistencies are less likely to occur.

BUG=576856

Change-Id: Ic842fadcbb3b140d2ba4295793457af2b62d9444
Reviewed-on: https://boringssl-review.googlesource.com/6900
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2016-01-13 22:28:54 +00:00
Adam Langley 7b8b9c17db Include 'asm' in the name of X25519 asm sources.
Some build systems don't like two targets with the same base name and
the curve25519 code had x25519-x86_64.[Sc].

Change-Id: If8382eb84996d7e75b34b28def57829d93019cff
Reviewed-on: https://boringssl-review.googlesource.com/6878
Reviewed-by: Adam Langley <agl@google.com>
2016-01-05 16:05:50 +00:00
Adam Langley 3202750a98 Update the fuzz tests for the server.
These seeds are the result of spending more CPU time fuzzing the server.

Change-Id: Iacf889ae6e214056033f4a5f9f3b89e4710c22a5
2015-12-22 16:35:07 -08:00
David Benjamin 6544426d82 Fix a ** 0 mod 1 = 0 for real this time.
Commit 2b0180c37fa6ffc48ee40caa831ca398b828e680 attempted to do this but
only hit one of many BN_mod_exp codepaths. Fix remaining variants and
add a test for each method.

Thanks to Hanno Boeck for reporting this issue.

(Imported from upstream's 44e4f5b04b43054571e278381662cebd3f3555e6.)

Change-Id: Ic691b354101c3e9c3565300836fb6d55c6f253ba
Reviewed-on: https://boringssl-review.googlesource.com/6820
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 23:30:22 +00:00
David Benjamin fe5f7c7b56 Only reserve EVP_MAX_MD_SIZE for the Finished, not twice of it.
EVP_MAX_MD_SIZE is large enough to fit a MD5/SHA1 concatenation, and
necessarily is because EVP_md5_sha1 exists. This shaves 128 bytes of
per-connection state.

Change-Id: I848a8563dfcbac14735bb7b302263a638528f98e
Reviewed-on: https://boringssl-review.googlesource.com/6804
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 23:29:21 +00:00
David Benjamin 0d56f888c3 Switch s to ssl everywhere.
That we're half and half is really confusing.

Change-Id: I1c2632682e8a3e63d01dada8e0eb3b735ff709ce
Reviewed-on: https://boringssl-review.googlesource.com/6785
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 23:28:22 +00:00
David Benjamin 974c7ba4ef Route DHE through the SSL_ECDH abstraction as well.
This unifies the ClientKeyExchange code rather nicely. ServerKeyExchange
is still pretty specialized. For simplicity, I've extended the yaSSL bug
workaround for clients as well as servers rather than route in a
boolean.

Chrome's already banished DHE to a fallback with intention to remove
altogether later, and the spec doesn't say anything useful about
ClientDiffieHellmanPublic encoding, so this is unlikely to cause
problems.

Change-Id: I0355cd1fd0fab5729e8812e4427dd689124f53a2
Reviewed-on: https://boringssl-review.googlesource.com/6784
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 23:17:32 +00:00
David Benjamin 4cc36adf5a Make it possible to tell what curve was used on the server.
We don't actually have an API to let you know if the value is legal to
interpret as a curve ID. (This was kind of a poor API. Oh well.) Also add tests
for key_exchange_info. I've intentionally left server-side plain RSA missing
for now because the SSL_PRIVATE_KEY_METHOD abstraction only gives you bytes and
it's probably better to tweak this API instead.

(key_exchange_info also wasn't populated on the server, though due to a
rebasing error, that fix ended up in the parent CL. Oh well.)

Change-Id: I74a322c8ad03f25b02059da7568c9e1a78419069
Reviewed-on: https://boringssl-review.googlesource.com/6783
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 23:12:25 +00:00
David Benjamin 4298d77379 Implement draft-ietf-tls-curve25519-01 in C.
The new curve is not enabled by default.

As EC_GROUP/EC_POINT is a bit too complex for X25519, this introduces an
SSL_ECDH_METHOD abstraction which wraps just the raw ECDH operation. It
also tidies up some of the curve code which kept converting back and
force between NIDs and curve IDs. Now everything transits as curve IDs
except for API entry points (SSL_set1_curves) which take NIDs. Those
convert immediately and act on curve IDs from then on.

Note that, like the Go implementation, this slightly tweaks the order of
operations. The client sees the server public key before sending its
own. To keep the abstraction simple, SSL_ECDH_METHOD expects to
generate a keypair before consuming the peer's public key. Instead, the
client handshake stashes the serialized peer public value and defers
parsing it until it comes time to send ClientKeyExchange. (This is
analogous to what it was doing before where it stashed the parsed peer
public value instead.)

It still uses TLS 1.2 terminology everywhere, but this abstraction should also
be compatible with TLS 1.3 which unifies (EC)DH-style key exchanges.
(Accordingly, this abstraction intentionally does not handle parsing the
ClientKeyExchange/ServerKeyExchange framing or attempt to handle asynchronous
plain RSA or the authentication bits.)

BUG=571231

Change-Id: Iba09dddee5bcdfeb2b70185308e8ab0632717932
Reviewed-on: https://boringssl-review.googlesource.com/6780
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 21:51:30 +00:00
David Benjamin c18ef750ee Allocate a NID for X25519.
No corresponding OID, but SSL_CTX_set1_curves assumes NIDs exist.

BUG=571231

Change-Id: Id5221cdc59132e26a89ae5f8978b946de690b4e0
Reviewed-on: https://boringssl-review.googlesource.com/6779
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 18:56:53 +00:00
David Benjamin 3a2a48086b Remove long-dead comment.
clang-format keeps getting annoyed at it. Also remove some long-dead
constants.

Change-Id: I61e773f5be1e60ca28f1ea085e3afa7cb2c97b9e
Reviewed-on: https://boringssl-review.googlesource.com/6778
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 18:55:53 +00:00
David Benjamin cba2b62a85 Implement draft-ietf-tls-curve25519-01 in Go.
This injects an interface to abstract between elliptic.Curve and a
byte-oriented curve25519. The C implementation will follow a similar
strategy.

Note that this slightly tweaks the order of operations. The client sees
the server public key before sending its own. To keep the abstraction
simple, ecdhCurve expects to generate a keypair before consuming the
peer's public key. Instead, the client handshake stashes the serialized
peer public value and defers parsing it until it comes time to send
ClientKeyExchange. (This is analogous to what it was doing before where
it stashed the parsed peer public value instead.)

BUG=571231

Change-Id: I771bb9aee0dd6903d395c84ec4f2dd7b3e366c75
Reviewed-on: https://boringssl-review.googlesource.com/6777
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 18:43:33 +00:00
David Benjamin ab14563022 Bundle a copy of golang.org/x/crypto/curve25519 for testing.
Hopefully this can be replaced with a standard library version later.

BUG=571231

Change-Id: I61ae1d9d057c6d9e1b92128042109758beccc7ff
Reviewed-on: https://boringssl-review.googlesource.com/6776
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:47:53 +00:00
David Benjamin a029ebc4c6 Switch the bundled poly1305 to relative imports.
We don't live in a workspace, but relative import paths exist, so we
don't have to modify the modules we bundle to avoid naming collisions.

Change-Id: Ie7c70dbc4bb0485421814d40b6a6bd5f140e1d29
Reviewed-on: https://boringssl-review.googlesource.com/6781
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:47:28 +00:00
David Benjamin 64d9250e2f Completely remove P-224 from the TLS stack.
It already wasn't in the default list and no one enables it. Remove it
altogether. (It's also gone from the current TLS 1.3 draft.)

Change-Id: I143d07d390d186252204df6bdb8ffd22649f80e3
Reviewed-on: https://boringssl-review.googlesource.com/6775
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:45:26 +00:00
David Benjamin 8c2b3bf965 Test all supported curves (including those off by default).
Change-Id: I54b2b354ab3d227305f829839e82e7ae7292fd7d
Reviewed-on: https://boringssl-review.googlesource.com/6774
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:41:47 +00:00
David Benjamin fc8251258d Convert ssl3_send_cert_verify to CBB.
In doing so, make the asynchronous portion look more like
ssl3_send_server_key_exchange. This is a considerably simpler structure,
so the save/resume doesn't need any state.

Mostly this means writing out the signature algorithm can now go through
CBB rather than a uint8_t* without bounds check.

Change-Id: If99fcffd0d41a84514c3d23034062c582f1bccb2
Reviewed-on: https://boringssl-review.googlesource.com/6771
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:40:47 +00:00
Adam Langley 5fb18c6b42 Make MSVC happy.
The MSVC build is failing with:
  ssl\s3_srvr.c(1363) : warning C4701: potentially uninitialized local variable 'digest_len' used

I don't believe that this warning is valid, but this change assigns a
value to |digest_len| to fix the build.

Change-Id: I20107a932bc16c880032cc1a57479b1a806aa8ea
Reviewed-on: https://boringssl-review.googlesource.com/6821
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:38:45 +00:00
David Benjamin 2a0b391ac9 Rewrite ssl3_send_server_key_exchange to use CBB.
There is some messiness around saving and restoring the CBB, but this is
still significantly clearer.

Note that the BUF_MEM_grow line is gone in favor of a fixed CBB like the
other functions ported thus far. This line was never necessary as
init_buf is initialized to 16k and none of our key exchanges get that
large. (The largest one can get is DHE_RSA. Even so, it'd take a roughly
30k-bit DH group with a 30k-bit RSA key.)

Having such limits and tight assumptions on init_buf's initial size is
poor (but on par for the old code which usually just blindly assumed the
message would not get too large) and the size of the certificate chain
is much less obviously bounded, so those BUF_MEM_grows can't easily go.

My current plan is convert everything but those which legitimately need
BUF_MEM_grow to CBB, then atomically convert the rest, remove init_buf,
and switch everything to non-fixed CBBs. This will hopefully also
simplify async resumption. In the meantime, having a story for
resumption means the future atomic change is smaller and, more
importantly, relieves some complexity budget in the ServerKeyExchange
code for adding Curve25519.

Change-Id: I1de6af9856caaed353453d92a502ba461a938fbd
Reviewed-on: https://boringssl-review.googlesource.com/6770
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:23:58 +00:00
David Benjamin d16bf3421c Add a -lldb flag to runner.go.
Apple these days ships lldb without gdb. Teach runner how to launch it
too.

Change-Id: I25f845f84f1c87872a9e3bc4b7fe3e7344e8c1f7
Reviewed-on: https://boringssl-review.googlesource.com/6769
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:05:50 +00:00
David Benjamin af21bcf91f Remove other unnecessary BN_CTX allocations.
Functions which take a BN_CTX also accept NULL. Allocating a BN_CTX is
only useful if doing multiple operations, which we aren't.

Change-Id: Ib31113f214707cce6283e090ded0bf93ae5e7c12
Reviewed-on: https://boringssl-review.googlesource.com/6768
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:01:58 +00:00
David Benjamin ae0eaaa397 Convert ssl3_send_client_key_exchange to CBB.
This relieves some complexity budget for adding Curve25519 to this
code.

This also adds a BN_bn2cbb_padded helper function since this seems to be a
fairly common need.

Change-Id: Ied0066fdaec9d02659abd6eb1a13f33502c9e198
Reviewed-on: https://boringssl-review.googlesource.com/6767
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 17:00:56 +00:00
Adam Langley 3ac4b3a391 Remove NO_ASM define that I accidently included in the previous commit.
Change-Id: I0000e51930cd1e286173f96f79dbb18d33cd294a
Reviewed-on: https://boringssl-review.googlesource.com/6811
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 16:34:33 +00:00
Adam Langley e6c540290d Don't build X25519 asm code when NO_ASM is set.
Change-Id: I6c7188648d81ab11a43b5491a850fb1d74e40986
Reviewed-on: https://boringssl-review.googlesource.com/6810
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 16:32:53 +00:00
Adam Langley 77a173efed Add x86-64 assembly for X25519.
This assembly is in gas syntax so is not built on Windows nor when
OPENSSL_SMALL is defined.

Change-Id: I1050cf1b16350fd4b758e4c463261b30a1b65390
Reviewed-on: https://boringssl-review.googlesource.com/6782
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 16:22:38 +00:00
Matt Braithwaite c75c0ae088 Add #defines for ED25519 key and signature lengths.
Change-Id: I3299f8fc4602c24688339dbffb1d7939282ad6b3
Reviewed-on: https://boringssl-review.googlesource.com/6723
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 16:06:07 +00:00
David Benjamin 48cce66aac Tidy up ssl3_get_server_key_exchange slightly.
Single-use BN_CTXs are unnecessary.

Change-Id: I2d59aae2168e43937c5d527794c335ed2809d547
Reviewed-on: https://boringssl-review.googlesource.com/6766
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:25:45 +00:00
David Benjamin c1cc858af2 Check for EC_KEY_set_public_key error.
This function may fail on malloc error.

Change-Id: I8631b1763dac5a3801fcaca81bdfcb8d24d3728c
Reviewed-on: https://boringssl-review.googlesource.com/6765
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:24:24 +00:00
David Benjamin 4cc671cbf4 Add CBB_reserve and CBB_did_write.
These will be needed when we start writing variable-length things to a
CBB.

Change-Id: Ie7b9b140f5f875b43adedc8203ce9d3f4068dfea
Reviewed-on: https://boringssl-review.googlesource.com/6764
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:23:52 +00:00
David Benjamin e13263d5e4 Resolve a few old TODOs.
A lot of commented-out code we haven't had to put them back, so these
can go now. Also remove the TODO about OAEP having a weird API. The API
is wrong, but upstream's shipped it with the wrong API, so that's what
it is now.

Change-Id: I7da607cf2d877cbede41ccdada31380f812f6dfa
Reviewed-on: https://boringssl-review.googlesource.com/6763
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:14:35 +00:00
David Benjamin 841934f079 Remove stack macros for nonexistent types.
There's a few that can't work since the types don't even exist.

Change-Id: Idf860b146439c95d33814d25bbc9b8f61774b569
Reviewed-on: https://boringssl-review.googlesource.com/6762
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:12:38 +00:00
David Benjamin 70ab223490 Remove ASN1_R_MALLOC_FAILURE.
There was a TODO to remove it once asn1_mac.h was trimmed. This has now
happened. Remove it and reset error codes for crypto/asn1.

Change-Id: Iaf2f3e75741914415372939471b135618910f95d
Reviewed-on: https://boringssl-review.googlesource.com/6761
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:12:24 +00:00
David Benjamin b965c63acb Reject calls to X509_verify_cert that have not been reinitialised
The function X509_verify_cert checks the value of |ctx->chain| at the
beginning, and if it is NULL then it initialises it, along with the value
of |ctx->untrusted|. The normal way to use X509_verify_cert() is to first
call X509_STORE_CTX_init(); then set up various parameters etc; then call
X509_verify_cert(); then check the results; and finally call
X509_STORE_CTX_cleanup(). The initial call to X509_STORE_CTX_init() sets
|ctx->chain| to NULL. The only place in the OpenSSL codebase  where
|ctx->chain| is set to anything other than a non NULL value is in
X509_verify_cert itself. Therefore the only ways that |ctx->chain| could be
non NULL on entry to X509_verify_cert is if one of the following occurs:
1) An application calls X509_verify_cert() twice without re-initialising
in between.
2) An application reaches inside the X509_STORE_CTX structure and changes
the value of |ctx->chain| directly.

With regards to the second of these, we should discount this - it should
not be supported to allow this.

With regards to the first of these, the documentation is not exactly
crystal clear, but the implication is that you must call
X509_STORE_CTX_init() before each call to X509_verify_cert(). If you fail
to do this then, at best, the results would be undefined.

Calling X509_verify_cert() with |ctx->chain| set to a non NULL value is
likely to have unexpected results, and could be dangerous. This commit
changes the behaviour of X509_verify_cert() so that it causes an error if
|ctx->chain| is anything other than NULL (because this indicates that we
have not been initialised properly). It also clarifies the associated
documentation.

(Imported from upstream's 692f07c3e0c04180b56febc2feb57cd94395a7a2.)

Change-Id: I971f1a305f12bbf9f4ae955313d5557368f0d374
Reviewed-on: https://boringssl-review.googlesource.com/6760
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:12:00 +00:00
David Benjamin 3f5b43df07 Simplify RSA key exchange padding check.
This check was fixed a while ago, but it could have been much simpler.

In the RSA key exchange, the expected size of the output is known, making the
padding check much simpler. There isn't any use in exporting the more general
RSA_message_index_PKCS1_type_2. (Without knowing the expected size, any
integrity check or swap to randomness or other mitigation is basically doomed
to fail.)

Verified with the valgrind uninitialized memory trick that we're still
constant-time.

Also update rsa.h to recommend against using the PKCS#1 v1.5 schemes.

Thanks to Ryan Sleevi for the suggestion.

Change-Id: I4328076b1d2e5e06617dd8907cdaa702635c2651
Reviewed-on: https://boringssl-review.googlesource.com/6613
Reviewed-by: Adam Langley <agl@google.com>
2015-12-22 00:10:14 +00:00
Luke Granger-Brown 3ef608594d Refuse to parse RSA pubkeys with invalid exponents.
We should reject RSA public keys with exponents of less than 3.

This change also rejects even exponents, although the usefulness
of such a public key is somewhat questionable.

BUG=chromium:541257

Change-Id: I1499e9762ba40a7cf69155d21d55bc210cd6d273
Reviewed-on: https://boringssl-review.googlesource.com/6710
Reviewed-by: Adam Langley <agl@google.com>
2015-12-21 23:49:02 +00:00
David Benjamin afe57cb14d Add a tool to generate Ed25519 keys.
Make it slightly easier for people to use.

Change-Id: I567e95bf1a5c203170a0b9732fd522fcbe5b7bc1
Reviewed-on: https://boringssl-review.googlesource.com/6773
Reviewed-by: Adam Langley <agl@google.com>
2015-12-18 23:34:13 +00:00
Adam Langley 77c3c0b025 Enable Ed25519 when building with OPENSSL_SMALL.
OPENSSL_SMALL will still cause the smaller base-point table to be used
and so won't be as fast at signing as the full version, but Ed25519 will
now work in those builds.

Without OPENSSL_SMALL:

Did 20000 Ed25519 key generation operations in 1008347us (19834.4 ops/sec)
Did 20000 Ed25519 signing operations in 1025594us (19500.9 ops/sec)
Did 6138 Ed25519 verify operations in 1001712us (6127.5 ops/sec)
Did 21000 Curve25519 base-point multiplication operations in 1019237us (20603.6 ops/sec)
Did 7095 Curve25519 arbitrary point multiplication operations in 1065986us (6655.8 ops/sec)

With (on the same machine):

Did 8415 Ed25519 key generation operations in 1020958us (8242.3 ops/sec)
Did 8952 Ed25519 signing operations in 1077635us (8307.1 ops/sec)
Did 6358 Ed25519 verify operations in 1047533us (6069.5 ops/sec)
Did 6620 Curve25519 base-point multiplication operations in 1008922us (6561.5 ops/sec)
Did 7183 Curve25519 arbitrary point multiplication operations in 1096285us (6552.1 ops/sec)

Change-Id: Ib443c0e2bdfd11e044087e66efd55b651a5667e7
Reviewed-on: https://boringssl-review.googlesource.com/6772
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-12-18 23:15:33 +00:00
David Benjamin 9f897b2580 Remove the stitched RC4-MD5 code and use the generic one.
This removes 16k from a release-mode build of the bssl tool. Now that we've
finished the AEAD refactor, there's no use in keeping this around as a
prototype for "stateful AEADs".

Before:
Did 2264000 RC4-MD5 (16 bytes) seal operations in 1000430us (2263026.9 ops/sec): 36.2 MB/s
Did 266000 RC4-MD5 (1350 bytes) seal operations in 1000984us (265738.5 ops/sec): 358.7 MB/s
Did 50000 RC4-MD5 (8192 bytes) seal operations in 1014209us (49299.5 ops/sec): 403.9 MB/s
After:
Did 1895000 RC4-MD5 (16 bytes) seal operations in 1000239us (1894547.2 ops/sec): 30.3 MB/s
Did 199000 RC4-MD5 (1350 bytes) seal operations in 1001361us (198729.5 ops/sec): 268.3 MB/s
Did 39000 RC4-MD5 (8192 bytes) seal operations in 1014832us (38430.0 ops/sec): 314.8 MB/s

There is a non-trivial performance hit, but this cipher doesn't matter much and
the stitched mode code reaches into MD5_CTX and RC4_KEY in somewhat unfortunate
ways.

Change-Id: I9ecd28d6afb54e90ce61baecc641742af2ae6269
Reviewed-on: https://boringssl-review.googlesource.com/6752
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:57:42 +00:00
David Benjamin 1741a9d143 Save some mallocs in computing the MAC for e_tls.c.
We can reuse the HMAC_CTX that stores the key. The API is kind of unfortunate
as, in principle, it should be possible to do an allocation-averse HMAC with a
shared key on multiple threads at once (EVP_AEAD_CTX is normally logically
const). At some point it may be worth rethinking those APIs somewhat.  But
these "stateful AEADs" are already stateful in their EVP_CIPHER_CTX, so this is
fine.

Each cipher was run individually to minimize the effect of other ciphers doing
their mallocs. (Although the cost of a malloc is presumably going to depend a
lot on the malloc implementation and what's happened before in the process, so
take these numbers with a bucket of salt. They vary widely even with the same
arguments.)

Taking malloc out of seal/open also helps with the malloc tests. DTLS currently
cannot distinguish a malloc failure (should be fatal) from a decryption failure
(not fatal), so the malloc tests get stuck. But this doesn't completely get us
there since tls_cbc.c mallocs. This also assumes EVP_CIPHER_CTX, EVP_MD_CTX,
and HMAC_CTX are all clever about reusing their allocations when reset (which
they are).

Before:
Did 1315000 AES-128-CBC-SHA1 (16 bytes) seal operations in 1000087us (1314885.6 ops/sec): 21.0 MB/s
Did 181000 AES-128-CBC-SHA1 (1350 bytes) seal operations in 1004918us (180114.2 ops/sec): 243.2 MB/s
Did 34000 AES-128-CBC-SHA1 (8192 bytes) seal operations in 1024250us (33195.0 ops/sec): 271.9 MB/s
After:
Did 1766000 AES-128-CBC-SHA1 (16 bytes) seal operations in 1000319us (1765436.8 ops/sec): 28.2 MB/s
Did 187000 AES-128-CBC-SHA1 (1350 bytes) seal operations in 1004002us (186254.6 ops/sec): 251.4 MB/s
Did 35000 AES-128-CBC-SHA1 (8192 bytes) seal operations in 1014885us (34486.7 ops/sec): 282.5 MB/s

Before:
Did 391000 DES-EDE3-CBC-SHA1 (16 bytes) seal operations in 1000038us (390985.1 ops/sec): 6.3 MB/s
Did 16000 DES-EDE3-CBC-SHA1 (1350 bytes) seal operations in 1060226us (15091.1 ops/sec): 20.4 MB/s
Did 2827 DES-EDE3-CBC-SHA1 (8192 bytes) seal operations in 1035971us (2728.8 ops/sec): 22.4 MB/s
After:
Did 444000 DES-EDE3-CBC-SHA1 (16 bytes) seal operations in 1001814us (443196.0 ops/sec): 7.1 MB/s
Did 17000 DES-EDE3-CBC-SHA1 (1350 bytes) seal operations in 1042535us (16306.4 ops/sec): 22.0 MB/s
Did 2590 DES-EDE3-CBC-SHA1 (8192 bytes) seal operations in 1012378us (2558.3 ops/sec): 21.0 MB/s

Before:
Did 1316000 AES-256-CBC-SHA1 (16 bytes) seal operations in 1000510us (1315329.2 ops/sec): 21.0 MB/s
Did 157000 AES-256-CBC-SHA1 (1350 bytes) seal operations in 1002944us (156539.1 ops/sec): 211.3 MB/s
Did 29000 AES-256-CBC-SHA1 (8192 bytes) seal operations in 1030284us (28147.6 ops/sec): 230.6 MB/s
After:
Did 1645000 AES-256-CBC-SHA1 (16 bytes) seal operations in 1000313us (1644485.3 ops/sec): 26.3 MB/s
Did 162000 AES-256-CBC-SHA1 (1350 bytes) seal operations in 1003060us (161505.8 ops/sec): 218.0 MB/s
Did 36000 AES-256-CBC-SHA1 (8192 bytes) seal operations in 1014819us (35474.3 ops/sec): 290.6 MB/s

Before:
Did 1435000 RC4-SHA1 (16 bytes) seal operations in 1000245us (1434648.5 ops/sec): 23.0 MB/s
Did 207000 RC4-SHA1 (1350 bytes) seal operations in 1004675us (206036.8 ops/sec): 278.1 MB/s
Did 38000 RC4-SHA1 (8192 bytes) seal operations in 1022712us (37156.1 ops/sec): 304.4 MB/s
After:
Did 1853000 RC4-SHA1 (16 bytes) seal operations in 1000433us (1852198.0 ops/sec): 29.6 MB/s
Did 206000 RC4-SHA1 (1350 bytes) seal operations in 1002370us (205512.9 ops/sec): 277.4 MB/s
Did 42000 RC4-SHA1 (8192 bytes) seal operations in 1024209us (41007.3 ops/sec): 335.9 MB/s

Change-Id: I0edb89bddf146cf91a8e7a99c56b2278c8f38094
Reviewed-on: https://boringssl-review.googlesource.com/6751
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:56:28 +00:00
David Benjamin df571631cc Add RC4-SHA1 and DES-EDE3-CBC-SHA1 to bssl speed.
For completeness. In so far as we care about legacy ciphers' performance at
all, we should have the others too.

Change-Id: Idd2d93345f3af8b6ac5772a1cb3c201f84fe3197
Reviewed-on: https://boringssl-review.googlesource.com/6750
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:53:23 +00:00
David Benjamin 13414b3a04 Implement draft-ietf-tls-chacha20-poly1305-04.
Only ECDHE-based ciphers are implemented. To ease the transition, the
pre-standard cipher shares a name with the standard one. The cipher rule parser
is hacked up to match the name to both ciphers. From the perspective of the
cipher suite configuration language, there is only one cipher.

This does mean it is impossible to disable the old variant without a code
change, but this situation will be very short-lived, so this is fine.

Also take this opportunity to make the CK and TXT names align with convention.

Change-Id: Ie819819c55bce8ff58e533f1dbc8bef5af955c21
Reviewed-on: https://boringssl-review.googlesource.com/6686
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:34:56 +00:00
David Benjamin 37489902ba Implement draft-ietf-tls-chacha20-poly1305-04 in Go.
This will be used to test the C implementation against.

Change-Id: I2d396d27630937ea610144e381518eae76f78dab
Reviewed-on: https://boringssl-review.googlesource.com/6685
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:33:54 +00:00
David Benjamin 2089fdd10e Implement RFC 7539 in Go.
In preparation for a Go implementation of the new TLS ciphers to test
against, implement the AEAD primitive.

Change-Id: I69b5b51257c3de16bdd36912ed2bc9d91ac853c8
Reviewed-on: https://boringssl-review.googlesource.com/6684
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:33:39 +00:00
David Benjamin 86e412dc18 Add client cert support to bssl client.
Handy to test servers with misbehaving client auth.

Change-Id: I93f7b77c35e223761edade648bc03d1f97ed82fd
Reviewed-on: https://boringssl-review.googlesource.com/6614
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 23:15:41 +00:00
David Benjamin 23a681b9f9 Fix build.
There were a couple more asm lines to turn into __asm__ when the patches got
reordered slightly.

Change-Id: I44be5caee6d09bb3db5dea4791592b12d175822c
Reviewed-on: https://boringssl-review.googlesource.com/6741
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:26:12 +00:00
David Benjamin e3203923b5 Rename the Go ChaCha20-Poly1305 implementation.
In preparation for implementing the RFC 7539 variant to test against.

Change-Id: I0ce5e856906e00925ad1d849017f9e7fda087a8e
Reviewed-on: https://boringssl-review.googlesource.com/6683
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:24:00 +00:00
David Benjamin 8ffab72683 Point EVP_aead_chacha20_poly1305 at the standardized version.
The consumers have all been updated, so we can move EVP_aead_chacha20_poly1305
to its final state. Unfortunately, the _rfc7539-suffixed version will need to
stick around for just a hair longer. Also the tls1.h macros, but the remaining
consumers are okay with that changing underneath them.

Change-Id: Ibbb70ec1860d6ac6a7e1d7b45e70fe692bf5ebe5
Reviewed-on: https://boringssl-review.googlesource.com/6600
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:22:11 +00:00
David Benjamin fef6fb592b Fix ChaCha20-Poly1305 tests.
https://boringssl-review.googlesource.com/6101 was mismerged from *ring* and
lost some tests. Also add the corresponding tag truncation tests for the new
construction. So long as we have that feature, we should have tests for it.
(Although, do we actually need to support it?)

Change-Id: I70784cbac345e0ad11b496102856c53932b7362e
Reviewed-on: https://boringssl-review.googlesource.com/6682
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:20:49 +00:00
David Benjamin 60a08ac211 Remove unreachable code to duplicate DH keys.
dh_tmp can only contain parameters, now that DHE always generates keys fresh
for each connection.

Change-Id: I56dad4cbec7e21326360d79df211031fd9734004
Reviewed-on: https://boringssl-review.googlesource.com/6702
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:20:12 +00:00
David Benjamin 4ec0cce743 Slightly tweak some array allocations.
clang scan-build is annoyed it's not obvious the sizeof line matches the
pointer type. This is easy to fix and makes it be quiet.

Change-Id: Iec80d2a087f81179c88cae300f56d3f76b32b347
Reviewed-on: https://boringssl-review.googlesource.com/6701
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:19:32 +00:00
David Benjamin 2936170d68 Fix memory leak in DSA redo case.
Found by clang scan-build.

Change-Id: I44a9d5ea165ede836c72aed8725d0bb0981b1004
Reviewed-on: https://boringssl-review.googlesource.com/6700
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:17:09 +00:00
David Benjamin a01deee96b Make CBB_len relative to its argument.
Rather than the length of the top-level CBB, which is kind of odd when ASN.1
length prefixes are not yet determined, return the number of bytes written to
the CBB so far. This can be computed without increasing the size of CBB at all.
Have offset and pending_*.

This means functions which take in a CBB as argument will not be sensitive to
whether the CBB is a top-level or child CBB. The extensions logic had to be
careful to only ever compare differences of lengths, which was awkward.

The reversal will also allow for the following pattern in the future, once
CBB_add_space is split into, say, CBB_reserve and CBB_did_write and we add a
CBB_data:

  uint8_t *signature;
  size_t signature_len = 0;
  if (!CBB_add_asn1(out, &cert, CBB_ASN1_SEQUENCE) ||
      /* Emit the TBSCertificate. */
      !CBB_add_asn1(&cert, &tbs_cert, CBS_ASN1_SEQUENCE) ||
      !CBB_add_tbs_cert_stuff(&tbs_cert, stuff) ||
      !CBB_flush(&cert) ||
      /* Feed it into md_ctx. */
      !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
      !EVP_DigestSignUpdate(&md_ctx, CBB_data(&cert), CBB_len(&cert)) ||
      /* Emit the signature algorithm. */
      !CBB_add_asn1(&cert, &sig_alg, CBS_ASN1_SEQUENCE) ||
      !CBB_add_sigalg_stuff(&sig_alg, other_stuff) ||
      /* Emit the signature. */
      !EVP_DigestSignFinal(&md_ctx, NULL, &signature_len) ||
      !CBB_reserve(&cert, &signature, signature_len) ||
      !EVP_DigestSignFinal(&md_ctx, signature, &signature_len) ||
      !CBB_did_write(&cert, signature_len)) {
    goto err;
  }

(Were TBSCertificate not the first field, we'd still have to sample
CBB_len(&cert), but at least that's reasonable straight-forward. The
alternative would be if CBB_data and CBB_len somehow worked on
recently-invalidated CBBs, but that would go wrong once the invalidated CBB's
parent flushed and possibly shifts everything.)

And similar for signing ServerKeyExchange.

Change-Id: I7761e492ae472d7632875b5666b6088970261b14
Reviewed-on: https://boringssl-review.googlesource.com/6681
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 21:16:12 +00:00
Adam Langley 77385bb43d Mark platform-specific HOST_[c2l|l2c] as (void).
I skipped a patch when landing and so 793c21e2 caused a build failure
when platform-specific versions of these macros were used.

Change-Id: I8ed6dbb92a511ef306d45087c3eb87781fdfed31
Reviewed-on: https://boringssl-review.googlesource.com/6740
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 20:16:46 +00:00
David Benjamin 6969971fef Remove a dead prototype.
Change-Id: I05cf52b31bd532505393e9a1ccae27f89f81f6f4
Reviewed-on: https://boringssl-review.googlesource.com/6680
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 20:03:53 +00:00
David Benjamin 1b36716ce2 Remove crypto/header_removed.h.
This is a remnant from when the headers in include/ where still
symlinks.

Change-Id: Ice27c412c0cdcc43312f5297119678091dcd5d38
Reviewed-on: https://boringssl-review.googlesource.com/6670
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 20:03:40 +00:00
David Benjamin 017231a544 Remove asm __asm__ define.
It's only used in one file. No sense in polluting the namespace here.

Change-Id: Iaf3870a4be2d2cad950f4d080e25fe7f0d3929c7
Reviewed-on: https://boringssl-review.googlesource.com/6660
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 20:03:17 +00:00
David Benjamin 793c21e266 Make HOST_l2c return void.
Nothing ever uses the return value. It'd be better off discarding it rather
than make callers stick (void) everywhere.

Change-Id: Ia28c970a1e5a27db441e4511249589d74408849b
Reviewed-on: https://boringssl-review.googlesource.com/6653
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 20:02:37 +00:00
David Benjamin 0aff3ffb88 Store the partial block as uint8_t, not uint32_t.
The uint32_t likely dates to them using HASH_LONG everywhere. Nothing ever
touches c->data as a uint32_t, only bytes. (Which makes sense seeing as it
stores the partial block.)

Change-Id: I634cb7f2b6306523aa663f8697b7dc92aa491320
Reviewed-on: https://boringssl-review.googlesource.com/6651
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 19:59:29 +00:00
David Benjamin 5a19d7dfa8 Use the straight-forward ROTATE macro.
I would hope any sensible compiler would recognize the rotation. (If
not, we should at least pull this into crypto/internal.h.) Confirmed
that clang at least produces the exact same instructions for
sha256_block_data_order for release + NO_ASM. This is also mostly moot
as SHA-1 and SHA-256 both have assembly versions on x86 that sidestep
most of this.

For the digests, take it out of md32_common.h since it doesn't use the
macro. md32_common.h isn't sure whether it's a multiply-included header
or not. It should be, but it has an #include guard (doesn't quite do
what you'd want) and will get HOST_c2l, etc., confused if one tries to
include it twice.

Change-Id: I1632801de6473ffd2c6557f3412521ec5d6b305c
Reviewed-on: https://boringssl-review.googlesource.com/6650
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 19:57:31 +00:00
David Benjamin 78fefbf3bb Reformat md32_common.h, part 2.
Manual tweaks and then clang-formatted again.

Change-Id: I809fdb71b2135343e5c1264dd659b464780fc54a
Reviewed-on: https://boringssl-review.googlesource.com/6649
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 19:52:06 +00:00
David Benjamin fea1137e55 Reformat md32_common.h, part 1.
We've tweaked it already and upstream's using a different indentation
style now anyway. This is the first of two commits. For verifiability,
this is the output of clang-format with no modifications.

Change-Id: Ia30f20bee0cc8046aedf9ac7106cc4630e8d93e6
Reviewed-on: https://boringssl-review.googlesource.com/6648
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 19:47:50 +00:00
David Benjamin 871fff076b *_Update of length zero is legal.
We can slightly simplify tls1_P_hash. (Confirmed md32_common.h emits
code with the check.)

Change-Id: I0293ceaaee261a7ac775b42a639f7a9f67705456
Reviewed-on: https://boringssl-review.googlesource.com/6647
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 19:46:57 +00:00
David Benjamin d9f0671bbe Remove |need_record_splitting| from |SSL3_STATE|.
It is redundant given the other state in the connection.

Change-Id: I5dc71627132659ab4316a5ea360c9ca480fb7c6c
Reviewed-on: https://boringssl-review.googlesource.com/6646
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 18:45:48 +00:00
David Benjamin cd480380fa Remove unused fields from SSL3_STATE.
These have been unused since we unified everything on EVP_AEAD. I must
have missed them when clearing out dead state. This shaves 136 bytes of
per-connection state.

Change-Id: I705f8de389fd34ab4524554ee9e4b1d6be198994
Reviewed-on: https://boringssl-review.googlesource.com/6645
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 18:42:56 +00:00
David Benjamin 7fc010014c Slightly simplify SSL3_RECORD.
There's no need to track consumed bytes, so rr->data and rr->off may be
merged together.

Change-Id: I8842d005665ea8b4d4a0cced941f3373872cdac4
Reviewed-on: https://boringssl-review.googlesource.com/6644
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 18:41:59 +00:00
David Benjamin ece5ba2797 Reset ssl error codes.
38 error codes have fallen off the list since the last time we did this.

Change-Id: Id7ee30889a5da2f6ab66957fd8e49e97640c8489
Reviewed-on: https://boringssl-review.googlesource.com/6643
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 18:38:20 +00:00
David Benjamin a41280d8cb Pull ChangeCipherSpec into the handshake state machine.
This uses ssl3_read_bytes for now. We still need to dismantle that
function and then invert the handshake state machine, but this gets
things closer to the right shape as an intermediate step and is a large
chunk in itself. It simplifies a lot of the CCS/handshake
synchronization as a lot of the invariants much more clearly follow from
the handshake itself.

Tests need to be adjusted since this changes some error codes. Now all
the CCS/Handshake checks fall through to the usual
SSL_R_UNEXPECTED_RECORD codepath. Most of what used to be a special-case
falls out naturally. (If half of Finished was in the same record as the
pre-CCS message, that part of the handshake record would have been left
unconsumed, so read_change_cipher_spec would have noticed, just like
read_app_data would have noticed.)

Change-Id: I15c7501afe523d5062f0e24a3b65f053008d87be
Reviewed-on: https://boringssl-review.googlesource.com/6642
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 18:36:57 +00:00
David Benjamin 8fd5c23218 Simplify fragmented HelloRequest state.
With server-side renegotiation gone, handshake_fragment's only purpose
in life is to handle a fragmented HelloRequest (we probably do need to
support those if some server does 1/n-1 record-splitting on handshake
records). The logic to route the data into
ssl3_read_bytes(SSL3_RT_HANDSHAKE) never happens, and the contents are
always a HelloRequest prefix.

This also trims a tiny bit of per-connection state.

Change-Id: Ia1b0dda5b7e79d817c28da1478640977891ebc97
Reviewed-on: https://boringssl-review.googlesource.com/6641
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:45:31 +00:00
David Benjamin ef5dfd2980 Add tests for malformed HelloRequests.
Change-Id: Iff053022c7ffe5b01c0daf95726cc7d49c33cbd6
Reviewed-on: https://boringssl-review.googlesource.com/6640
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:40:29 +00:00
David Benjamin 8411b248c3 Add tests for bad ChangeCipherSpecs.
Change-Id: I7eac3582b7b23b5da95be68277609cfa63195b02
Reviewed-on: https://boringssl-review.googlesource.com/6629
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:39:43 +00:00
David Benjamin 502a843dee Switch unrolled loop in BN_usub with memcpy.
See also upstream's 06cf881a3a10d5af3c1255c08cfd0c6ddb5f1cc3,
9f040d6decca7930e978784c917f731e5c45e8f0, and
9f6795e7d2d1e35668ad70ba0afc480062be4e2e.

Change-Id: I27d90e382867a5fe988d152b31f8494e001a6a9f
Reviewed-on: https://boringssl-review.googlesource.com/6628
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:38:48 +00:00
David Benjamin c3ae38b4f8 Remove DH EVP_PKEY hooks.
They would never work. Better notice when callers depend on it than fail at
runtime.

This depends on https://android-review.googlesource.com/#/c/183610/ in
Conscrypt.

Change-Id: I3411f291416df834cf85850890617625a2e76939
Reviewed-on: https://boringssl-review.googlesource.com/6552
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:38:06 +00:00
Nico Weber 7100ee9832 Chromium's update.sh is dead, long live update.py
update.py used to be used only on Windows until very recently, but
Windows and non-Windows have been at the same clang revision for
a while now.  So even a few months ago update.py and update.sh
would've contained the same clang revision.

BUG=chromium:494442

Change-Id: Ie9127a1c49e31a7810ee431f8e662350c245917c
Reviewed-on: https://boringssl-review.googlesource.com/6620
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 17:30:31 +00:00
David Benjamin f28dd64d43 Fix flaky BadRSAClientKeyExchange-1 test.
Sometimes BadRSAClientKeyExchange-1 fails with DATA_TOO_LARGE_FOR_MODULUS if
the corruption brings the ciphertext above the RSA modulus. Ensure this does
not happen.

Change-Id: I0d8ea6887dfcab946fdf5d38f5b196f5a927c4a9
Reviewed-on: https://boringssl-review.googlesource.com/6731
Reviewed-by: Adam Langley <agl@google.com>
2015-12-16 15:40:18 +00:00
David Benjamin 423488557c Remove unused functions.
Change-Id: I48d6db3b2e521c726962c291cce7baa029e09623
Reviewed-on: https://boringssl-review.googlesource.com/6627
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 21:32:44 +00:00
David Benjamin 45dab251f3 Skip free callbacks on empty CRYPTO_EX_DATAs.
Avoids bouncing on the lock, but it doesn't really matter since it's all
taking read locks. If we're declaring that callbacks don't get to see
every object being created, they shouldn't see every object being
destroyed.

CRYPTO_dup_ex_data also already had this optimization, though it wasn't
documented.

BUG=391192

Change-Id: I5b8282335112bca3850a7c0168f8bd7f7d4a2d57
Reviewed-on: https://boringssl-review.googlesource.com/6626
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 21:32:14 +00:00
David Benjamin 8a58933db0 Remove the CRYPTO_EX_new callback.
This callback is never used. The one caller I've ever seen is in Android
code which isn't built with BoringSSL and it was a no-op.

It also doesn't actually make much sense. A callback cannot reasonably
assume that it sees every, say, SSL_CTX created because the index may be
registered after the first SSL_CTX is created. Nor is there any point in
an EX_DATA consumer in one file knowing about an SSL_CTX created in
completely unrelated code.

Replace all the pointers with a typedef to int*. This will ensure code
which passes NULL or 0 continues to compile while breaking code which
passes an actual function.

This simplifies some object creation functions which now needn't worry
about CRYPTO_new_ex_data failing. (Also avoids bouncing on the lock, but
it's taking a read lock, so this doesn't really matter.)

BUG=391192

Change-Id: I02893883c6fa8693682075b7b130aa538a0a1437
Reviewed-on: https://boringssl-review.googlesource.com/6625
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 21:29:46 +00:00
David Benjamin 0abd6f2eb6 Get struct timeval from sys/time.h.
The naclports patch switches sys/types.h to sys/time.h. Per
http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/time.h.html
this is correct.

Change-Id: If6d56cb28fa16a1d8b4515a45532434f6c23a29d
Reviewed-on: https://boringssl-review.googlesource.com/6624
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 20:32:36 +00:00
David Benjamin 1246670caa Use UINT64_C in sha512.c table.
From the naclports patch:
https://chromium.googlesource.com/external/naclports/+/master/ports/boringssl/nacl.patch

Change-Id: I37ad45fbde0b1b1437d3abd8ed7422bd72cfd959
Reviewed-on: https://boringssl-review.googlesource.com/6623
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 20:30:10 +00:00
David Benjamin 5ddffbb8bc Make SSL_(CTX_)?set_tmp_ecdh call SSL_(CTX_)?set1_curves.
Then deprecate the old functions. Thanks to upstream's
6977e8ee4a718a76351ba5275a9f0be4e530eab5 for the idea.

Change-Id: I916abd6fca2a3b2a439ec9902d9779707f7e41eb
Reviewed-on: https://boringssl-review.googlesource.com/6622
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 20:28:47 +00:00
David Benjamin 53e5c2c225 Remove SSL_(CTX_)?set_ecdh_callback.
It has no callers. I prepped for its removal earlier with
https://android.googlesource.com/platform/external/conscrypt/+/c05697c2c50fe1331f08c6f32d0bc9636eecdc2d
and then completely forgot.

Thanks to upstream's 6f78b9e824c053d062188578635c575017b587c5 for
the reminder. Quoth them:

> This only gets used to set a specific curve without actually checking
> that the peer supports it or not and can therefor result in handshake
> failures that can be avoided by selecting a different cipher.

It's also a very confusing API since it does NOT pass ownership of the
EC_KEY to the caller.

Change-Id: I6a00643b3a2d6746e9e0e228b47c2bc9694b0084
Reviewed-on: https://boringssl-review.googlesource.com/6621
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 20:07:37 +00:00
David Benjamin 756ad17337 Initialize |one_index| in OAEP padding check.
This was a mistake in https://boringssl-review.googlesource.com/6611.

Change-Id: Ifb5c52cc7571b6f1ada4af9b46eab1f9b080b4f6
Reviewed-on: https://boringssl-review.googlesource.com/6730
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:46:39 +00:00
David Benjamin 1634a33495 Convert rsa/padding.c to constant-time helpers.
Remove the custom copy of those helpers.

Change-Id: I810c3ae8dbf7bc0654d3e9fb9900c425d36f64aa
Reviewed-on: https://boringssl-review.googlesource.com/6611
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:39:37 +00:00
David Benjamin b36a395a9a Add slightly better RSA key exchange tests.
Cover not just the wrong version, but also other mistakes.

Change-Id: I46f05a9a37b7e325adc19084d315a415777d3a46
Reviewed-on: https://boringssl-review.googlesource.com/6610
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:26:28 +00:00
David Benjamin 0bd71eb85d Remove weird ret negation logic.
This is a remnant of ssl3_get_client_hello's old DTLS cookie logic, which has
since been removed. (If we ever need HelloVerifyRequest support on the server,
we'll implement something stateless in front.) We can switch this to something
more straightforward now.

See also upstream's 94f98a9019e1c0a3be4ca904b2c27c7af3d937c0,

Change-Id: Ie733030209a381a4915d6744fa12a79ffe972fa5
Reviewed-on: https://boringssl-review.googlesource.com/6601
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:24:51 +00:00
David Benjamin e9cddb8879 Remove SSL_OP_LEGACY_SERVER_CONNECT.
I don't think we're ever going to manage to enforce this, and it doesn't
seem worth the trouble. We don't support application protocols which use
renegotiation outside of the HTTP/1.1 mid-stream client auth hack.
There, it's on the server to reject legacy renegotiations.

This removes the last of SSL_OP_ALL.

Change-Id: I996fdeaabf175b6facb4f687436549c0d3bb0042
Reviewed-on: https://boringssl-review.googlesource.com/6580
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:22:53 +00:00
David Benjamin 3e052de5a0 Tighten SSL_OP_LEGACY_SERVER_CONNECT to align with RFC 5746.
RFC 5746 forbids a server from downgrading or upgrading
renegotiation_info support. Even with SSL_OP_LEGACY_SERVER_CONNECT set
(the default), we can still enforce a few things.

I do not believe this has practical consequences. The attack variant
where the server half is prefixed does not involve a renegotiation on
the client. The converse where the client sees the renegotiation and
prefix does, but we only support renego for the mid-stream HTTP/1.1
client auth hack, which doesn't do this. (And with triple-handshake,
HTTPS clients should be requiring the certificate be unchanged across
renego which makes this moot.)

Ultimately, an application which makes the mistake of using
renegotiation needs to be aware of what exactly that means and how to
handle connection state changing mid-stream. We make renego opt-in now,
so this is a tenable requirement.

(Also the legacy -> secure direction would have been caught by the
server anyway since we send a non-empty RI extension.)

Change-Id: I915965c342f8a9cf3a4b6b32f0a87a00c3df3559
Reviewed-on: https://boringssl-review.googlesource.com/6559
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:17:56 +00:00
David Benjamin 03f000577f Remove SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.
This dates to SSLeay 0.8.0 (or earlier). The use counter sees virtually
no hits.

Change-Id: Iff4c8899d5cb0ba4afca113c66d15f1d980ffe41
Reviewed-on: https://boringssl-review.googlesource.com/6558
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:14:00 +00:00
David Benjamin ef5e515819 Remove SSL_OP_TLS_D5_BUG.
This dates to SSLeay 0.9.0. The Internet seems to have completely
forgotten what "D5" is. (I can't find reference to it beyond
documentation of this quirk.) The use counter we added sees virtually no
hits.

Change-Id: I9781d401acb98ce3790b1b165fc257a6f5e9b155
Reviewed-on: https://boringssl-review.googlesource.com/6557
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:11:41 +00:00
David Benjamin c100ef4379 Limit depth of ASN1 parse printing.
(Imported from upstream's d88ef40a1e5c81d0d32b4a431e55f5456e678dd2 and
943c4ca62b3f5a160340d57aecb9413407a06e15.)

Change-Id: Idd52aebae6839695be0f3a8a7659adeec6650b98
Reviewed-on: https://boringssl-review.googlesource.com/6556
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:06:04 +00:00
David Benjamin 2205093e7e Add a comment in SetTestState from bssl_shim.
Per Nico's comment in https://boringssl-review.googlesource.com/#/c/3342/3/ssl/test/bssl_shim.cc.

Also remove unnecessary cast and change the variable name to |state|. |async|
is a remnant from when it was |AsyncState| rather than |TestState|.

Change-Id: I83f23593b0c4e64b0ddd056573f75c0aabe96f9e
Reviewed-on: https://boringssl-review.googlesource.com/6555
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:05:46 +00:00
Piotr Sikora 6ae67dfee8 Don't leak Android hacks to other build platforms.
Previously, android_compat_hacks.c and android_compat_keywrap.c
were added to crypto_sources when multiple build platforms were
specified in one invocation.

Change-Id: I4fd8bffc4785bef0148d12cd6f292d79c043b806
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Reviewed-on: https://boringssl-review.googlesource.com/6566
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 19:02:31 +00:00
Brian Smith a0ef7b0a56 Enforce that |EC_KEY| private key is in [0, group->order).
Change-Id: I16abea5769737c7edd1be717f9a4f38678af43ce
Reviewed-on: https://boringssl-review.googlesource.com/6564
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 18:45:03 +00:00
Brian Smith 533a273871 Add |EC_METHOD| method for verifying public key order.
In some cases it would be good to restrict the input range of scalars
given to |EC_METHOD::mul| to be [0, order-1]. This is a first step
towards that goal.

Change-Id: I58a25db06f6c7a68a0ac1fe79794b04f7a173b23
Reviewed-on: https://boringssl-review.googlesource.com/6562
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 18:39:07 +00:00
Brian Smith a3d9de05fb Add |EC_GROUP_get0_order| to replace |EC_GROUP_get_order|.
|EC_GROUP_get0_order| doesn't require any heap allocations and never
fails, so it is much more convenient and more efficient for callers to
call.

Change-Id: Ic60f768875e7bc8e74362dacdb5cbbc6957b05a6
Reviewed-on: https://boringssl-review.googlesource.com/6532
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 18:18:13 +00:00
Sam Clegg 88478562a4 Include <sys/time.h> in packeted_bio.h for 'timeval'
At least for newlib (Native Client) including sys/types.h
is not enough to get a timeval declaration.

Change-Id: I4971a1aacc80b6fdc12c0e81c5d8007ed13eb8b7
Reviewed-on: https://boringssl-review.googlesource.com/6722
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 18:11:18 +00:00
Sam Clegg dca63cfa75 Don't abort in |init_once| if |fcntl| returns ENOSYS
Native Client doesn't support fcntl natively and its default
implemention just returns ENOSYS.

Change-Id: Id8615e2f6f0a75a1140f8efd75afde471ccdf466
Reviewed-on: https://boringssl-review.googlesource.com/6721
Reviewed-by: Adam Langley <agl@google.com>
2015-12-15 18:10:40 +00:00
Joachim Bauch afd565ff9c Add defines for SRTP profiles using GCM ciphers from RFC 7714.
BUG=webrtc:5222

Change-Id: I8399bd595564dedbe5492b8ea6eb915f41367cbf
Reviewed-on: https://boringssl-review.googlesource.com/6690
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
2015-12-10 23:18:16 +00:00
Adam Langley 902870e3b5 Gate SHA_CTX compatibility on !WINDOWS.
Windows does support anonymous unions but warns about it. Since I'm not
sure what warnings we have enabled in Chromium, this change just drops
the union for Windows.

Change-Id: I914f8cd5855eb07153105250c0f026eaedb35365
Reviewed-on: https://boringssl-review.googlesource.com/6631
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-12-04 22:13:19 +00:00
Adam Langley 34aa55c05e Support the SHA_CTX hack without ANDROID.
wpa_supplicant needs access to the internals of SHA_CTX. We supported
this only for builds with ANDROID defined previously but that's a pain
for wpa_supplicant to deal with. Thus this change enables it
unconditionally.

Perhaps in the future we'll be able to get a function to do this into
OpenSSL and BoringSSL.

Change-Id: Ib5d088c586fe69249c87404adb45aab5a7d5cf80
Reviewed-on: https://boringssl-review.googlesource.com/6630
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-12-04 20:23:46 +00:00
David Benjamin 6d9e5a7448 Re-apply 75b833cc81
I messed up and missed that we were carrying a diff on x86_64-mont5.pl. This
was accidentally dropped in https://boringssl-review.googlesource.com/6616.

To confirm the merge is good now, check out at this revision and run:

  git diff e701f16bd69b6f251ed537e40364c281e85a63b2^ crypto/bn/asm/x86_64-mont5.pl > /tmp/A

Then in OpenSSL's repository:

  git diff d73cc256c8e256c32ed959456101b73ba9842f72^ d73cc256c8e256c32ed959456101b73ba9842f72 crypto/bn/asm/x86_64-mont5.pl  > /tmp/B

And confirm the diffs vary in only metadata:

  diff -u /tmp/A /tmp/B

--- /tmp/A	2015-12-03 11:53:23.127034998 -0500
+++ /tmp/B	2015-12-03 11:53:53.099314287 -0500
@@ -1,8 +1,8 @@
 diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl
-index 38def07..3c5a8fc 100644
+index 388e3c6..64e668f 100755
 --- a/crypto/bn/asm/x86_64-mont5.pl
 +++ b/crypto/bn/asm/x86_64-mont5.pl
-@@ -1770,6 +1770,15 @@ sqr8x_reduction:
+@@ -1784,6 +1784,15 @@ sqr8x_reduction:
  .align	32
  .L8x_tail_done:
  	add	(%rdx),%r8		# can this overflow?
@@ -18,7 +18,7 @@
  	xor	%rax,%rax

  	neg	$carry
-@@ -3116,6 +3125,15 @@ sqrx8x_reduction:
+@@ -3130,6 +3139,15 @@ sqrx8x_reduction:
  .align	32
  .Lsqrx8x_tail_done:
  	add	24+8(%rsp),%r8		# can this overflow?
@@ -34,7 +34,7 @@
  	mov	$carry,%rax		# xor	%rax,%rax

  	sub	16+8(%rsp),$carry	# mov 16(%rsp),%cf
-@@ -3159,13 +3177,11 @@ my ($rptr,$nptr)=("%rdx","%rbp");
+@@ -3173,13 +3191,11 @@ my ($rptr,$nptr)=("%rdx","%rbp");
  my @ri=map("%r$_",(10..13));
  my @ni=map("%r$_",(14..15));
  $code.=<<___;

Change-Id: I3fb5253783ed82e4831f5bffde75273bd9609c23
Reviewed-on: https://boringssl-review.googlesource.com/6618
Reviewed-by: Adam Langley <agl@google.com>
2015-12-03 17:25:12 +00:00
David Benjamin 28243c08db Add PSS parameter check.
Avoid seg fault by checking mgf1 parameter is not NULL. This can be
triggered during certificate verification so could be a DoS attack
against a client or a server enabling client authentication.

Thanks to Loïc Jonas Etienne (Qnective AG) for discovering this bug.

CVE-2015-3194

(Imported from upstream's c394a488942387246653833359a5c94b5832674e and test
data from 00456fded43eadd4bb94bf675ae4ea5d158a764f.)

Change-Id: Ic97059d42722fd810973ccb0c26c415c4eaae79a
Reviewed-on: https://boringssl-review.googlesource.com/6617
Reviewed-by: Adam Langley <agl@google.com>
2015-12-03 16:47:12 +00:00
David Benjamin e701f16bd6 bn/asm/x86_64-mont5.pl: fix carry propagating bug (CVE-2015-3193).
(Imported from upstream's d73cc256c8e256c32ed959456101b73ba9842f72.)

Change-Id: I673301fee57f0ab5bef24553caf8b2aac67fb3a9
Reviewed-on: https://boringssl-review.googlesource.com/6616
Reviewed-by: Adam Langley <agl@google.com>
2015-12-03 16:44:35 +00:00
David Benjamin cb852981cd Fix leak with ASN.1 combine.
When parsing a combined structure pass a flag to the decode routine
so on error a pointer to the parent structure is not zeroed as
this will leak any additional components in the parent.

This can leak memory in any application parsing PKCS#7 or CMS structures.

CVE-2015-3195.

Thanks to Adam Langley (Google/BoringSSL) for discovering this bug using
libFuzzer.

PR#4131

(Imported from upstream's cc598f321fbac9c04da5766243ed55d55948637d, with test
from our original report. Verified ASan trips up on the test without the fix.)

Change-Id: I007d93f172b2f16bf6845d685d72717ed840276c
Reviewed-on: https://boringssl-review.googlesource.com/6615
Reviewed-by: Adam Langley <agl@google.com>
2015-12-03 16:43:34 +00:00
Adam Langley c4f25ce0c6 Work around yaSSL bug.
yaSSL has a couple of bugs in their DH client implementation. This
change works around the worst of the two.

Firstly, they expect the the DH public value to be the same length as
the prime. This change pads the public value as needed to ensure this.

Secondly, although they handle the first byte of the shared key being
zero, they don't handle the case of the second, third, etc bytes being
zero. So whenever that happens the handshake fails. I don't think that
there's anything that we can do about that one.

Change-Id: I789c9e5739f19449473305d59fe5c3fb9b4a6167
Reviewed-on: https://boringssl-review.googlesource.com/6578
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-30 22:41:24 +00:00
Brian Smith c5eb4676b6 Remove dead code in p256-x86_64.
Change-Id: I9d0b3fa39445d08202c67d905d2c676d5d968c33
Reviewed-on: https://boringssl-review.googlesource.com/6561
Reviewed-by: Adam Langley <agl@google.com>
2015-11-20 23:45:43 +00:00
David Benjamin 758d12732a Add get0 getters for EVP_PKEY.
Right now your options are:
- Bounce on a reference and deal with cleanup needlessly.
- Manually check the type tag and peek into the union.

We probably have no hope of opaquifying this struct, but for new code, let's
recommend using this function rather than the more error-prone thing.

Change-Id: I9b39ff95fe4264a3f7d1e0d2894db337aa968f6c
Reviewed-on: https://boringssl-review.googlesource.com/6551
Reviewed-by: Adam Langley <agl@google.com>
2015-11-20 23:34:12 +00:00
Mostyn Bramley-Moore fde89b43c3 avoid clashes with libc's 'open' in e_chacha20poly1305.c
Some strange toolchains can have an implicit (or explicit) fcntl.h include,
so let's avoid using the name 'open' for local functions.  This should not
cause any trouble.

Change-Id: Ie131b5920ac23938013c2c03302b97a7418c7180
Reviewed-on: https://boringssl-review.googlesource.com/6540
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-20 20:02:23 +00:00
Brian Smith 60a45aa7cc Remove reference to removed |RSA_FLAG_NO_CONSTTIME| flag.
Change-Id: I0bfdccf009772d4ff8cd419758ab5bfae95f5cc5
Reviewed-on: https://boringssl-review.googlesource.com/6530
Reviewed-by: Adam Langley <agl@google.com>
2015-11-20 19:59:29 +00:00
David Benjamin 81edc9beb6 Do away with BN_LLONG in favor of BN_ULLONG.
BN_LLONG is only ever used in #ifdefs. The actual type is BN_ULLONG. Switch the
ifdefs to check on BN_ULLONG and remove BN_LLONG. Also fix signedness of all
the constants (potentially avoiding undefined behavior in some operations).

Change-Id: I3e7739bbe14c50ea7db04fc507a034a8cb315a5f
Reviewed-on: https://boringssl-review.googlesource.com/6518
Reviewed-by: Adam Langley <agl@google.com>
2015-11-20 19:59:07 +00:00
Matt Braithwaite e8fe07fcc4 Fix AES XTS mode key size.
I screwed up the |EVP_CIPHER| parameters for XTS when I first imported
it, and there were no tests to catch it.  (The problem was that
|EVP_CIPH_XTS_MODE| means “the key size is actually twice what it says
here.”)

With these changes, OpenSSL's tests pass.

(Along the way, make a few other things about XTS slightly less
decrepit.)

Change-Id: Icbfbc5e6d532d1c132392ee366f9cab42802d674
Reviewed-on: https://boringssl-review.googlesource.com/6529
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 18:08:33 +00:00
David Benjamin 93a5b44296 Make CRYPTO_library_init use a CRYPTO_once_t.
Initialization by multiple consumers on ARM is still problematic due to
CRYPTO_set_NEON_{capable,functional}, until we reimplement that in-library, but
if that is called before the first CRYPTO_library_init, this change makes it
safe.

BUG=556462

Change-Id: I5845d09cca909bace8293ba7adf09a3bd0d4f943
Reviewed-on: https://boringssl-review.googlesource.com/6519
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 18:05:22 +00:00
Brian Smith bf762186c6 Remove the |ri| field of |BN_MONT_CTX|.
The |ri| field was only used in |BN_MONT_CTX_set|, so make it a local
variable of that function.

Change-Id: Id8c3d44ac2e30e3961311a7b1a6731fe2c33a0eb
Reviewed-on: https://boringssl-review.googlesource.com/6526
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:40:13 +00:00
Brian Smith 596ab10b0f s/BN_BITS/BN_BITS2/ in |BN_mod_inverse_ex|; remove |BN_BITS| & |BN_MASK|.
The comment in |BN_mod_inverse_ex| makes it clear that |BN_BITS2| was
intended. Besides fixing the code to match the comment, remove
the now-unused |BN_BITS| and the already-unused |BN_MASK| to prevent
future confusion of this sort.

On MSVC builds there seems to be very little difference in performance
between the two code paths according to |bssl speed|.

Change-Id: I765b7b3d464e2057b1d7952af25b6deb2724976a
Reviewed-on: https://boringssl-review.googlesource.com/6525
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:39:32 +00:00
Brian Smith 7af36e1e38 Share common definitions of |TOBN| and |BIGNUM_STATIC|.
Previously, both crypto/dh and crypto/ec defined |TOBN| macros that did
the same thing, but which took their arguments in the opposite order.
This change makes the code consistently use the same macro. It also
makes |STATIC_BIGNUM| available for internal use outside of crypto/bn.

Change-Id: Ide57f6a5b74ea95b3585724c7e1a630c82a864d9
Reviewed-on: https://boringssl-review.googlesource.com/6528
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:38:52 +00:00
David Benjamin ff2df337a0 Reformat the cipher suite table.
clang-format packing them tightly made newlines inconsistent which
wasn't very helpful.

Change-Id: I46a787862ed1f5b0eee101394e24c779b6bc652b
Reviewed-on: https://boringssl-review.googlesource.com/6517
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:32:55 +00:00
David Benjamin 9f2e2770e1 Remove strength_bits.
Trim the cipher table further. Those values are entirely determined by
algorithm_enc.

Change-Id: I355c245b0663e41e54e62d15903a4a9a667b4ffe
Reviewed-on: https://boringssl-review.googlesource.com/6516
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:32:28 +00:00
David Benjamin d6e9eec3f8 Remove algo_strength.
FIPS is the same as HIGH (but for CHACHA20), so those are redundant.
Likewise, MEDIUM vs HIGH was just RC4. Remove those in favor of
redefining those legacy rules to mean this.

One less field to keep track of in each cipher.

Change-Id: I2b2489cffb9e16efb0ac7d7290c173cac061432a
Reviewed-on: https://boringssl-review.googlesource.com/6515
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:30:44 +00:00
David Benjamin dcb6ef0f0b Remove algorithm_ssl.
It's redundant with other cipher properties. We can express these in code.
Cipher rule matching gets a little bit complicated due to the confusing legacy
protocol version cipher rules, so add some tests for it. (It's really hard to
grep for uses of them, so I've kept them working to be safe.)

Change-Id: Ic6b3fcd55d76d4a51b31bf7ae629a2da50a7450e
Reviewed-on: https://boringssl-review.googlesource.com/6453
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:28:24 +00:00
David Benjamin d28f59c27b Switch the keylog BIO to a callback.
The keylog BIO is internally synchronized by the SSL_CTX lock, but an
application may wish to log keys from multiple SSL_CTXs. This is in
preparation for switching Chromium to use a separate SSL_CTX per profile
to more naturally split up the session caches.

It will also be useful for routing up SSLKEYLOGFILE in WebRTC. There,
each log line must be converted to an IPC up from the renderer
processes.

This will require changes in Chromium when we roll BoringSSL.

BUG=458365,webrtc:4417

Change-Id: I2945bdb4def0a9c36e751eab3d5b06c330d66b54
Reviewed-on: https://boringssl-review.googlesource.com/6514
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:23:49 +00:00
David Benjamin fba735cfd8 Register the *25519 tests as dependencies of all_tests.
This ensures the run_tests target updates those binaries.

Change-Id: I32b68026da4852424b5621e014e71037c8a5754c
Reviewed-on: https://boringssl-review.googlesource.com/6513
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:09:09 +00:00
Brian Smith f3376ace43 Remove |EC_POINTs_mul| & simplify p256-x86_64.
Without |EC_POINTs_mul|, there's never more than one variable point
passed to a |EC_METHOD|'s |mul| method. This allows them to be
simplified considerably. In this commit, the p256-x86_64 implementation
has been simplified to eliminate the heap allocation and looping
related that was previously necessary to deal with the possibility of
there being multiple input points. The other implementations were left
mostly as-is; they should be similarly simplified in the future.

Change-Id: I70751d1d5296be2562af0730e7ccefdba7a1acae
Reviewed-on: https://boringssl-review.googlesource.com/6493
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 01:08:46 +00:00
Brian Smith 301efc8cea Fix error handling in |p256-x86_64|.
This makes similar fixes as were done in the following OpenSSL commits:

    c028254b12a8ea0d0f8a677172eda2e2d78073f3: Correctly set Z_is_one on
    the return value in the NISTZ256 implementation.

    e22d2199e2a5cc9b243f45c2b633d1e31fadecd7: Error checking and memory
    leak leak fixes in NISTZ256.

    4446044a793a9103a4bc70c0214005e6a4463767: NISTZ256: set Z_is_one to
    boolean 0/1 as is customary.

    a4d5269e6d0dba0c276c968448a3576f7604666a: NISTZ256: don't swallow
    malloc errors.

The fixes aren't exactly the same. In particular, the comments "This is
an unusual input, we don't guarantee constant-timeness" and the changes
to |ecp_nistz256_mult_precompute| (which isn't in BoringSSL) were
omitted.

Change-Id: Ia7bb982daa62fb328e8bd2d4dd49a8857e104096
Reviewed-on: https://boringssl-review.googlesource.com/6492
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:52:33 +00:00
Brian Smith e2136d9c28 Remove |EC_GROUP_precompute_mult| and |EC_KEY_precompute_mult|.
Change-Id: I1663ec6046b8f1f67a62e4c6483af719d6f362ad
Reviewed-on: https://boringssl-review.googlesource.com/6486
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:35:59 +00:00
Brian Smith 9b26297608 Make |EC_GROUP_precompute_mult|/|EC_KEY_precompute_mult| no-ops.
This moves us closer to having |EC_GROUP| and |EC_KEY| being immutable.
The functions are left as no-ops for backward compatibility.

Change-Id: Ie23921ab0364f0771c03aede37b064804c9f69e0
Reviewed-on: https://boringssl-review.googlesource.com/6485
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:27:39 +00:00
Brian Smith 5058d79948 Remove p224-64 and p256-64 dead code for non-default generators.
This extends 9f1f04f313 to the other
implementations.

|EC_GFp_nistp224_method| and |EC_GFp_nistp256_method| are not marked
|OPENSSL_EXPORT|. |EC_GROUP_set_generator| doesn't allow the generator
to be changed for any |EC_GROUP| for built-in curves. Consequently,
there's no way (except some kind of terrible abuse) that this code
could be executed with a non-default generator.

Change-Id: I5d9b6be4e6f9d384159cb3d708390a8e3c69f23f
Reviewed-on: https://boringssl-review.googlesource.com/6489
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:23:14 +00:00
Adam Langley b1b6229fc8 Add NEON implementation of curve25519.
Nexus 7 goes from 1002.8 ops/sec to 4704.8 at a cost of 10KB of code.
(It'll actually save code if built with -mfpu=neon because then the
generic version can be discarded by the compiler.)

Change-Id: Ia6d02efb2c2d1bb02a07eb56ec4ca3b0dba99382
Reviewed-on: https://boringssl-review.googlesource.com/6524
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:20:38 +00:00
Adam Langley 9e65d487b8 Allow |CRYPTO_is_NEON_capable| to be known at compile time, if possible.
If -mfpu=neon is passed then we don't need to worry about checking for
NEON support at run time. This change allows |CRYPTO_is_NEON_capable| to
statically return 1 in this case. This then allows the compiler to
discard generic code in several cases.

Change-Id: I3b229740ea3d5cb0a304f365c400a0996d0c66ef
Reviewed-on: https://boringssl-review.googlesource.com/6523
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-19 00:15:11 +00:00
Adam Langley 3ac32b1eda Fix curve25519 code for MSVC.
MSVC doesn't like unary minus on unsigned types. Also, the speed test
always failed because the inputs were all zeros and thus had small
order.

Change-Id: Ic2d3c2c9bd57dc66295d93891396871cebac1e0b
2015-11-17 15:15:05 -08:00
Adam Langley 4fb0dc4b03 Add X25519 and Ed25519 support.
(Ed25519 support is disabled when |OPENSSL_SMALL| is defined.)

libcrypto.a sizes:

x86-64 -O3 -march=native: +78012 (1584902 → 1662914)
x86-64 -O3 -march=native -DOPENSSL_SMALL: +10596 (1356206 → 1366802)
Android armv7 Thumb -O2 -DOPENSSL_SMALL: +13132 (1258462 → 1271594)

Change-Id: I6a7e64d481e4ce4daa7d5057578081358746cfb9
Reviewed-on: https://boringssl-review.googlesource.com/6497
Reviewed-by: Adam Langley <agl@google.com>
2015-11-17 21:56:12 +00:00
Piotr Sikora c324f1783e Make sure pthread_once() succeeds.
It can fail on FreeBSD when library is not linked against either
threading library and results in init routine not being executed
at all, leading to errors in other parts of the code.

Change-Id: I1063f6940e381e6470593c063fbfecf3f47991cd
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Reviewed-on: https://boringssl-review.googlesource.com/6522
Reviewed-by: Adam Langley <agl@google.com>
2015-11-17 21:44:40 +00:00
Piotr Sikora 9361243065 Don't include <alloca.h>, it's no longer needed.
Relevant code was removed in 5d5e39f5d2.

Change-Id: I198844064030c04f88e5541f2bbaa29ae13d14bb
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Reviewed-on: https://boringssl-review.googlesource.com/6521
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-17 19:21:40 +00:00
Adam Langley b00061cea7 Add SSL_CIPHER_is_AES[128|256]CBC.
Change-Id: I3072f884be77b8646e90d316154b96448f0cf2a1
Reviewed-on: https://boringssl-review.googlesource.com/6520
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-17 19:15:06 +00:00
David Benjamin 3a59611726 size_t SSL*_use_*_ASN1.
So long as we're not getting rid of them (the certificate variants may
be useful when we decouple from crypto/x509 anyway), get the types and
bounds checks right.

Also reject trailing data and require the input be a single element.
Note: this is a slight compatibility risk, but we did it for
SSL*_use_RSAPrivateKey_ASN1 previously and I think it's probably worth
seeing if anything breaks here.

Change-Id: I64fa3fc6249021ccf59584d68e56ff424a190082
Reviewed-on: https://boringssl-review.googlesource.com/6490
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:59:14 +00:00
David Benjamin b324159be9 Fix ssl3_send_server_key_exchange error path.
This codepath should not actually be reachable, unless maybe the caller is
doing something really dumb. (Unconfiguring the key partway through the
connection.)

Change-Id: Ic8e0cfc3c426439016370f9a85be9c05509358f1
Reviewed-on: https://boringssl-review.googlesource.com/6483
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:27:27 +00:00
David Benjamin f584a5aaa2 Reset epoch state in one place.
TLS resets it in t1_enc.c while DTLS has it sprinkled everywhere.

Change-Id: I78f0f0e646b4dc82a1058199c4b00f2e917aa5bc
Reviewed-on: https://boringssl-review.googlesource.com/6511
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:19:31 +00:00
David Benjamin 2077cf9152 Use UINT64_C instead of OPENSSL_U64.
stdint.h already has macros for this. The spec says that, in C++,
__STDC_CONSTANT_MACROS is needed, so define it for bytestring_test.cc.
Chromium seems to use these macros without trouble, so I'm assuming we
can rely on them.

Change-Id: I56d178689b44d22c6379911bbb93d3b01dd832a3
Reviewed-on: https://boringssl-review.googlesource.com/6510
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:18:00 +00:00
David Benjamin af07365b49 Check for overflow when parsing a CBS with d2i_*.
Until we've done away with the d2i_* stack completely, boundaries need
to be mindful of the type mismatch. d2i_* takes a long, not a size_t.

Change-Id: If02f9ca2cfde02d0929ac18275d09bf5df400f3a
Reviewed-on: https://boringssl-review.googlesource.com/6491
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:17:42 +00:00
David Benjamin 780cd92b98 modes/asm/ghash-armv4.pl: extend Apple fix to all clang cases.
Triggered by RT#3989.

(Imported from upstream's fbab8baddef8d3346ae40ff068871e2ddaf10270. This
doesn't seem to affect us, but avoid getting out of sync.)

Change-Id: I164e2a72e4b75e286ceaa03745ed9bcbf6c3e32e
Reviewed-on: https://boringssl-review.googlesource.com/6512
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 23:11:19 +00:00
Adam Langley f9c77dedfa Drop CBB allocation failure test.
To no great surprise, ASAN didn't like this test and I suspect that
Chromium, with its crashing allocator, won't like it either. Oh well.

Change-Id: I235dbb965dbba186f8f37d7df45f8eac9addc7eb
Reviewed-on: https://boringssl-review.googlesource.com/6496
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 22:25:59 +00:00
Adam Langley a33915d690 Have |CBB_init| zero the |CBB| before any possible failures.
People expect to do:

CBB foo;

if (!CBB_init(&foo, 100) ||
    …
    …) {
  CBB_cleanup(&foo);
  return 0;
}

However, currently, if the allocation of |initial_capacity| fails in
|CBB_init| then |CBB_cleanup| will operate on uninitialised values. This
change makes the above pattern safe.

Change-Id: I3e002fda8f0a3ac18650b504e7e84a842d4165ca
Reviewed-on: https://boringssl-review.googlesource.com/6495
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 21:59:46 +00:00
Adam Langley c5c85defb2 Make RAND_seed read a byte of random data.
OpenSSH calls |RAND_seed| before jailing in the expectation that that
will be sufficient to ensure that later RAND calls are successful.

See internal bug 25695426.

Change-Id: I9d3f5665249af6610328ac767cb83059bb2953dd
Reviewed-on: https://boringssl-review.googlesource.com/6494
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-16 21:58:46 +00:00
Adam Langley d9e27021e1 Don't encode or decode ∞.
|EC_POINT_point2oct| would encode ∞, which is surprising, and
|EC_POINT_oct2point| would decode ∞, which is insane. This change
removes both behaviours.

Thanks to Brian Smith for pointing it out.

Change-Id: Ia89f257dc429a69b9ea7b7b15f75454ccc9c3bdd
Reviewed-on: https://boringssl-review.googlesource.com/6488
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 23:52:37 +00:00
Adam Langley e7806fd477 Remove point-on-curve check from |ec_GFp_simple_oct2point|.
In the case of a compressed point, the decompression ensures that the
point is on the curve. In the uncompressed case,
|EC_POINT_set_affine_coordinates_GFp| checks that the point is on the
curve as of 38feb990a1.

Change-Id: Icd69809ae396838b4aef4fa89b3b354560afed55
Reviewed-on: https://boringssl-review.googlesource.com/6487
Reviewed-by: Brian Smith <brian@briansmith.org>
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 23:51:17 +00:00
David Benjamin 20c373118c Become partially -Wmissing-variable-declarations-clean.
There's a few things that will be kind of a nuisance and possibly not worth it
(crypto/asn1 dumps a lot of undeclared things, etc.). But it caught some
mistakes. Even without the warning, making sure to include the externs before
defining a function helps catch type mismatches.

Change-Id: I3dab282aaba6023e7cebc94ed7a767a5d7446b08
Reviewed-on: https://boringssl-review.googlesource.com/6484
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 20:09:20 +00:00
Brian Smith 7308aaa9b4 Remove EC_GFp_simple_method (dead code).
Change-Id: I1820bd5412313e00a69123370178c0fe3e12b5ef
Reviewed-on: https://boringssl-review.googlesource.com/6482
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 20:07:51 +00:00
Brian Smith f872951880 Fix null pointer dereference when using "simple" EC.
This regressed in f0523e9f20.

Change-Id: I70c3fcb0d91ac00e5088b086312384756eda6140
Reviewed-on: https://boringssl-review.googlesource.com/6481
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 20:05:13 +00:00
Brian Smith 8bde5d2e51 Remove the unused |Ni| member of |BN_MONT_CTX|.
Change-Id: I0a542c48c7adae28f05778d6c34c9b6836fc3449
Reviewed-on: https://boringssl-review.googlesource.com/6480
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 20:04:43 +00:00
David Benjamin ce7ae6fa27 Enable AVX code for SHA-*.
SHA-1, SHA-256, and SHA-512 get a 12-26%, 17-23%, and 33-37% improvement,
respectively on x86-64. SHA-1 and SHA-256 get a 8-20% and 14-17% improvement on
x86. (x86 does not have AVX code for SHA-512.) This costs us 12k of binary size
on x86-64 and 8k of binary size on x86.

$ bssl speed SHA- (x86-64, before)
Did 4811000 SHA-1 (16 bytes) operations in 1000013us (4810937.5 ops/sec): 77.0 MB/s
Did 1414000 SHA-1 (256 bytes) operations in 1000253us (1413642.3 ops/sec): 361.9 MB/s
Did 56000 SHA-1 (8192 bytes) operations in 1002640us (55852.5 ops/sec): 457.5 MB/s
Did 2536000 SHA-256 (16 bytes) operations in 1000140us (2535645.0 ops/sec): 40.6 MB/s
Did 603000 SHA-256 (256 bytes) operations in 1001613us (602028.9 ops/sec): 154.1 MB/s
Did 25000 SHA-256 (8192 bytes) operations in 1010132us (24749.2 ops/sec): 202.7 MB/s
Did 1767000 SHA-512 (16 bytes) operations in 1000477us (1766157.5 ops/sec): 28.3 MB/s
Did 638000 SHA-512 (256 bytes) operations in 1000933us (637405.3 ops/sec): 163.2 MB/s
Did 32000 SHA-512 (8192 bytes) operations in 1025646us (31199.8 ops/sec): 255.6 MB/s

$ bssl speed SHA- (x86-64, after)
Did 5438000 SHA-1 (16 bytes) operations in 1000060us (5437673.7 ops/sec): 87.0 MB/s
Did 1590000 SHA-1 (256 bytes) operations in 1000181us (1589712.3 ops/sec): 407.0 MB/s
Did 71000 SHA-1 (8192 bytes) operations in 1007958us (70439.4 ops/sec): 577.0 MB/s
Did 2955000 SHA-256 (16 bytes) operations in 1000251us (2954258.5 ops/sec): 47.3 MB/s
Did 740000 SHA-256 (256 bytes) operations in 1000628us (739535.6 ops/sec): 189.3 MB/s
Did 31000 SHA-256 (8192 bytes) operations in 1019619us (30403.5 ops/sec): 249.1 MB/s
Did 2348000 SHA-512 (16 bytes) operations in 1000285us (2347331.0 ops/sec): 37.6 MB/s
Did 878000 SHA-512 (256 bytes) operations in 1001064us (877066.8 ops/sec): 224.5 MB/s
Did 43000 SHA-512 (8192 bytes) operations in 1002485us (42893.4 ops/sec): 351.4 MB/s

$ bssl speed SHA- (x86, before, SHA-512 redacted because irrelevant)
Did 4319000 SHA-1 (16 bytes) operations in 1000066us (4318715.0 ops/sec): 69.1 MB/s
Did 1306000 SHA-1 (256 bytes) operations in 1000437us (1305429.5 ops/sec): 334.2 MB/s
Did 58000 SHA-1 (8192 bytes) operations in 1014807us (57153.7 ops/sec): 468.2 MB/s
Did 2291000 SHA-256 (16 bytes) operations in 1000343us (2290214.5 ops/sec): 36.6 MB/s
Did 594000 SHA-256 (256 bytes) operations in 1000684us (593594.0 ops/sec): 152.0 MB/s
Did 25000 SHA-256 (8192 bytes) operations in 1030688us (24255.6 ops/sec): 198.7 MB/s

$ bssl speed SHA- (x86, after, SHA-512 redacted because irrelevant)
Did 4673000 SHA-1 (16 bytes) operations in 1000063us (4672705.6 ops/sec): 74.8 MB/s
Did 1484000 SHA-1 (256 bytes) operations in 1000453us (1483328.1 ops/sec): 379.7 MB/s
Did 69000 SHA-1 (8192 bytes) operations in 1008305us (68431.7 ops/sec): 560.6 MB/s
Did 2684000 SHA-256 (16 bytes) operations in 1000196us (2683474.0 ops/sec): 42.9 MB/s
Did 679000 SHA-256 (256 bytes) operations in 1000525us (678643.7 ops/sec): 173.7 MB/s
Did 29000 SHA-256 (8192 bytes) operations in 1033251us (28066.8 ops/sec): 229.9 MB/s

Change-Id: I952a3b4fc4c52ebb50690da3b8c97770e8342e98
Reviewed-on: https://boringssl-review.googlesource.com/6470
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 20:03:32 +00:00
Brian Smith 9f1f04f313 Remove nistz256 dead code for non-default generators.
|EC_GFp_nistz256_method| is not marked |OPENSSL_EXPORT| so only the
built-in P-256 curve uses it. |EC_GROUP_set_generator| doesn't allow
the generator to be changed for any |EC_GROUP| for a built-in curve.
Consequently, there's no way (except some kind of terrible abuse) that
the nistz code could be executed with a non-default generator.

Change-Id: Ib22f00bc74c103b7869ed1e35032b1f3d26cdad2
Reviewed-on: https://boringssl-review.googlesource.com/6446
Reviewed-by: Adam Langley <agl@google.com>
2015-11-12 19:59:16 +00:00
573 changed files with 51625 additions and 36638 deletions
+16 -8
View File
@@ -2,14 +2,18 @@
## Build Prerequisites
* [CMake](http://www.cmake.org/download/) 2.8.8 or later is required.
* [CMake](https://cmake.org/download/) 2.8.8 or later is required.
* Perl 5.6.1 or later is required. On Windows,
[Strawberry Perl](http://strawberryperl.com/) and MSYS Perl have both been
reported to work. If not found by CMake, it may be configured explicitly by
setting `PERL_EXECUTABLE`.
[Active State Perl](http://www.activestate.com/activeperl/) has been
reported to work, as has MSYS Perl.
[Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC
to `PATH`, which can confuse some build tools when identifying the compiler
(removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems).
If Perl is not found by CMake, it may be configured explicitly by setting
`PERL_EXECUTABLE`.
* On Windows you currently must use [Ninja](https://martine.github.io/ninja/)
* On Windows you currently must use [Ninja](https://ninja-build.org/)
to build; on other platforms, it is not required, but recommended, because
it makes builds faster.
@@ -21,8 +25,8 @@
`CMAKE_ASM_NASM_COMPILER`.
* A C compiler is required. On Windows, MSVC 12 (Visual Studio 2013) or later
with Platform SDK 8.1 or later are supported. Recent versions of GCC and
Clang should work on non-Windows platforms, and maybe on Windows too.
with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+)
and Clang should work on non-Windows platforms, and maybe on Windows too.
* [Go](https://golang.org/dl/) is required. If not found by CMake, the go
executable may be configured explicitly by setting `GO_EXECUTABLE`.
@@ -58,7 +62,8 @@ files because the build scripts will detect changes to them and rebuild
themselves automatically.
Note that the default build flags in the top-level `CMakeLists.txt` are for
debugging—optimisation isn't enabled.
debugging—optimisation isn't enabled. Pass `-DCMAKE_BUILD_TYPE=Release` to
`cmake` to configure a release build.
If you want to cross-compile then there is an example toolchain file for 32-bit
Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like
@@ -75,6 +80,9 @@ In order to serve environments where code-size is important as well as those
where performance is the overriding concern, `OPENSSL_SMALL` can be defined to
remove some code that is especially large.
See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html)
for other variables which may be used to configure the build.
### Building for Android
It's possible to build BoringSSL with the Android NDK using CMake. This has
+15 -3
View File
@@ -1,6 +1,16 @@
cmake_minimum_required (VERSION 2.8.10)
project (BoringSSL)
# Defer enabling C and CXX languages.
project (BoringSSL NONE)
if(WIN32)
# On Windows, prefer cl over gcc if both are available. By default most of
# the CMake generators prefer gcc, even on Windows.
set(CMAKE_GENERATOR_CC cl)
endif()
enable_language(C)
enable_language(CXX)
if(ANDROID)
# Android-NDK CMake files reconfigure the path and so Go and Perl won't be
@@ -17,8 +27,9 @@ if (NOT GO_EXECUTABLE)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -std=c++0x -fvisibility=hidden")
set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${C_CXX_FLAGS}")
elseif(MSVC)
set(MSVC_DISABLED_WARNINGS_LIST
"C4100" # 'exarg' : unreferenced formal parameter
@@ -51,6 +62,7 @@ elseif(MSVC)
# copy constructor is inaccessible or deleted
"C4626" # assignment operator could not be generated because a base class
# assignment operator is inaccessible or deleted
"C4701" # potentially uninitialized local variable 'p' used
"C4706" # assignment within conditional expression
"C4710" # 'function': function not inlined
"C4711" # function 'function' selected for inline expansion
+49
View File
@@ -0,0 +1,49 @@
Want to contribute? Great! First, read this page (including the small print at the end).
### Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things—for instance that you'll tell us if you
know that your code infringes on other people's patents. You don't have to sign
the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first via email with your idea so that we can help out and possibly guide
you. Coordinating up front makes it much easier to avoid frustration later on.
### Code reviews
All submissions, including submissions by project members, require review. We
use [Gerrit](https://boringssl-review.googlesource.com) for this purpose.
#### Setup
If you have not done so on this machine, you will need to set up a password for
Gerrit. Sign in with a Google account, visit
[this link](https://boringssl.googlesource.com/), and click the "Generate
Password" link in the top right. You will also need to prepare your checkout to
[add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html)
on commit. Run:
curl -Lo .git/hooks/commit-msg https://boringssl-review.googlesource.com/tools/hooks/commit-msg
chmod u+x .git/hooks/commit-msg
#### Uploading changes
To upload a change, push it to the special `refs/for/master` target:
git push origin HEAD:refs/for/master
The output will then give you a link to the change. Add `agl@google.com` and
`davidben@google.com` as reviewers.
Pushing a commit with the same Change-Id as an existing change will upload a new
version of it. (Use the `git rebase` or `git commit --amend` commands.)
For more detailed instructions, see the
[Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html).
### The small print
Contributions made by corporations are covered by a different agreement than
the one above, the
[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
+23
View File
@@ -130,6 +130,23 @@ BoringSSL's `BN_bn2hex` function uses lowercase hexadecimal digits instead of
uppercase. Some code may require changes to avoid being sensitive to this
difference.
### Legacy ASN.1 functions
OpenSSL's ASN.1 stack uses `d2i` functions for parsing. They have the form:
RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
In addition to returning the result, OpenSSL places it in `*out` if `out` is
not `NULL`. On input, if `*out` is not `NULL`, OpenSSL will usually (but not
always) reuse that object rather than allocating a new one. In BoringSSL, these
functions are compatibility wrappers over a newer ASN.1 stack. Even if `*out`
is not `NULL`, these wrappers will always allocate a new object and free the
previous one.
Ensure that callers do not rely on this object reuse behavior. It is
recommended to avoid the `out` parameter completely and always pass in `NULL`.
Note that less error-prone APIs are available for BoringSSL-specific code (see
below).
## Optional BoringSSL-specific simplifications
@@ -162,3 +179,9 @@ locks. Without initializing these, the library is not thread-safe. Configuring
these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the
corresponding Windows APIs internally and is always thread-safe where the API
guarantees it.
### ASN.1
BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of
new functions using the much less error-prone `CBS` and `CBB` types.
BoringSSL-only code should use those functions where available.
+1
View File
@@ -28,3 +28,4 @@ There are other files in this directory which might be helpful:
* [STYLE.md](/STYLE.md): rules and guidelines for coding style.
* include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
+2
View File
@@ -105,6 +105,7 @@ add_subdirectory(rc4)
add_subdirectory(conf)
add_subdirectory(chacha)
add_subdirectory(poly1305)
add_subdirectory(curve25519)
# Level 1, depends only on 0.*
add_subdirectory(digest)
@@ -174,6 +175,7 @@ add_library(
$<TARGET_OBJECTS:conf>
$<TARGET_OBJECTS:chacha>
$<TARGET_OBJECTS:poly1305>
$<TARGET_OBJECTS:curve25519>
$<TARGET_OBJECTS:buf>
$<TARGET_OBJECTS:bn>
$<TARGET_OBJECTS:bio>
-5
View File
@@ -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:
-8
View File
@@ -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:
+11
View File
@@ -43,3 +43,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)
+176 -168
View File
@@ -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;
{
int ret, j, bits, len;
unsigned char *p, *d;
if (a == NULL) return(0);
if (a == NULL)
return (0);
len=a->length;
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;
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);
ret = 1 + len;
if (pp == NULL)
return (ret);
p= *pp;
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);
}
*(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;
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 (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);
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;
}
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 */
/*
* 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;
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 ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
{
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);
}
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);
}
/*
* Checks if the given bit string contains only bits specified by
* 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 ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
{
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);
}
/*
* 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;
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;
}
/*
* 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;
}
+42 -44
View File
@@ -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);
}
+212 -221
View File
@@ -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;
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;
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 (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 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 ((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 (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);
}
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;
{
int ret, r, constructed;
unsigned char *p;
if (a == NULL) return(0);
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_BIT_STRING)
return (i2d_ASN1_BIT_STRING(a, 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);
}
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;
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);
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;
}
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 (tag != Ptag) {
i = ASN1_R_WRONG_TAG;
goto err;
}
if (inf & V_ASN1_CONSTRUCTED)
{
ASN1_const_CTX c;
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);
}
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;
}
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);
}
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 */
/*
* 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;
{
ASN1_STRING *os = NULL;
BUF_MEM b;
int num;
b.length=0;
b.max=0;
b.data=NULL;
b.length = 0;
b.max = 0;
b.data = NULL;
if (a == NULL)
{
c->error=ERR_R_PASSED_NULL_PARAMETER;
goto err;
}
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;
}
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;
}
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 (!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);
}
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);
}
+173 -192
View File
@@ -62,225 +62,206 @@
#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
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))
{
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 (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 (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;
}
+43 -35
View File
@@ -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);
}
+100 -102
View File
@@ -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;
{
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;
}
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);
}
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;
{
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;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_ENUMERATED)
neg = 1;
else if (i != V_ASN1_ENUMERATED)
return -1;
for (i=0; i<a->length; i++)
{
r<<=8;
r|=(unsigned char)a->data[i];
}
if (neg) r= -r;
return(r);
}
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;
{
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;
}
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);
}
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;
{
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);
}
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);
}
+170 -171
View File
@@ -63,193 +63,192 @@
#include <openssl/mem.h>
#include <openssl/time_support.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;
{
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 (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 ((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 ((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);
}
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;
{
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);
}
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;
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);
if (s == NULL)
s = M_ASN1_GENERALIZEDTIME_new();
if (s == NULL)
return (NULL);
ts=OPENSSL_gmtime(&t, &data);
if (ts == 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;
}
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;
}
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);
}
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);
}
+73 -80
View File
@@ -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);
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);
}
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);
}
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);
}
+335 -331
View File
@@ -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;
}
{
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);
ret = ASN1_STRING_cmp(x, y);
if (neg)
return -ret;
else
return ret;
}
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;
{
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 (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) {
*(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;
}
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);
}
*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;
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);
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;
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);
}
/*
* 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);
}
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).
/*
* 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;
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);
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;
}
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;
}
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;
}
/*
* 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);
}
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;
{
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;
}
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);
}
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;
{
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;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
for (i=0; i<a->length; i++)
{
r<<=8;
r|=(unsigned char)a->data[i];
}
if (neg) r= -r;
return(r);
}
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;
{
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);
}
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;
{
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);
}
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);
}
+258 -239
View File
@@ -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;
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) {
/* 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_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_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_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;
case MBSTRING_ASC:
nchar = len;
break;
default:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
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 ((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;
}
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 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;
}
/* 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;
/* 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_BMP:
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
outlen = nchar << 2;
cpyfunc = cpy_univ;
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;
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;
}
+293 -309
View File
@@ -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));
}
+13 -6
View File
@@ -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);
}
+54 -52
View File
@@ -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);
}
+174 -152
View File
@@ -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;
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);
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;
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;
}
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);
}
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));
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;
return 0;
}
#endif
+114 -118
View File
@@ -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;
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);
}
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;
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 (!ASN1_TIME_check(t))
return NULL;
if (!out || !*out)
{
if (!(ret = ASN1_GENERALIZEDTIME_new ()))
return NULL;
if (out) *out = ret;
}
else ret = *out;
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;
}
/* 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);
/* 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);
BUF_strlcat(str, (char *)t->data, newlen);
return ret;
}
return ret;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
{
ASN1_TIME t;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
t.type = V_ASN1_UTCTIME;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
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;
t.type = V_ASN1_UTCTIME;
return 1;
}
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);
{
if (t == NULL) {
time_t now_t;
time(&now_t);
if (OPENSSL_gmtime(&now_t, tm))
return 1;
return 0;
}
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);
}
+79 -86
View File
@@ -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;
}
+226 -235
View File
@@ -63,280 +63,271 @@
#include <openssl/mem.h>
#include <openssl/time_support.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;
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;
}
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);
}
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;
{
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 (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 (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 ((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;
}
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;
{
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);
}
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;
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;
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;
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 (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;
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;
}
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;
{
struct tm stm, ttm;
int day, sec;
if (!asn1_utctime_to_tm(&stm, s))
return -2;
if (!asn1_utctime_to_tm(&stm, s))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
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 (!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;
{
struct tm tm;
int offset;
memset(&tm,'\0',sizeof tm);
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
# 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. */
}
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
+159 -135
View File
@@ -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;
}
+348 -355
View File
@@ -63,16 +63,13 @@
#include <openssl/err.h>
#include <openssl/mem.h>
/* Used in asn1_mac.h.
* TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
/* 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/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);
@@ -97,414 +94,410 @@ 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,
int 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;
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 (!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;
}
if (inf && !(ret & V_ASN1_CONSTRUCTED))
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, (int)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);
}
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;
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);
}
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 */
/*
* 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;
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;
}
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;
{
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);
}
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;
{
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);
}
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;
{
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 (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);
}
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;
{
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);
}
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;
{
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);
}
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); }
{
return M_ASN1_STRING_type(x);
}
unsigned char * ASN1_STRING_data(ASN1_STRING *x)
{ return M_ASN1_STRING_data(x); }
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return M_ASN1_STRING_data(x);
}
+11 -11
View File
@@ -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 */ ;
+313 -346
View File
@@ -60,376 +60,343 @@
#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_parse2(BIO *bp, const unsigned char **pp, long length,
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 int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
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;
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
p= *pp;
tot=p+length;
op=p-1;
while ((p < tot) && (op < p))
{
op=p;
j=ASN1_get_object(&p,&len,&tag,&xclass,length);
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);
#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)
{
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;
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;
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;
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;
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;
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_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;
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;
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_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);
}
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];
}
+51
View File
@@ -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 <stdio.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../test/scoped_types.h"
// 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.");
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;
}
return true;
}
int main() {
CRYPTO_library_init();
if (!TestLargeTags()) {
return 1;
}
printf("PASS\n");
return 0;
}
+30 -29
View File
@@ -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->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->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;
}
/* 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;
}
+329 -348
View File
@@ -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 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_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;
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_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);
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,
};
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;
}
{
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;
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;
wrlen = 0;
ret = -1;
for(;;)
{
switch (ctx->state)
{
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;
/* 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:
/* Copy any pre data first */
case ASN1_STATE_PRE_COPY:
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
ASN1_STATE_HEADER);
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
ASN1_STATE_HEADER);
if (ret <= 0)
goto done;
if (ret <= 0)
goto done;
break;
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;
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;
break;
case ASN1_STATE_HEADER_COPY:
ret = BIO_write(b->next_bio,
ctx->buf + ctx->bufpos, ctx->buflen);
if (ret <= 0)
goto done;
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;
}
ctx->buflen -= ret;
if (ctx->buflen)
ctx->bufpos += ret;
else {
ctx->bufpos = 0;
ctx->state = ASN1_STATE_DATA_COPY;
}
break;
break;
case ASN1_STATE_DATA_COPY:
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 (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 (ctx->copylen == 0)
ctx->state = ASN1_STATE_HEADER;
if (inl == 0)
goto done;
if (inl == 0)
goto done;
break;
break;
default:
BIO_clear_retry_flags(b);
return 0;
default:
BIO_clear_retry_flags(b);
return 0;
}
}
}
}
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
return (wrlen > 0) ? wrlen : ret;
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;
}
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_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)
{
{
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_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_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_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_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_SET_EX_ARG:
ctx->ex_arg = arg2;
break;
case BIO_C_GET_EX_ARG:
*(void **)arg2 = ctx->ex_arg;
break;
case BIO_C_GET_EX_ARG:
*(void **)arg2 = ctx->ex_arg;
break;
case BIO_CTRL_FLUSH:
if (!b->next_bio)
return 0;
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;
}
/* 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_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;
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);
default:
if (!b->next_bio)
return 0;
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
}
}
return ret;
}
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;
}
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_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_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_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);
}
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);
}
+138 -141
View File
@@ -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;
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p;
int derlen;
const ASN1_AUX *aux;
ASN1_STREAM_ARG sarg;
if (!parg)
return 0;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
ndef_aux = *(NDEF_SUPPORT **)parg;
aux = ndef_aux->it->funcs;
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;
/* 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;
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;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
if (!*ndef_aux->boundary)
return 0;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
return 1;
}
return 1;
}
+128 -134
View File
@@ -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);
}
+131 -139
View File
@@ -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;
{
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;
bs->type = V_ASN1_INTEGER;
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=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);
}
+125 -133
View File
@@ -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;
{
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;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1) {
if (first)
break;
else
goto err_sl;
}
first = 0;
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] == '\\');
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=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;
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;
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);
}
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);
}
+30 -29
View File
@@ -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;
}
+45 -47
View File
@@ -59,54 +59,52 @@
#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;
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 (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++;
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]);
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);
}
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);
}
+1033 -1148
View File
File diff suppressed because it is too large Load Diff
+508 -544
View File
File diff suppressed because it is too large Load Diff
+162 -180
View File
@@ -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);
}
{
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;
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)
{
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_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_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_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_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_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;
}
}
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;
}
{
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;
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_BOOLEAN:
if (it)
*(ASN1_BOOLEAN *)pval = it->size;
else
*(ASN1_BOOLEAN *)pval = -1;
return;
case V_ASN1_NULL:
break;
case V_ASN1_NULL:
break;
case V_ASN1_ANY:
ASN1_primitive_free(pval, NULL);
OPENSSL_free(*pval);
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;
}
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
*pval = NULL;
break;
}
*pval = NULL;
}
+251 -268
View File
@@ -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)
{
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_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_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_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_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)
{
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;
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)
{
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;
{
const ASN1_EXTERN_FUNCS *ef;
switch(it->itype)
{
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_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_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;
}
}
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 */
{
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;
}
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));
}
{
/* 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
/*
* 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;
{
ASN1_TYPE *typ;
ASN1_STRING *str;
int utype;
if (!it)
return 0;
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->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;
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_BOOLEAN:
*(ASN1_BOOLEAN *)pval = it->size;
return 1;
case V_ASN1_NULL:
*pval = (ASN1_VALUE *)1;
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;
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;
}
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;
}
+437 -483
View File
File diff suppressed because it is too large Load Diff
+28 -21
View File
@@ -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);
+62 -52
View File
@@ -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;
}
+97 -82
View File
@@ -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;
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));
/* 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;
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;
/* 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;
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);
}
-1
View File
@@ -116,7 +116,6 @@ static bool TestDecode() {
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
if (!TestEncode() ||
!TestDecode()) {
-1
View File
@@ -412,7 +412,6 @@ static bool TestASN1() {
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
#if defined(OPENSSL_WINDOWS)
// Initialize Winsock.
+3 -3
View File
@@ -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);
+4 -21
View File
@@ -56,6 +56,8 @@
#include <openssl/bn.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -311,27 +313,8 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
}
}
if (rp != ap) {
for (;;) {
if (!dif--) {
break;
}
rp[0] = ap[0];
if (!dif--) {
break;
}
rp[1] = ap[1];
if (!dif--) {
break;
}
rp[2] = ap[2];
if (!dif--) {
break;
}
rp[3] = ap[3];
rp += 4;
ap += 4;
}
if (dif > 0 && rp != ap) {
memcpy(rp, ap, sizeof(*rp) * dif);
}
r->top = max;
-1
View File
@@ -91,7 +91,6 @@ $code=<<___;
#endif
.global bn_mul_mont
.hidden bn_mul_mont
.type bn_mul_mont,%function
.align 5
+8 -68
View File
@@ -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
@@ -220,7 +220,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 +245,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 +536,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__ */
+19 -3
View File
@@ -1770,6 +1770,15 @@ sqr8x_reduction:
.align 32
.L8x_tail_done:
add (%rdx),%r8 # can this overflow?
adc \$0,%r9
adc \$0,%r10
adc \$0,%r11
adc \$0,%r12
adc \$0,%r13
adc \$0,%r14
adc \$0,%r15 # can't overflow, because we
# started with "overhung" part
# of multiplication
xor %rax,%rax
neg $carry
@@ -3116,6 +3125,15 @@ sqrx8x_reduction:
.align 32
.Lsqrx8x_tail_done:
add 24+8(%rsp),%r8 # can this overflow?
adc \$0,%r9
adc \$0,%r10
adc \$0,%r11
adc \$0,%r12
adc \$0,%r13
adc \$0,%r14
adc \$0,%r15 # can't overflow, because we
# started with "overhung" part
# of multiplication
mov $carry,%rax # xor %rax,%rax
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
@@ -3159,13 +3177,11 @@ my ($rptr,$nptr)=("%rdx","%rbp");
my @ri=map("%r$_",(10..13));
my @ni=map("%r$_",(14..15));
$code.=<<___;
xor %rbx,%rbx
xor %ebx,%ebx
sub %r15,%rsi # compare top-most words
adc %rbx,%rbx
mov %rcx,%r10 # -$num
.byte 0x67
or %rbx,%rax
.byte 0x67
mov %rcx,%r9 # -$num
xor \$1,%rax
sar \$3+2,%rcx # cf=0
+4 -5
View File
@@ -166,11 +166,10 @@ void BN_clear(BIGNUM *bn) {
}
const BIGNUM *BN_value_one(void) {
static const BN_ULONG data_one = 1;
static const BIGNUM const_one = {(BN_ULONG *)&data_one, 1, 1, 0,
BN_FLG_STATIC_DATA};
static const BN_ULONG kOneLimbs[1] = { 1 };
static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs);
return &const_one;
return &kOne;
}
void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
@@ -296,7 +295,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;
+9 -22
View File
@@ -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;
}
+55 -34
View File
@@ -330,6 +330,13 @@ int main(int argc, char *argv[]) {
return 0;
}
static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
BIGNUM *raw = NULL;
int ret = BN_hex2bn(&raw, in);
out->reset(raw);
return ret;
}
static bool test_add(FILE *fp) {
ScopedBIGNUM a(BN_new());
ScopedBIGNUM b(BN_new());
@@ -1107,6 +1114,27 @@ static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
return false;
}
}
// Regression test for carry propagation bug in sqr8x_reduction.
if (!HexToBIGNUM(&a, "050505050505") ||
!HexToBIGNUM(&b, "02") ||
!HexToBIGNUM(
&c,
"4141414141414141414141274141414141414141414141414141414141414141"
"4141414141414141414141414141414141414141414141414141414141414141"
"4141414141414141414141800000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000001") ||
!BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) ||
!BN_mul(e.get(), a.get(), a.get(), ctx)) {
return false;
}
if (BN_cmp(d.get(), e.get()) != 0) {
fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n");
return false;
}
return true;
}
@@ -1288,23 +1316,23 @@ static bool test_exp(FILE *fp, BN_CTX *ctx) {
// test_exp_mod_zero tests that 1**0 mod 1 == 0.
static bool test_exp_mod_zero(void) {
ScopedBIGNUM zero(BN_new());
if (!zero) {
ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new());
if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) {
return false;
}
BN_zero(zero.get());
ScopedBN_CTX ctx(BN_CTX_new());
ScopedBIGNUM r(BN_new());
if (!ctx || !r ||
!BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
return false;
}
if (!BN_is_zero(r.get())) {
fprintf(stderr, "1**0 mod 1 = ");
BN_print_fp(stderr, r.get());
fprintf(stderr, ", should be 0\n");
if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
!BN_is_zero(r.get()) ||
!BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
nullptr) ||
!BN_is_zero(r.get()) ||
!BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
nullptr, nullptr) ||
!BN_is_zero(r.get()) ||
!BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
nullptr) ||
!BN_is_zero(r.get())) {
return false;
}
@@ -1545,13 +1573,6 @@ static bool test_dec2bn(BN_CTX *ctx) {
return true;
}
static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
BIGNUM *raw = NULL;
int ret = BN_hex2bn(&raw, in);
out->reset(raw);
return ret;
}
static bool test_hex2bn(BN_CTX *ctx) {
ScopedBIGNUM bn;
int ret = HexToBIGNUM(&bn, "0");
@@ -1778,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},
@@ -1802,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;
}
@@ -1817,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;
@@ -1829,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;
}
@@ -1848,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;
}
@@ -1865,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;
@@ -1873,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;
}
@@ -1905,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;
+9 -4
View File
@@ -63,6 +63,7 @@
#include <string.h>
#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -195,6 +196,11 @@ int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
return 1;
}
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
uint8_t *ptr;
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
}
static const char hextable[] = "0123456789abcdef";
char *BN_bn2hex(const BIGNUM *bn) {
@@ -202,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;
@@ -379,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;
+6 -26
View File
@@ -260,10 +260,10 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
q = BN_MASK2;
} else {
/* n0 < d0 */
#ifdef BN_LLONG
#ifdef BN_ULLONG
BN_ULLONG t2;
#if defined(BN_LLONG) && !defined(div_asm)
#if defined(BN_ULLONG) && !defined(div_asm)
q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
#else
q = div_asm(n0, n1, d0);
@@ -288,34 +288,14 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
}
t2 -= d1;
}
#else /* !BN_LLONG */
#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]))) {
@@ -331,7 +311,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
}
t2l -= d1;
}
#endif /* !BN_LLONG */
#endif /* !BN_ULLONG */
}
l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
@@ -601,7 +581,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
}
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
#ifndef BN_LLONG
#ifndef BN_ULLONG
BN_ULONG ret = 0;
#else
BN_ULLONG ret = 0;
@@ -614,7 +594,7 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
w &= BN_MASK2;
for (i = a->top - 1; i >= 0; i--) {
#ifndef BN_LLONG
#ifndef BN_ULLONG
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
#else
+22 -13
View File
@@ -445,8 +445,12 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0) {
ret = BN_one(r);
return ret;
/* x**0 mod 1 is still zero. */
if (BN_is_one(m)) {
BN_zero(r);
return 1;
}
return BN_one(r);
}
BN_CTX_start(ctx);
@@ -632,8 +636,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
if (bits == 0) {
ret = BN_one(rr);
return ret;
/* x**0 mod 1 is still zero. */
if (BN_is_one(m)) {
BN_zero(rr);
return 1;
}
return BN_one(rr);
}
BN_CTX_start(ctx);
@@ -875,8 +883,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0) {
ret = BN_one(rr);
return ret;
/* x**0 mod 1 is still zero. */
if (BN_is_one(m)) {
BN_zero(rr);
return 1;
}
return BN_one(rr);
}
BN_CTX_start(ctx);
@@ -942,7 +954,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;
}
@@ -1230,17 +1242,14 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
if (bits == 0) {
/* x**0 mod 1 is still zero. */
if (BN_is_one(m)) {
ret = 1;
BN_zero(rr);
} else {
ret = BN_one(rr);
return 1;
}
return ret;
return BN_one(rr);
}
if (a == 0) {
BN_zero(rr);
ret = 1;
return ret;
return 1;
}
BN_CTX_start(ctx);
+1 -1
View File
@@ -279,7 +279,7 @@ BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
* sign*Y*a == A (mod |n|).
*/
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS2 <= 32 ? 450 : 2048))) {
/* Binary inversion algorithm; requires odd modulus.
* This is faster than the general algorithm if the modulus
* is sufficiently small (about 400 .. 500 bits on 32-bit
+15 -257
View File
@@ -61,21 +61,12 @@
#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__)))
#if defined(OPENSSL_WINDOWS)
#define alloca _alloca
#else
#include <alloca.h>
#endif
#ifdef BN_LLONG
#ifdef BN_ULLONG
#define mul_add(r, a, w, c) \
{ \
BN_ULLONG t; \
@@ -100,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); \
@@ -130,101 +122,7 @@
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_LLONG */
#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
#endif /* !BN_ULLONG */
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
@@ -304,95 +202,7 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
}
#else /* !(defined(BN_LLONG) || 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_LLONG) || defined(BN_UMULT_HIGH)) */
#if defined(BN_LLONG)
#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);
@@ -470,9 +280,9 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
return ret;
}
#endif /* !defined(BN_LLONG) */
#endif /* !defined(BN_ULLONG) */
#ifdef BN_LLONG
#ifdef BN_ULLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n) {
BN_ULLONG ll = 0;
@@ -512,7 +322,7 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
return (BN_ULONG)ll;
}
#else /* !BN_LLONG */
#else /* !BN_ULLONG */
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n) {
@@ -569,7 +379,7 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
return (BN_ULONG)c;
}
#endif /* !BN_LLONG */
#endif /* !BN_ULLONG */
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n) {
@@ -631,7 +441,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
#ifdef BN_LLONG
#ifdef BN_ULLONG
/* Keep in mind that additions to multiplication result can not overflow,
* because its high half cannot be all-ones. */
@@ -679,7 +489,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. */
@@ -722,59 +532,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)
#else /* !BN_LLONG */
/* 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_LLONG */
#endif /* !BN_ULLONG */
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
+29 -87
View File
@@ -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,53 +146,48 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
#if !defined(_MSC_VER)
/* MSVC doesn't support two-word integers on 64-bit. */
#define BN_LLONG __int128_t
#define BN_ULLONG __uint128_t
#define BN_ULLONG uint128_t
#endif
#define BN_BITS 128
#define BN_BITS2 64
#define BN_BYTES 8
#define BN_BITS4 32
#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
#define BN_MASK2 (0xffffffffffffffffL)
#define BN_MASK2l (0xffffffffL)
#define BN_MASK2h (0xffffffff00000000L)
#define BN_MASK2h1 (0xffffffff80000000L)
#define BN_TBIT (0x8000000000000000L)
#define BN_MASK2 (0xffffffffffffffffUL)
#define BN_MASK2l (0xffffffffUL)
#define BN_MASK2h (0xffffffff00000000UL)
#define BN_MASK2h1 (0xffffffff80000000UL)
#define BN_TBIT (0x8000000000000000UL)
#define BN_DEC_CONV (10000000000000000000UL)
#define BN_DEC_NUM 19
#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo)
#elif defined(OPENSSL_32_BIT)
#define BN_LLONG int64_t
#define BN_ULLONG uint64_t
#define BN_MASK (0xffffffffffffffffLL)
#define BN_BITS 64
#define BN_BITS2 32
#define BN_BYTES 4
#define BN_BITS4 16
#define BN_MASK2 (0xffffffffL)
#define BN_MASK2l (0xffff)
#define BN_MASK2h1 (0xffff8000L)
#define BN_MASK2h (0xffff0000L)
#define BN_TBIT (0x80000000L)
#define BN_DEC_CONV (1000000000L)
#define BN_MASK2 (0xffffffffUL)
#define BN_MASK2l (0xffffUL)
#define BN_MASK2h1 (0xffff8000UL)
#define BN_MASK2h (0xffff0000UL)
#define BN_TBIT (0x80000000UL)
#define BN_DEC_CONV (1000000000UL)
#define BN_DEC_NUM 9
#define TOBN(hi, lo) lo, hi
#else
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
#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 */
#if defined(BN_LLONG)
#define STATIC_BIGNUM(x) \
{ \
(BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
}
#if defined(BN_ULLONG)
#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
#endif
@@ -220,67 +217,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_LLONG)
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
#endif
#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_LLONG) */
#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
+5 -11
View File
@@ -134,7 +134,6 @@ BN_MONT_CTX *BN_MONT_CTX_new(void) {
memset(ret, 0, sizeof(BN_MONT_CTX));
BN_init(&ret->RR);
BN_init(&ret->N);
BN_init(&ret->Ni);
return ret;
}
@@ -146,7 +145,6 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont) {
BN_free(&mont->RR);
BN_free(&mont->N);
BN_free(&mont->Ni);
OPENSSL_free(mont);
}
@@ -156,11 +154,9 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) {
}
if (!BN_copy(&to->RR, &from->RR) ||
!BN_copy(&to->N, &from->N) ||
!BN_copy(&to->Ni, &from->Ni)) {
!BN_copy(&to->N, &from->N)) {
return NULL;
}
to->ri = from->ri;
to->n0[0] = from->n0[0];
to->n0[1] = from->n0[1];
return to;
@@ -193,8 +189,6 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
tmod.dmax = 2;
tmod.neg = 0;
mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
/* Only certain BN_BITS2<=32 platforms actually make use of
* n0[1], and we could use the #else case (with a shorter R
@@ -278,9 +272,10 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
mont->n0[1] = 0;
#endif
/* setup RR for conversions */
/* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */
int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
BN_zero(&(mont->RR));
if (!BN_set_bit(&(mont->RR), mont->ri * 2)) {
if (!BN_set_bit(&(mont->RR), ri * 2)) {
goto err;
}
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
@@ -422,11 +417,10 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
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);
const BIGNUM *n = &mont->N;
nl=n->top;
if (nl == 0) { ret->top=0; return(1); }
+6 -26
View File
@@ -62,6 +62,10 @@
#include "internal.h"
#define BN_MUL_RECURSIVE_SIZE_NORMAL 16
#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
BN_ULONG *rr;
@@ -107,31 +111,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 +597,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 */
+21 -28
View File
@@ -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];
+1
View File
@@ -5,6 +5,7 @@ add_library(
OBJECT
asn1_compat.c
ber.c
cbs.c
cbb.c
@@ -1,4 +1,4 @@
/* Copyright (c) 2014, Google Inc.
/* 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
@@ -12,6 +12,40 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
/* This header is linked to under the names of several headers that have been
* removed. It's possible to put a #error in here in order to catch that an
* clean up older code. */
#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;
}
+129 -88
View File
@@ -14,6 +14,7 @@
#include <openssl/bytestring.h>
#include <assert.h>
#include <string.h>
#include "internal.h"
@@ -24,11 +25,36 @@
* 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_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 +75,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 +95,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,111 +103,86 @@ 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 (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 (is_eoc(header_len, &contents)) {
return looking_for_eoc;
}
if (!squash_header) {
if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
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 (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;
}
continue;
}
if (!CBS_skip(&contents, header_len)) {
return 0;
}
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 +206,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;
}
+101 -12
View File
@@ -12,6 +12,10 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#if !defined(__STDC_CONSTANT_MACROS)
#define __STDC_CONSTANT_MACROS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -22,7 +26,6 @@
#include <openssl/bytestring.h>
#include "internal.h"
#include "../internal.h"
#include "../test/scoped_types.h"
@@ -341,12 +344,14 @@ static bool TestCBBPrefixed() {
size_t buf_len;
CBB cbb, contents, inner_contents, inner_inner_contents;
if (!CBB_init(&cbb, 0)) {
return false;
}
if (!CBB_add_u8_length_prefixed(&cbb, &contents) ||
if (!CBB_init(&cbb, 0) ||
CBB_len(&cbb) != 0 ||
!CBB_add_u8_length_prefixed(&cbb, &contents) ||
!CBB_add_u8_length_prefixed(&cbb, &contents) ||
!CBB_add_u8(&contents, 1) ||
CBB_len(&contents) != 1 ||
!CBB_flush(&cbb) ||
CBB_len(&cbb) != 3 ||
!CBB_add_u16_length_prefixed(&cbb, &contents) ||
!CBB_add_u16(&contents, 0x203) ||
!CBB_add_u24_length_prefixed(&cbb, &contents) ||
@@ -574,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};
@@ -604,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,
@@ -612,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 {
@@ -627,9 +694,9 @@ static const ASN1Uint64Test kASN1Uint64Tests[] = {
{127, "\x02\x01\x7f", 3},
{128, "\x02\x02\x00\x80", 4},
{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
{OPENSSL_U64(0x0102030405060708),
{UINT64_C(0x0102030405060708),
"\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
{OPENSSL_U64(0xffffffffffffffff),
{UINT64_C(0xffffffffffffffff),
"\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
};
@@ -698,12 +765,32 @@ static bool TestASN1Uint64() {
return true;
}
static int TestZero() {
static bool TestZero() {
CBB cbb;
CBB_zero(&cbb);
// Calling |CBB_cleanup| on a zero-state |CBB| must not crash.
CBB_cleanup(&cbb);
return 1;
return true;
}
static bool TestCBBReserve() {
uint8_t buf[10];
uint8_t *ptr;
size_t len;
ScopedCBB cbb;
if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
// Too large.
CBB_reserve(cbb.get(), &ptr, 11) ||
// Successfully reserve the entire space.
!CBB_reserve(cbb.get(), &ptr, 10) ||
ptr != buf ||
// Advancing under the maximum bytes is legal.
!CBB_did_write(cbb.get(), 5) ||
!CBB_finish(cbb.get(), NULL, &len) ||
len != 5) {
return false;
}
return true;
}
int main(void) {
@@ -722,9 +809,11 @@ int main(void) {
!TestCBBDiscardChild() ||
!TestCBBASN1() ||
!TestBerConvert() ||
!TestImplicitString() ||
!TestASN1Uint64() ||
!TestGetOptionalASN1Bool() ||
!TestZero()) {
!TestZero() ||
!TestCBBReserve()) {
return 1;
}
+63 -29
View File
@@ -25,6 +25,7 @@ void CBB_zero(CBB *cbb) {
}
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
/* This assumes that |cbb| has already been zeroed. */
struct cbb_buffer_st *base;
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
@@ -37,16 +38,15 @@ static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
base->cap = cap;
base->can_resize = 1;
memset(cbb, 0, sizeof(CBB));
cbb->base = base;
cbb->is_top_level = 1;
return 1;
}
int CBB_init(CBB *cbb, size_t initial_capacity) {
uint8_t *buf;
CBB_zero(cbb);
buf = OPENSSL_malloc(initial_capacity);
uint8_t *buf = OPENSSL_malloc(initial_capacity);
if (initial_capacity > 0 && buf == NULL) {
return 0;
}
@@ -60,6 +60,8 @@ int CBB_init(CBB *cbb, size_t initial_capacity) {
}
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
CBB_zero(cbb);
if (!cbb_init(cbb, buf, len)) {
return 0;
}
@@ -82,8 +84,8 @@ void CBB_cleanup(CBB *cbb) {
cbb->base = NULL;
}
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
size_t len) {
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
size_t len) {
size_t newlen;
if (base == NULL) {
@@ -119,7 +121,17 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
if (out) {
*out = base->buf + base->len;
}
base->len = newlen;
return 1;
}
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
size_t len) {
if (!cbb_buffer_reserve(base, out, len)) {
return 0;
}
/* This will not overflow or |cbb_buffer_reserve| would have failed. */
base->len += len;
return 1;
}
@@ -177,28 +189,28 @@ int CBB_flush(CBB *cbb) {
return 0;
}
if (cbb->child == NULL || cbb->pending_len_len == 0) {
if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
return 1;
}
child_start = cbb->offset + cbb->pending_len_len;
child_start = cbb->child->offset + cbb->child->pending_len_len;
if (!CBB_flush(cbb->child) ||
child_start < cbb->offset ||
child_start < cbb->child->offset ||
cbb->base->len < child_start) {
return 0;
}
len = cbb->base->len - child_start;
if (cbb->pending_is_asn1) {
if (cbb->child->pending_is_asn1) {
/* For ASN.1 we assume that we'll only need a single byte for the length.
* If that turned out to be incorrect, we have to move the contents along
* in order to make space. */
size_t len_len;
uint8_t initial_length_byte;
assert (cbb->pending_len_len == 1);
assert (cbb->child->pending_len_len == 1);
if (len > 0xfffffffe) {
/* Too large. */
@@ -230,12 +242,13 @@ int CBB_flush(CBB *cbb) {
memmove(cbb->base->buf + child_start + extra_bytes,
cbb->base->buf + child_start, len);
}
cbb->base->buf[cbb->offset++] = initial_length_byte;
cbb->pending_len_len = len_len - 1;
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
cbb->child->pending_len_len = len_len - 1;
}
for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
cbb->base->buf[cbb->offset + i] = len;
for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
i--) {
cbb->base->buf[cbb->child->offset + i] = len;
len >>= 8;
}
if (len != 0) {
@@ -244,17 +257,20 @@ int CBB_flush(CBB *cbb) {
cbb->child->base = NULL;
cbb->child = NULL;
cbb->pending_len_len = 0;
cbb->pending_is_asn1 = 0;
cbb->offset = 0;
return 1;
}
const uint8_t *CBB_data(const CBB *cbb) {
assert(cbb->child == NULL);
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
}
size_t CBB_len(const CBB *cbb) {
assert(cbb->child == NULL);
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
return cbb->base->len;
return cbb->base->len - cbb->offset - cbb->pending_len_len;
}
static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
@@ -265,7 +281,7 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
return 0;
}
cbb->offset = cbb->base->len;
size_t offset = cbb->base->len;
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
return 0;
}
@@ -274,8 +290,9 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->pending_len_len = len_len;
cbb->pending_is_asn1 = 0;
cbb->child->offset = offset;
cbb->child->pending_len_len = len_len;
cbb->child->pending_is_asn1 = 0;
return 1;
}
@@ -303,7 +320,7 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
return 0;
}
cbb->offset = cbb->base->len;
size_t offset = cbb->base->len;
if (!CBB_add_u8(cbb, 0)) {
return 0;
}
@@ -311,8 +328,9 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->pending_len_len = 1;
cbb->pending_is_asn1 = 1;
cbb->child->offset = offset;
cbb->child->pending_len_len = 1;
cbb->child->pending_is_asn1 = 1;
return 1;
}
@@ -336,6 +354,25 @@ int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
return 1;
}
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
if (!CBB_flush(cbb) ||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
return 0;
}
return 1;
}
int CBB_did_write(CBB *cbb, size_t len) {
size_t newlen = cbb->base->len + len;
if (cbb->child != NULL ||
newlen < cbb->base->len ||
newlen > cbb->base->cap) {
return 0;
}
cbb->base->len = newlen;
return 1;
}
int CBB_add_u8(CBB *cbb, uint8_t value) {
if (!CBB_flush(cbb)) {
return 0;
@@ -365,13 +402,10 @@ void CBB_discard_child(CBB *cbb) {
return;
}
cbb->base->len = cbb->offset;
cbb->base->len = cbb->child->offset;
cbb->child->base = NULL;
cbb->child = NULL;
cbb->pending_len_len = 0;
cbb->pending_is_asn1 = 0;
cbb->offset = 0;
}
int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
+39 -10
View File
@@ -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 */
+18 -13
View File
@@ -25,6 +25,9 @@
#include <openssl/chacha.h>
#include "../internal.h"
#if defined(ASM_GEN) || \
!defined(OPENSSL_WINDOWS) && \
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
@@ -80,8 +83,8 @@ typedef unsigned vec __attribute__((vector_size(16)));
#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 LOAD(m) (vec) _mm_loadu_si128((const __m128i *)(m))
#define LOAD_ALIGNED(m) (vec) _mm_load_si128((const __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))
@@ -157,26 +160,28 @@ void CRYPTO_chacha_20(
const uint8_t nonce[12],
uint32_t counter)
{
unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
unsigned iters, i;
unsigned *op = (unsigned *)out;
const unsigned *ip = (const unsigned *)in;
const unsigned *kp = (const unsigned *)key;
#if defined(__ARM_NEON__)
uint32_t np[3];
uint8_t alignment_buffer[16] __attribute__((aligned(16)));
alignas(16) uint8_t alignment_buffer[16];
#endif
vec s0, s1, s2, s3;
__attribute__ ((aligned (16))) unsigned chacha_const[] =
alignas(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]);
s1 = LOAD(&((const vec*)kp)[0]);
s2 = LOAD(&((const vec*)kp)[1]);
s3 = (vec){
counter,
((uint32_t*)nonce)[0],
((uint32_t*)nonce)[1],
((uint32_t*)nonce)[2]
((const uint32_t*)nonce)[0],
((const uint32_t*)nonce)[1],
((const uint32_t*)nonce)[2]
};
for (iters = 0; iters < inlen/(BPI*64); iters++)
@@ -286,7 +291,7 @@ void CRYPTO_chacha_20(
inlen = inlen % 64;
if (inlen)
{
__attribute__ ((aligned (16))) vec buf[4];
alignas(16) vec buf[4];
vec v0,v1,v2,v3;
v0 = s0; v1 = s1; v2 = s2; v3 = s3;
for (i = CHACHA_RNDS/2; i; i--)
@@ -316,7 +321,7 @@ void CRYPTO_chacha_20(
buf[0] = REVV_BE(v0 + s0);
for (i=inlen & ~15; i<inlen; i++)
((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
((char *)op)[i] = ((const char *)ip)[i] ^ ((const char *)buf)[i];
}
}
+1 -1
View File
@@ -200,7 +200,7 @@ struct AEADName {
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_rfc7539 },
{ "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 },
+1 -1
View File
@@ -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;
}
+3 -3
View File
@@ -384,7 +384,7 @@ 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;
unsigned num = (unsigned)ctx->num;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.ctr) {
@@ -394,7 +394,7 @@ static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
dat->block);
}
ctx->num = (size_t)num;
ctx->num = (int)num;
return 1;
}
@@ -1652,7 +1652,7 @@ static int aead_aes_ctr_hmac_sha256_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
if (in_len + aes_ctx->tag_len < in_len ||
/* This input is so large it would overflow the 32-bit block counter. */
in_len_64 >= (OPENSSL_U64(1) << 32) * AES_BLOCK_SIZE) {
in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
+27 -30
View File
@@ -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);
@@ -108,10 +103,11 @@ static void aead_poly1305(aead_poly1305_update update,
CRYPTO_poly1305_finish(&ctx, tag);
}
static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
uint8_t *out, size_t *out_len, size_t max_out_len,
const uint8_t nonce[12], const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
static int seal_impl(aead_poly1305_update poly1305_update,
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t nonce[12],
const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
@@ -138,7 +134,7 @@ static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
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);
@@ -146,10 +142,11 @@ static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
return 1;
}
static int open(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
uint8_t *out, size_t *out_len, size_t max_out_len,
const uint8_t nonce[12], const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
static int open_impl(aead_poly1305_update poly1305_update,
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t nonce[12],
const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
size_t plaintext_len;
const uint64_t in_len_64 = in_len;
@@ -171,7 +168,7 @@ static int open(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
}
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) {
@@ -212,8 +209,8 @@ static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
return seal(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
}
static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
@@ -225,8 +222,8 @@ static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
return open(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
}
static const EVP_AEAD aead_chacha20_poly1305 = {
@@ -243,10 +240,14 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
NULL, /* get_iv */
};
const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
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) {
@@ -267,8 +268,8 @@ static int aead_chacha20_poly1305_old_seal(
uint8_t nonce_96[12];
memset(nonce_96, 0, 4);
memcpy(nonce_96 + 4, nonce, 8);
return seal(poly1305_update_old, ctx, out, out_len, max_out_len, nonce_96, in,
in_len, ad, ad_len);
return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
nonce_96, in, in_len, ad, ad_len);
}
static int aead_chacha20_poly1305_old_open(
@@ -282,8 +283,8 @@ static int aead_chacha20_poly1305_old_open(
uint8_t nonce_96[12];
memset(nonce_96, 0, 4);
memcpy(nonce_96 + 4, nonce, 8);
return open(poly1305_update_old, ctx, out, out_len, max_out_len, nonce_96, in,
in_len, ad, ad_len);
return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
nonce_96, in, in_len, ad, ad_len);
}
static const EVP_AEAD aead_chacha20_poly1305_old = {
@@ -303,7 +304,3 @@ static const EVP_AEAD aead_chacha20_poly1305_old = {
const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
return &aead_chacha20_poly1305_old;
}
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305_old;
}
-311
View File
@@ -54,21 +54,13 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/aead.h>
#include <assert.h>
#include <string.h>
#include <openssl/cipher.h>
#include <openssl/cpu.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/rc4.h>
#include "internal.h"
static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
const uint8_t *iv, int enc) {
@@ -93,306 +85,3 @@ static const EVP_CIPHER rc4 = {
NULL /* cleanup */, NULL /* ctrl */, };
const EVP_CIPHER *EVP_rc4(void) { return &rc4; }
struct aead_rc4_md5_tls_ctx {
RC4_KEY rc4;
MD5_CTX head, tail, md;
size_t payload_length;
unsigned char tag_len;
};
static int
aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t tag_len) {
struct aead_rc4_md5_tls_ctx *rc4_ctx;
size_t i;
uint8_t hmac_key[MD5_CBLOCK];
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = MD5_DIGEST_LENGTH;
}
if (tag_len > MD5_DIGEST_LENGTH) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
/* The keys consists of |MD5_DIGEST_LENGTH| bytes of HMAC(MD5) key followed
* by some number of bytes of RC4 key. */
if (key_len <= MD5_DIGEST_LENGTH) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0;
}
rc4_ctx = OPENSSL_malloc(sizeof(struct aead_rc4_md5_tls_ctx));
if (rc4_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
memset(rc4_ctx, 0, sizeof(struct aead_rc4_md5_tls_ctx));
RC4_set_key(&rc4_ctx->rc4, key_len - MD5_DIGEST_LENGTH,
key + MD5_DIGEST_LENGTH);
memset(hmac_key, 0, sizeof(hmac_key));
memcpy(hmac_key, key, MD5_DIGEST_LENGTH);
for (i = 0; i < sizeof(hmac_key); i++) {
hmac_key[i] ^= 0x36;
}
MD5_Init(&rc4_ctx->head);
MD5_Update(&rc4_ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++) {
hmac_key[i] ^= 0x36 ^ 0x5c;
}
MD5_Init(&rc4_ctx->tail);
MD5_Update(&rc4_ctx->tail, hmac_key, sizeof(hmac_key));
rc4_ctx->tag_len = tag_len;
ctx->aead_state = rc4_ctx;
return 1;
}
static void aead_rc4_md5_tls_cleanup(EVP_AEAD_CTX *ctx) {
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
OPENSSL_cleanse(rc4_ctx, sizeof(struct aead_rc4_md5_tls_ctx));
OPENSSL_free(rc4_ctx);
}
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
#define STITCHED_CALL
/* rc4_md5_enc is defined in rc4_md5-x86_64.pl */
void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, MD5_CTX *ctx,
const void *inp, size_t blocks);
#endif
static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
MD5_CTX md;
#if defined(STITCHED_CALL)
size_t rc4_off, md5_off, blocks;
#else
const size_t rc4_off = 0;
const size_t md5_off = 0;
#endif
uint8_t digest[MD5_DIGEST_LENGTH];
if (in_len + rc4_ctx->tag_len < in_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE);
return 0;
}
if (max_out_len < in_len + rc4_ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
/* The MAC's payload begins with the additional data. See
* https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
MD5_Update(&md, ad, ad_len);
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
* length for legacy ciphers. */
uint8_t ad_extra[2];
ad_extra[0] = (uint8_t)(in_len >> 8);
ad_extra[1] = (uint8_t)(in_len & 0xff);
MD5_Update(&md, ad_extra, sizeof(ad_extra));
#if defined(STITCHED_CALL)
/* 32 is $MOD from rc4_md5-x86_64.pl. */
rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
md5_off = MD5_CBLOCK - md.num;
/* Ensure RC4 is behind MD5. */
if (rc4_off > md5_off) {
md5_off += MD5_CBLOCK;
}
assert(md5_off >= rc4_off);
if (in_len > md5_off && (blocks = (in_len - md5_off) / MD5_CBLOCK) &&
(OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
/* Process the initial portions of the plaintext normally. */
MD5_Update(&md, in, md5_off);
RC4(&rc4_ctx->rc4, rc4_off, in, out);
/* Process the next |blocks| blocks of plaintext with stitched routines. */
rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, in + md5_off,
blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
md.Nh += blocks >> 29;
md.Nl += blocks <<= 3;
if (md.Nl < (unsigned int)blocks) {
md.Nh++;
}
} else {
rc4_off = 0;
md5_off = 0;
}
#endif
/* Finish computing the MAC. */
MD5_Update(&md, in + md5_off, in_len - md5_off);
MD5_Final(digest, &md);
memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
MD5_Update(&md, digest, sizeof(digest));
if (rc4_ctx->tag_len == MD5_DIGEST_LENGTH) {
MD5_Final(out + in_len, &md);
} else {
MD5_Final(digest, &md);
memcpy(out + in_len, digest, rc4_ctx->tag_len);
}
/* Encrypt the remainder of the plaintext and the MAC. */
RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
RC4(&rc4_ctx->rc4, MD5_DIGEST_LENGTH, out + in_len, out + in_len);
*out_len = in_len + rc4_ctx->tag_len;
return 1;
}
static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
MD5_CTX md;
size_t plaintext_len;
#if defined(STITCHED_CALL)
unsigned int l;
size_t rc4_off, md5_off, blocks;
extern unsigned int OPENSSL_ia32cap_P[];
#else
const size_t rc4_off = 0;
const size_t md5_off = 0;
#endif
uint8_t digest[MD5_DIGEST_LENGTH];
if (in_len < rc4_ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
plaintext_len = in_len - rc4_ctx->tag_len;
if (nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_len < in_len) {
/* This requires that the caller provide space for the MAC, even though it
* will always be removed on return. */
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
/* The MAC's payload begins with the additional data. See
* https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
MD5_Update(&md, ad, ad_len);
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
* length for legacy ciphers. */
uint8_t ad_extra[2];
ad_extra[0] = (uint8_t)(plaintext_len >> 8);
ad_extra[1] = (uint8_t)(plaintext_len & 0xff);
MD5_Update(&md, ad_extra, sizeof(ad_extra));
#if defined(STITCHED_CALL)
rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
md5_off = MD5_CBLOCK - md.num;
/* Ensure MD5 is a full block behind RC4 so it has plaintext to operate on in
* both normal and stitched routines. */
if (md5_off > rc4_off) {
rc4_off += 2 * MD5_CBLOCK;
} else {
rc4_off += MD5_CBLOCK;
}
if (in_len > rc4_off && (blocks = (in_len - rc4_off) / MD5_CBLOCK) &&
(OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
/* Decrypt the initial portion of the ciphertext and digest the plaintext
* normally. */
RC4(&rc4_ctx->rc4, rc4_off, in, out);
MD5_Update(&md, out, md5_off);
/* Decrypt and digest the next |blocks| blocks of ciphertext with the
* stitched routines. */
rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, out + md5_off,
blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
l = (md.Nl + (blocks << 3)) & 0xffffffffU;
if (l < md.Nl) {
md.Nh++;
}
md.Nl = l;
md.Nh += blocks >> 29;
} else {
md5_off = 0;
rc4_off = 0;
}
#endif
/* Process the remainder of the input. */
RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
MD5_Update(&md, out + md5_off, plaintext_len - md5_off);
MD5_Final(digest, &md);
/* Calculate HMAC and verify it */
memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
MD5_Update(&md, digest, MD5_DIGEST_LENGTH);
MD5_Final(digest, &md);
if (CRYPTO_memcmp(out + plaintext_len, digest, rc4_ctx->tag_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
*out_len = plaintext_len;
return 1;
}
static int aead_rc4_md5_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
const RC4_KEY **out_key) {
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
*out_key = &rc4_ctx->rc4;
return 1;
}
static const EVP_AEAD aead_rc4_md5_tls = {
16 + MD5_DIGEST_LENGTH, /* key len (RC4 + MD5) */
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
aead_rc4_md5_tls_init,
NULL, /* init_with_direction */
aead_rc4_md5_tls_cleanup,
aead_rc4_md5_tls_seal,
aead_rc4_md5_tls_open,
aead_rc4_md5_tls_get_rc4_state,
NULL, /* get_iv */
};
const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
+38 -24
View File
@@ -20,6 +20,7 @@
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
#include <openssl/type_check.h>
@@ -111,7 +112,6 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
@@ -146,17 +146,13 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
* in-place. */
uint8_t mac[EVP_MAX_MD_SIZE];
unsigned mac_len;
HMAC_CTX hmac_ctx;
HMAC_CTX_init(&hmac_ctx);
if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
!HMAC_Update(&hmac_ctx, ad, ad_len) ||
!HMAC_Update(&hmac_ctx, ad_extra, sizeof(ad_extra)) ||
!HMAC_Update(&hmac_ctx, in, in_len) ||
!HMAC_Final(&hmac_ctx, mac, &mac_len)) {
HMAC_CTX_cleanup(&hmac_ctx);
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) ||
!HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) ||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) {
return 0;
}
HMAC_CTX_cleanup(&hmac_ctx);
/* Configure the explicit IV. */
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
@@ -216,7 +212,6 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
@@ -324,18 +319,14 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
* implemented. */
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE);
HMAC_CTX hmac_ctx;
HMAC_CTX_init(&hmac_ctx);
unsigned mac_len_u;
if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
!HMAC_Update(&hmac_ctx, ad_fixed, ad_len) ||
!HMAC_Update(&hmac_ctx, out, data_len) ||
!HMAC_Final(&hmac_ctx, mac, &mac_len_u)) {
HMAC_CTX_cleanup(&hmac_ctx);
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) ||
!HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) ||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) {
return 0;
}
mac_len = mac_len_u;
HMAC_CTX_cleanup(&hmac_ctx);
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
record_mac = &out[data_len];
@@ -359,6 +350,13 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 1;
}
static int aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5(),
0);
}
static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
@@ -433,8 +431,8 @@ static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
EVP_sha1(), 1);
}
static int aead_rc4_sha1_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
const RC4_KEY **out_key) {
static int aead_rc4_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
const RC4_KEY **out_key) {
const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) {
return 0;
@@ -464,18 +462,32 @@ static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
EVP_sha1(), 1 /* implicit iv */);
}
static const EVP_AEAD aead_rc4_md5_tls = {
MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_rc4_md5_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
aead_rc4_tls_get_rc4_state, /* get_rc4_state */
NULL, /* get_iv */
};
static const EVP_AEAD aead_rc4_sha1_tls = {
SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
NULL, /* init */
aead_rc4_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
aead_rc4_sha1_tls_get_rc4_state, /* get_rc4_state */
NULL, /* get_iv */
aead_rc4_tls_get_rc4_state, /* get_rc4_state */
NULL, /* get_iv */
};
static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
@@ -618,6 +630,8 @@ static const EVP_AEAD aead_null_sha1_tls = {
NULL, /* get_iv */
};
const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; }
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
@@ -418,5 +418,107 @@ AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813
CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
TAG: f7d3b58a34a86e99267e5db206f17bbe
# BoringSSL has additional tests here for truncated tags. *ring* doesn't
# support tag truncation, so those tests were removed.
KEY: 3304e4917ad7777b86c26a636292c9cc4c10d32003c49e07209eb0ef8505031a
NONCE: 4d572d116fbd8c4d
IN: 2f242c2ba33790ecef862b0e077ff8b15eb9d10cf2ff621ed65902494431dcbd
AD: e699bbf250cdd93d229d0740e433897e2d19132e2b722df8b69bb6a7c2cf3b93
CT: fb81e30436e437c7f686f86b1b65c73549a9d09db810d320785c3634934150b3
TAG: 8b
KEY: ed6057bb163f1609ff28b938122f495e3d5ae4ec3dbd7456c9b5c82e28e952dc
NONCE: e6ff6852f3a3afde
IN: 3c50edc967eb0b3b2355f6400e0a036e796c8b7d72c5e583a86e820d53e76c43
AD: 2441db55148e14e9e241d68296eb60d529408f0534143089671bce546db96d88
CT: 6ecabccee31519374d4bed11296e7483d1cb759bea3f4446a96bda8b4ca6d7ac
TAG: 355f
KEY: 73568183c1f9725af30e0f2067606ce802c3fe3ab5cff8d02b3db8c35176ee0d
NONCE: 0bc9e19321b3d00a
IN: ec2590af5ccd226a32ff750c1b029c11e3dd76c469a5579da9418e4c3fdc0d41
AD: df30160ae0cbf2cf8992221bd62dffe691dd602afa784ca691479e957af3acf1
CT: 9e8d8ac30626f8b831448d6976933aa5bb8c6dbc794e1f4b7eeb0e4a59342c07
TAG: 9fd36a
KEY: 273bcb3f8c067da4ec3418799ad40e7e4aee74ad7e629499d646df4a7e585025
NONCE: f60be3eb894b4030
IN: 697498ba964d5ef401da4d94844fab1efc635e7157d0831a325bb5a4cf1fbd34
AD: 9129715deab14f02c76ba8172571b1fa9d50365cd795bfccdfc28e7e7b4f66fc
CT: bd4cd5af83be1c13933302675d9fcaf1c4cacdf269f6ff441d1ea2211c54e7ed
TAG: 7ab12a37
KEY: ad39610c2e6a6d0961207390e076e972c2edadca885c92965fa648b2ce34fdbf
NONCE: a90db690bba83b78
IN: 31c49e3cd3d80a82e6b90316dfb94b38b8a23042519bf40c8181fec873c99002
AD: ddbd7d821d18d44c66295abf245b227b5cf4366811b7b34c07679600abdbfc29
CT: 94628fc303a0546edd51e966f2bd87968f37800c607d5e5a91f727fc1fec406f
TAG: c22ec4e4c8
KEY: 29984954060ba06ece1bcfc0e50195f4632c6df48da1e02ae6c14f7065668971
NONCE: cce53a25aeeaf747
IN: b9b87433a9894f3c9ca8212623d62369a565a2edcddd276e07d611eda3597426
AD: 19fa9aa59697559d8b46d9cd49c3b763c0b73b26b9e334a3eeac2c86fdbaca8d
CT: b68c83397770c36f073710882fa86d43b0e54e8efef0ff75075604d0d7ec4e1b
TAG: 40d4ab752f3d
KEY: 5c3b838b84100b2a818c0842e9fe19a7c50cf5f3ea73364c816ef588e500ff3f
NONCE: fdf6b0229e4bcc2a
IN: 2ba91904c143be99297b39f52856904af41705c176c8c6554b6bc89bddffbcc1
AD: 3539d9dd821f004f4ced1637071f4be6abd7fe98f017f0a8ce3f49dc8d496f46
CT: ff9d6d924e737a1df8c2bd3047e40ab401f903aa0e5b51acb991bac38ac2cc4d
TAG: 1bcaa415a6a3c7
KEY: 6d65e627cab6d5eb1a088b25bd6c3a8a004a7a19cccae909d62fed3559c812f7
NONCE: 7ff00a8798b792de
IN: 6848ee4ac820291a2e1dc3baad97f1ad8b7160dfeaa1bc83b2700ae42b5a366b
AD: d2437b1306bf0ea211449fac863ca0d1074d84caee9009c5d54b9e9bdc8de6b1
CT: 2da0abe2a71e1c0b1ab309c160a8cebe45c6e16170aa5561806484ba2b5b9a9a
TAG: 566003e1f78d2a90
KEY: 63401046a96efbc8c6483a2c396b2a593d3fae0db565525b85999fae13a46b6a
NONCE: 051393d775e635ee
IN: 2b4b6477580382aae782f8b5772c0948a444d8d95caacd85c0856c7e4393fe09
AD: 3d84d2e70e9c062d1f511eb685a9a90c8d5fa50eadf8455c7148666b3e7155e0
CT: 880c1123e54fd8ffb3c293720dd174913572e619ef46504cdaa64fc451b0ec1c
TAG: 339274339c88d50ac0
KEY: 291fccfce0782f1787d62d4b9293d2ada4c04d37a8288ba9ba9aae0d31aad204
NONCE: 7450bbd62e4aba7b
IN: adc251e793181e5d4c4bd983b853eb13f2096ccb340996b6eca4cd2157efcec7
AD: 4c598f6deedc8c1d97da33654763495cca3517430eec4edb006b10c95e031ae6
CT: 28bda22e4922cd8ff6739cd8a6bdafce036d9c61a145a65ca1b86f6d4d3206a1
TAG: d98fd43fe7ac74d4b016
KEY: fa3a9674d4a0eb36b2f7547c956443d09e6b4e4acfc9deda838eb7ebdb999a8d
NONCE: 0a2572592c3bbbf6
IN: ae27f70fda9f5a5be0f704a27f0b8a9c04ce83d3c2e0d7ec152da25f473b0c8a
AD: 6ee8705a9a3655d198497ad410da02005872ecbe397824851b80f4050bfdd311
CT: f356cbd88e4e2aff62d91e3f914032085388955bbba995fde013758b8702e38f
TAG: 00324c76fecd3f50e1e3b8
KEY: 471ec87b992b104d369748d96856b5f66149cb45ca05c17f29d24eb9526fe6db
NONCE: 23a2df9ed0b47439
IN: 2b9452bca0f48e5519ec3d0736597608df6ad9ce799eba913cff71573d79c092
AD: a56722ddfaee5f1b64398c225ee8bcdcfde5c2127101c363bfac52bc409c1082
CT: 7bbc464aac5dd29c25262fe0b116c176d827c2cc8dd63428393b0a9110f3c194
TAG: 2e87f4a6663a62e47c7e197f
KEY: a29d1cfd4ccdc18803fbca9500f4bb29ce99cfcbf8acc41b8208dae4b7ee5d64
NONCE: 634f99e88e237ef0
IN: 09ee5982c5743f396d0c29c13e3fbb8fb89f61705da05466291e010effd51a5c
AD: 564dddfcc3227b413244f1105b610f192decf15c4cfa067f4d7fcd6bd7af11b8
CT: 32916b67a6f32733623344c98c49773f3e721dc2ded105fb245799525bc9c84c
TAG: ff463c07e7ef831321d3fd775f
KEY: 08ba23616d911188f91da063278bef1237dcbf17f52585e53c2c4b6cf3ac9f0d
NONCE: 989ae593eddd3874
IN: 749152c9478944c8271c0c11e07bc1c569eec01493e65b3b94842a1bf5d721f8
AD: a12d1a45b7c9b91ab08751a70b753714052ad24e0b2619fe8c3be303c65f2dbc
CT: 34c40538ee1d22ddf8ac290dd7d423dfc622b5cf8f3412a5343e277822aea713
TAG: 014c7c678e0949e88071d1fe3531
KEY: c2ba8bed8634156afc6bfe3754c91744d4131de39d059f3a866399f916553b5c
NONCE: 80fbf7b433a4cd9c
IN: 419be6623e7964f9f26068dd969e4a139617e67c5ffb269b3013c433fe771c77
AD: 3937592db78a61ff469691b6800792019bc2b3d42512f23c1b1a66a8274495cb
CT: 9d5bd1c7e766763eb00684c038043111d8c6390a8d6e17a15ef97c02ab16f09c
TAG: a64d0eeb4a01481ec0cee8c1c357e3
+108 -4
View File
@@ -47,8 +47,8 @@ AD: "123456789abcdef0"
CT: e275aeb341e1fc9a70c4fd4496fc7cdb
TAG: 41acd0560ea6843d3e5d4e5babf6e946
# Test vectors from chacha20_poly1305_deprecated_tests.txt, modified for the
# RFC 7539 AEAD construction.
# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539
# AEAD construction.
KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
NONCE: 000000003de9c0da2bd7f91e
@@ -470,5 +470,109 @@ AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813
CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
TAG: 296a397d280d026fc3627f4718971be9
# BoringSSL has additional tests here for truncated tags. *ring* doesn't
# support tag truncation, so those tests were removed.
# Tag truncation tests.
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c2
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f3
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f37465
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a84
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a8413
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a841386
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a84138648
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a84138648a5
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
NONCE: 000000005d9856060c54ab06
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
TAG: d3f7b9c295f374651a84138648a591
+39 -10
View File
@@ -146,7 +146,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 +160,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:
*
* 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;
* rotate_offset = (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++) {
+9
View File
@@ -776,3 +776,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) {}
+1 -1
View File
@@ -34,7 +34,7 @@ unsigned long getauxval(unsigned long type) __attribute__((weak));
extern uint32_t OPENSSL_armcap_P;
char CRYPTO_is_NEON_capable(void) {
char CRYPTO_is_NEON_capable_at_runtime(void) {
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
}
+1 -1
View File
@@ -127,7 +127,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;
}
+12 -8
View File
@@ -14,6 +14,8 @@
#include <openssl/crypto.h>
#include <openssl/cpu.h>
#include "internal.h"
@@ -86,22 +88,22 @@ uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
#endif
#if defined(OPENSSL_WINDOWS)
#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER)
#define OPENSSL_CDECL __cdecl
#else
#define OPENSSL_CDECL
#endif
#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
#if !defined(OPENSSL_WINDOWS)
static void do_library_init(void) __attribute__ ((constructor));
#else
#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
#elif defined(OPENSSL_WINDOWS)
#pragma section(".CRT$XCU", read)
static void __cdecl do_library_init(void);
__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
do_library_init;
#else
static void do_library_init(void) __attribute__ ((constructor));
#endif
#endif /* !BORINGSSL_NO_STATIC_INITIALIZER */
/* do_library_init is the actual initialization function. If
* BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
@@ -117,9 +119,9 @@ static void OPENSSL_CDECL do_library_init(void) {
void CRYPTO_library_init(void) {
/* TODO(davidben): It would be tidier if this build knob could be replaced
* with an internal lazy-init mechanism that would handle things correctly
* in-library. */
* in-library. https://crbug.com/542879 */
#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
do_library_init();
CRYPTO_once(&once, do_library_init);
#endif
}
@@ -136,3 +138,5 @@ int CRYPTO_malloc_init(void) {
}
void ENGINE_load_builtin_engines(void) {}
void OPENSSL_load_builtin_modules(void) {}
+47
View File
@@ -0,0 +1,47 @@
include_directories(../../include)
if (${ARCH} STREQUAL "arm")
set(
CURVE25519_ARCH_SOURCES
asm/x25519-asm-arm.S
)
endif()
if (${ARCH} STREQUAL "x86_64")
set(
CURVE25519_ARCH_SOURCES
asm/x25519-asm-x86_64.S
)
endif()
add_library(
curve25519
OBJECT
curve25519.c
x25519-x86_64.c
${CURVE25519_ARCH_SOURCES}
)
add_executable(
ed25519_test
ed25519_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(ed25519_test crypto)
add_dependencies(all_tests ed25519_test)
add_executable(
x25519_test
x25519_test.cc
)
target_link_libraries(x25519_test crypto)
add_dependencies(all_tests x25519_test)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
/* Copyright (c) 2015, 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 <stdint.h>
#include <string.h>
#include <openssl/curve25519.h>
#include "../test/file_test.h"
static bool TestSignature(FileTest *t, void *arg) {
std::vector<uint8_t> private_key, public_key, message, expected_signature;
if (!t->GetBytes(&private_key, "PRIV") ||
private_key.size() != 64 ||
!t->GetBytes(&public_key, "PUB") ||
public_key.size() != 32 ||
!t->GetBytes(&message, "MESSAGE") ||
!t->GetBytes(&expected_signature, "SIG") ||
expected_signature.size() != 64) {
return false;
}
uint8_t signature[64];
if (!ED25519_sign(signature, message.data(), message.size(),
private_key.data())) {
t->PrintLine("ED25519_sign failed");
return false;
}
if (!t->ExpectBytesEqual(expected_signature.data(), expected_signature.size(),
signature, sizeof(signature))) {
return false;
}
if (!ED25519_verify(message.data(), message.size(), signature,
public_key.data())) {
t->PrintLine("ED25519_verify failed");
return false;
}
return true;
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "%s <test input.txt>\n", argv[0]);
return 1;
}
return FileTestMain(TestSignature, nullptr, argv[1]);
}
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (c) 2015, 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_CURVE25519_INTERNAL_H
#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \
!defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM)
#define BORINGSSL_X25519_X86_64
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
#define BORINGSSL_X25519_NEON
/* x25519_NEON is defined in asm/x25519-arm.S. */
void x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_CURVE25519_INTERNAL_H */
+225
View File
@@ -0,0 +1,225 @@
#include <openssl/curve25519.h>
#include <string.h>
#include "internal.h"
#if defined(BORINGSSL_X25519_X86_64)
typedef struct { uint64_t v[5]; } fe25519;
/* These functions are defined in asm/x25519-x86_64.S */
void x25519_x86_64_work_cswap(fe25519 *, uint64_t);
void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
void x25519_x86_64_square(fe25519 *out, const fe25519 *a);
void x25519_x86_64_freeze(fe25519 *);
void x25519_x86_64_ladderstep(fe25519 *work);
static void fe25519_setint(fe25519 *r, unsigned v) {
r->v[0] = v;
r->v[1] = 0;
r->v[2] = 0;
r->v[3] = 0;
r->v[4] = 0;
}
/* Assumes input x being reduced below 2^255 */
static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
fe25519 t;
t = *x;
x25519_x86_64_freeze(&t);
r[0] = (uint8_t)(t.v[0] & 0xff);
r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
r[6] = (uint8_t)((t.v[0] >> 48));
r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
r[12] = (uint8_t)((t.v[1] >> 45));
r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
r[19] = (uint8_t)((t.v[2] >> 50));
r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
r[25] = (uint8_t)((t.v[3] >> 47));
r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
r[31] = (uint8_t)((t.v[4] >> 44));
}
static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
r->v[0] = x[0];
r->v[0] += (uint64_t)x[1] << 8;
r->v[0] += (uint64_t)x[2] << 16;
r->v[0] += (uint64_t)x[3] << 24;
r->v[0] += (uint64_t)x[4] << 32;
r->v[0] += (uint64_t)x[5] << 40;
r->v[0] += ((uint64_t)x[6] & 7) << 48;
r->v[1] = x[6] >> 3;
r->v[1] += (uint64_t)x[7] << 5;
r->v[1] += (uint64_t)x[8] << 13;
r->v[1] += (uint64_t)x[9] << 21;
r->v[1] += (uint64_t)x[10] << 29;
r->v[1] += (uint64_t)x[11] << 37;
r->v[1] += ((uint64_t)x[12] & 63) << 45;
r->v[2] = x[12] >> 6;
r->v[2] += (uint64_t)x[13] << 2;
r->v[2] += (uint64_t)x[14] << 10;
r->v[2] += (uint64_t)x[15] << 18;
r->v[2] += (uint64_t)x[16] << 26;
r->v[2] += (uint64_t)x[17] << 34;
r->v[2] += (uint64_t)x[18] << 42;
r->v[2] += ((uint64_t)x[19] & 1) << 50;
r->v[3] = x[19] >> 1;
r->v[3] += (uint64_t)x[20] << 7;
r->v[3] += (uint64_t)x[21] << 15;
r->v[3] += (uint64_t)x[22] << 23;
r->v[3] += (uint64_t)x[23] << 31;
r->v[3] += (uint64_t)x[24] << 39;
r->v[3] += ((uint64_t)x[25] & 15) << 47;
r->v[4] = x[25] >> 4;
r->v[4] += (uint64_t)x[26] << 4;
r->v[4] += (uint64_t)x[27] << 12;
r->v[4] += (uint64_t)x[28] << 20;
r->v[4] += (uint64_t)x[29] << 28;
r->v[4] += (uint64_t)x[30] << 36;
r->v[4] += ((uint64_t)x[31] & 127) << 44;
}
static void fe25519_invert(fe25519 *r, const fe25519 *x) {
fe25519 z2;
fe25519 z9;
fe25519 z11;
fe25519 z2_5_0;
fe25519 z2_10_0;
fe25519 z2_20_0;
fe25519 z2_50_0;
fe25519 z2_100_0;
fe25519 t;
int i;
/* 2 */ x25519_x86_64_square(&z2, x);
/* 4 */ x25519_x86_64_square(&t, &z2);
/* 8 */ x25519_x86_64_square(&t, &t);
/* 9 */ x25519_x86_64_mul(&z9, &t, x);
/* 11 */ x25519_x86_64_mul(&z11, &z9, &z2);
/* 22 */ x25519_x86_64_square(&t, &z11);
/* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9);
/* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0);
/* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); }
/* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
/* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0);
/* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
/* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
/* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0);
/* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); }
/* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0);
/* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
/* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
/* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0);
/* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
/* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
/* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0);
/* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
x25519_x86_64_square(&t, &t);
}
/* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0);
/* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
/* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0);
/* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t);
/* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t);
/* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t);
/* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t);
/* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11);
}
static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
fe25519 work[5];
work[0] = *xr;
fe25519_setint(work + 1, 1);
fe25519_setint(work + 2, 0);
work[3] = *xr;
fe25519_setint(work + 4, 1);
int i, j;
uint8_t prevbit = 0;
j = 6;
for (i = 31; i >= 0; i--) {
while (j >= 0) {
const uint8_t bit = 1 & (s[i] >> j);
const uint64_t swap = bit ^ prevbit;
prevbit = bit;
x25519_x86_64_work_cswap(work + 1, swap);
x25519_x86_64_ladderstep(work);
j -= 1;
}
j = 7;
}
*xr = work[1];
*zr = work[2];
}
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]) {
uint8_t e[32];
memcpy(e, scalar, sizeof(e));
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fe25519 t;
fe25519 z;
fe25519_unpack(&t, point);
mladder(&t, &z, e);
fe25519_invert(&z, &z);
x25519_x86_64_mul(&t, &t, &z);
fe25519_pack(out, &t);
}
#endif /* BORINGSSL_X25519_X86_64 */
+126
View File
@@ -0,0 +1,126 @@
/* Copyright (c) 2015, 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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/curve25519.h>
static bool TestX25519() {
/* 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,
0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4,
};
static const uint8_t kPoint1[32] = {
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
};
uint8_t out[32];
X25519(out, kScalar1, kPoint1);
static const uint8_t kExpected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
};
if (memcmp(kExpected1, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test one failed.\n");
return false;
}
static const uint8_t kScalar2[32] = {
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea,
0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d,
};
static const uint8_t kPoint2[32] = {
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95,
0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0,
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};
X25519(out, kScalar2, kPoint2);
static const uint8_t kExpected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
if (memcmp(kExpected2, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test two failed.\n");
return false;
}
return true;
}
static bool TestX25519SmallOrder() {
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
};
uint8_t out[32], private_key[32];
memset(private_key, 0x11, sizeof(private_key));
if (X25519(out, private_key, kSmallOrderPoint)) {
fprintf(stderr, "X25519 returned success with a small-order input.\n");
return false;
}
return true;
}
static bool TestX25519Iterated() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
unsigned i;
for (i = 0; i < 1000; i++) {
X25519(out, scalar, point);
memcpy(point, scalar, sizeof(point));
memcpy(scalar, out, sizeof(scalar));
}
static const uint8_t kExpected[32] = {
0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef,
0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60,
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
};
if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
fprintf(stderr, "Iterated X25519 test failed\n");
return false;
}
return true;
}
int main(int argc, char **argv) {
if (!TestX25519() ||
!TestX25519Iterated() ||
!TestX25519SmallOrder()) {
return 1;
}
printf("PASS\n");
return 0;
}
-17
View File
@@ -202,24 +202,7 @@ how to use xors :-) I got it to its final state.
#define ITERATIONS 16
#define HALF_ITERATIONS 8
#if defined(_MSC_VER)
#define ROTATE(a, n) (_lrotr(a, n))
#elif defined(__ICC)
#define ROTATE(a, n) (_rotr(a, n))
#elif defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && \
!defined(__STRICT_ANSI__) && \
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#define ROTATE(a, n) \
({ \
unsigned int ret; \
asm("rorl %1,%0" : "=r"(ret) : "I"(n), "0"(a) : "cc"); \
ret; \
})
#endif
#ifndef ROTATE
#define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n))))
#endif
#if defined(__cplusplus)
+33 -11
View File
@@ -62,30 +62,52 @@
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
int ok = 0;
BIGNUM q;
*ret = 0;
BN_init(&q);
if (!BN_set_word(&q, 1)) {
BN_CTX *ctx = BN_CTX_new();
if (ctx == NULL) {
return 0;
}
BN_CTX_start(ctx);
int ok = 0;
/* 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;
}
+5 -9
View File
@@ -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;
@@ -85,11 +85,7 @@ DH *DH_new(void) {
CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
dh->references = 1;
if (!CRYPTO_new_ex_data(&g_ex_data_class, dh, &dh->ex_data)) {
CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
OPENSSL_free(dh);
return NULL;
}
CRYPTO_new_ex_data(&dh->ex_data);
return dh;
}
@@ -448,11 +444,11 @@ DH *DHparams_dup(const DH *dh) {
return ret;
}
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
int DH_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, new_func,
dup_func, free_func)) {
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func,
free_func)) {
return -1;
}
return index;
+57 -1
View File
@@ -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;
}
+119 -132
View File
@@ -55,182 +55,169 @@
#include <openssl/bn.h>
#include "internal.h"
#include "../bn/internal.h"
#if BN_BITS2 == 32
#define TOBN(lo, hi) lo, hi
#elif BN_BITS2 == 64
#define TOBN(lo, hi) ((BN_ULONG)hi << 32 | lo)
#else
#error "unsupported BN_BITS2"
#endif
static const BN_ULONG dh1024_160_p[] = {
TOBN(0x2E4A4371, 0xDF1FB2BC), TOBN(0x6D4DA708, 0xE68CFDA7),
TOBN(0x365C1A65, 0x45BF37DF), TOBN(0x0DC8B4BD, 0xA151AF5F),
TOBN(0xF55BCCC0, 0xFAA31A4F), TOBN(0xE5644738, 0x4EFFD6FA),
TOBN(0x219A7372, 0x98488E9C), TOBN(0x90C4BD70, 0xACCBDD7D),
TOBN(0xD49B83BF, 0x24975C3C), TOBN(0xA9061123, 0x13ECB4AE),
TOBN(0x2EE652C0, 0x9838EF1E), TOBN(0x75A23D18, 0x6073E286),
TOBN(0x52D23B61, 0x9A6A9DCA), TOBN(0xFB06A3C6, 0x52C99FBC),
TOBN(0xAE5D54EC, 0xDE92DE5E), TOBN(0xA080E01D, 0xB10B8F96),
TOBN(0xDF1FB2BC, 0x2E4A4371), TOBN(0xE68CFDA7, 0x6D4DA708),
TOBN(0x45BF37DF, 0x365C1A65), TOBN(0xA151AF5F, 0x0DC8B4BD),
TOBN(0xFAA31A4F, 0xF55BCCC0), TOBN(0x4EFFD6FA, 0xE5644738),
TOBN(0x98488E9C, 0x219A7372), TOBN(0xACCBDD7D, 0x90C4BD70),
TOBN(0x24975C3C, 0xD49B83BF), TOBN(0x13ECB4AE, 0xA9061123),
TOBN(0x9838EF1E, 0x2EE652C0), TOBN(0x6073E286, 0x75A23D18),
TOBN(0x9A6A9DCA, 0x52D23B61), TOBN(0x52C99FBC, 0xFB06A3C6),
TOBN(0xDE92DE5E, 0xAE5D54EC), TOBN(0xB10B8F96, 0xA080E01D),
};
static const BN_ULONG dh1024_160_g[] = {
TOBN(0x22B3B2E5, 0x855E6EEB), TOBN(0xF97C2A24, 0x858F4DCE),
TOBN(0x18D08BC8, 0x2D779D59), TOBN(0x8E73AFA3, 0xD662A4D1),
TOBN(0x69B6A28A, 0x1DBF0A01), TOBN(0x7A091F53, 0xA6A24C08),
TOBN(0x63F80A76, 0x909D0D22), TOBN(0xB9A92EE1, 0xD7FBD7D3),
TOBN(0x9E2749F4, 0x5E91547F), TOBN(0xB01B886A, 0x160217B4),
TOBN(0x5504F213, 0x777E690F), TOBN(0x5C41564B, 0x266FEA1E),
TOBN(0x14266D31, 0xD6406CFF), TOBN(0x58AC507F, 0xF8104DD2),
TOBN(0xEFB99905, 0x6765A442), TOBN(0xC3FD3412, 0xA4D1CBD5),
TOBN(0x855E6EEB, 0x22B3B2E5), TOBN(0x858F4DCE, 0xF97C2A24),
TOBN(0x2D779D59, 0x18D08BC8), TOBN(0xD662A4D1, 0x8E73AFA3),
TOBN(0x1DBF0A01, 0x69B6A28A), TOBN(0xA6A24C08, 0x7A091F53),
TOBN(0x909D0D22, 0x63F80A76), TOBN(0xD7FBD7D3, 0xB9A92EE1),
TOBN(0x5E91547F, 0x9E2749F4), TOBN(0x160217B4, 0xB01B886A),
TOBN(0x777E690F, 0x5504F213), TOBN(0x266FEA1E, 0x5C41564B),
TOBN(0xD6406CFF, 0x14266D31), TOBN(0xF8104DD2, 0x58AC507F),
TOBN(0x6765A442, 0xEFB99905), TOBN(0xA4D1CBD5, 0xC3FD3412),
};
static const BN_ULONG dh1024_160_q[] = {
TOBN(0x49462353, 0x64B7CB9D), TOBN(0x8ABA4E7D, 0x81A8DF27), 0xF518AA87,
TOBN(0x64B7CB9D, 0x49462353), TOBN(0x81A8DF27, 0x8ABA4E7D), 0xF518AA87,
};
static const BN_ULONG dh2048_224_p[] = {
TOBN(0x0C10E64F, 0x0AC4DFFE), TOBN(0x4E71B81C, 0xCF9DE538),
TOBN(0xFFA31F71, 0x7EF363E2), TOBN(0x6B8E75B9, 0xE3FB73C1),
TOBN(0x4BA80A29, 0xC9B53DCF), TOBN(0x16E79763, 0x23F10B0E),
TOBN(0x13042E9B, 0xC52172E4), TOBN(0xC928B2B9, 0xBE60E69C),
TOBN(0xB9E587E8, 0x80CD86A1), TOBN(0x98C641A4, 0x315D75E1),
TOBN(0x44328387, 0xCDF93ACC), TOBN(0xDC0A486D, 0x15987D9A),
TOBN(0x1FD5A074, 0x7310F712), TOBN(0xDE31EFDC, 0x278273C7),
TOBN(0x415D9330, 0x1602E714), TOBN(0xBC8985DB, 0x81286130),
TOBN(0x70918836, 0xB3BF8A31), TOBN(0xB9C49708, 0x6A00E0A0),
TOBN(0x8BBC27BE, 0xC6BA0B2C), TOBN(0xED34DBF6, 0xC9F98D11),
TOBN(0xB6C12207, 0x7AD5B7D0), TOBN(0x55B7394B, 0xD91E8FEF),
TOBN(0xEFDA4DF8, 0x9037C9ED), TOBN(0xAD6AC212, 0x6D3F8152),
TOBN(0x1274A0A6, 0x1DE6B85A), TOBN(0x309C180E, 0xEB3D688A),
TOBN(0x7BA1DF15, 0xAF9A3C40), TOBN(0xF95A56DB, 0xE6FA141D),
TOBN(0xB61D0A75, 0xB54B1597), TOBN(0x683B9FD1, 0xA20D64E5),
TOBN(0x9559C51F, 0xD660FAA7), TOBN(0x9123A9D0, 0xAD107E1E),
TOBN(0x0AC4DFFE, 0x0C10E64F), TOBN(0xCF9DE538, 0x4E71B81C),
TOBN(0x7EF363E2, 0xFFA31F71), TOBN(0xE3FB73C1, 0x6B8E75B9),
TOBN(0xC9B53DCF, 0x4BA80A29), TOBN(0x23F10B0E, 0x16E79763),
TOBN(0xC52172E4, 0x13042E9B), TOBN(0xBE60E69C, 0xC928B2B9),
TOBN(0x80CD86A1, 0xB9E587E8), TOBN(0x315D75E1, 0x98C641A4),
TOBN(0xCDF93ACC, 0x44328387), TOBN(0x15987D9A, 0xDC0A486D),
TOBN(0x7310F712, 0x1FD5A074), TOBN(0x278273C7, 0xDE31EFDC),
TOBN(0x1602E714, 0x415D9330), TOBN(0x81286130, 0xBC8985DB),
TOBN(0xB3BF8A31, 0x70918836), TOBN(0x6A00E0A0, 0xB9C49708),
TOBN(0xC6BA0B2C, 0x8BBC27BE), TOBN(0xC9F98D11, 0xED34DBF6),
TOBN(0x7AD5B7D0, 0xB6C12207), TOBN(0xD91E8FEF, 0x55B7394B),
TOBN(0x9037C9ED, 0xEFDA4DF8), TOBN(0x6D3F8152, 0xAD6AC212),
TOBN(0x1DE6B85A, 0x1274A0A6), TOBN(0xEB3D688A, 0x309C180E),
TOBN(0xAF9A3C40, 0x7BA1DF15), TOBN(0xE6FA141D, 0xF95A56DB),
TOBN(0xB54B1597, 0xB61D0A75), TOBN(0xA20D64E5, 0x683B9FD1),
TOBN(0xD660FAA7, 0x9559C51F), TOBN(0xAD107E1E, 0x9123A9D0),
};
static const BN_ULONG dh2048_224_g[] = {
TOBN(0x191F2BFA, 0x84B890D3), TOBN(0x2A7065B3, 0x81BC087F),
TOBN(0xF6EC0179, 0x19C418E1), TOBN(0x71CFFF4C, 0x7B5A0F1C),
TOBN(0x9B6AA4BD, 0xEDFE72FE), TOBN(0x94B30269, 0x81E1BCFE),
TOBN(0x8D6C0191, 0x566AFBB4), TOBN(0x409D13CD, 0xB539CCE3),
TOBN(0x5F2FF381, 0x6AA21E7F), TOBN(0x770589EF, 0xD9E263E4),
TOBN(0xD19963DD, 0x10E183ED), TOBN(0x150B8EEB, 0xB70A8137),
TOBN(0x28C8F8AC, 0x051AE3D4), TOBN(0x0C1AB15B, 0xBB77A86F),
TOBN(0x16A330EF, 0x6E3025E3), TOBN(0xD6F83456, 0x19529A45),
TOBN(0x118E98D1, 0xF180EB34), TOBN(0x50717CBE, 0xB5F6C6B2),
TOBN(0xDA7460CD, 0x09939D54), TOBN(0x22EA1ED4, 0xE2471504),
TOBN(0x521BC98A, 0xB8A762D0), TOBN(0x5AC1348B, 0xF4D02727),
TOBN(0x1999024A, 0xC1766910), TOBN(0xA8D66AD7, 0xBE5E9001),
TOBN(0x620A8652, 0xC57DB17C), TOBN(0x00C29F52, 0xAB739D77),
TOBN(0xA70C4AFA, 0xDD921F01), TOBN(0x10B9A6F0, 0xA6824A4E),
TOBN(0xCFE4FFE3, 0x74866A08), TOBN(0x89998CAF, 0x6CDEBE7B),
TOBN(0x8FFDAC50, 0x9DF30B5C), TOBN(0x4F2D9AE3, 0xAC4032EF),
TOBN(0x84B890D3, 0x191F2BFA), TOBN(0x81BC087F, 0x2A7065B3),
TOBN(0x19C418E1, 0xF6EC0179), TOBN(0x7B5A0F1C, 0x71CFFF4C),
TOBN(0xEDFE72FE, 0x9B6AA4BD), TOBN(0x81E1BCFE, 0x94B30269),
TOBN(0x566AFBB4, 0x8D6C0191), TOBN(0xB539CCE3, 0x409D13CD),
TOBN(0x6AA21E7F, 0x5F2FF381), TOBN(0xD9E263E4, 0x770589EF),
TOBN(0x10E183ED, 0xD19963DD), TOBN(0xB70A8137, 0x150B8EEB),
TOBN(0x051AE3D4, 0x28C8F8AC), TOBN(0xBB77A86F, 0x0C1AB15B),
TOBN(0x6E3025E3, 0x16A330EF), TOBN(0x19529A45, 0xD6F83456),
TOBN(0xF180EB34, 0x118E98D1), TOBN(0xB5F6C6B2, 0x50717CBE),
TOBN(0x09939D54, 0xDA7460CD), TOBN(0xE2471504, 0x22EA1ED4),
TOBN(0xB8A762D0, 0x521BC98A), TOBN(0xF4D02727, 0x5AC1348B),
TOBN(0xC1766910, 0x1999024A), TOBN(0xBE5E9001, 0xA8D66AD7),
TOBN(0xC57DB17C, 0x620A8652), TOBN(0xAB739D77, 0x00C29F52),
TOBN(0xDD921F01, 0xA70C4AFA), TOBN(0xA6824A4E, 0x10B9A6F0),
TOBN(0x74866A08, 0xCFE4FFE3), TOBN(0x6CDEBE7B, 0x89998CAF),
TOBN(0x9DF30B5C, 0x8FFDAC50), TOBN(0xAC4032EF, 0x4F2D9AE3),
};
static const BN_ULONG dh2048_224_q[] = {
TOBN(0xB36371EB, 0xBF389A99), TOBN(0x4738CEBC, 0x1F80535A),
TOBN(0x99717710, 0xC58D93FE), 0x801C0D34,
TOBN(0xBF389A99, 0xB36371EB), TOBN(0x1F80535A, 0x4738CEBC),
TOBN(0xC58D93FE, 0x99717710), 0x801C0D34,
};
static const BN_ULONG dh2048_256_p[] = {
TOBN(0x1E1A1597, 0xDB094AE9), TOBN(0xD7EF09CA, 0x693877FA),
TOBN(0x6E11715F, 0x6116D227), TOBN(0xC198AF12, 0xA4B54330),
TOBN(0xD7014103, 0x75F26375), TOBN(0x54E710C3, 0xC3A3960A),
TOBN(0xBD0BE621, 0xDED4010A), TOBN(0x89962856, 0xC0B857F6),
TOBN(0x71506026, 0xB3CA3F79), TOBN(0xE6B486F6, 0x1CCACB83),
TOBN(0x14056425, 0x67E144E5), TOBN(0xA41825D9, 0xF6A167B5),
TOBN(0x96524D8E, 0x3AD83477), TOBN(0x51BFA4AB, 0xF13C6D9A),
TOBN(0x35488A0E, 0x2D525267), TOBN(0xCAA6B790, 0xB63ACAE1),
TOBN(0x81B23F76, 0x4FDB70C5), TOBN(0x12307F5C, 0xBC39A0BF),
TOBN(0xB1E59BB8, 0xB941F54E), TOBN(0xD45F9088, 0x6C5BFC11),
TOBN(0x4275BF7B, 0x22E0B1EF), TOBN(0x5B4758C0, 0x91F9E672),
TOBN(0x6BCF67ED, 0x5A8A9D30), TOBN(0x97517ABD, 0x209E0C64),
TOBN(0x830E9A7C, 0x3BF4296D), TOBN(0x34096FAA, 0x16C3D911),
TOBN(0x61B2AA30, 0xFAF7DF45), TOBN(0xD61957D4, 0xE00DF8F1),
TOBN(0x435E3B00, 0x5D2CEED4), TOBN(0x660DD0F2, 0x8CEEF608),
TOBN(0x65195999, 0xFFBBD19C), TOBN(0xB4B6663C, 0x87A8E61D),
TOBN(0xDB094AE9, 0x1E1A1597), TOBN(0x693877FA, 0xD7EF09CA),
TOBN(0x6116D227, 0x6E11715F), TOBN(0xA4B54330, 0xC198AF12),
TOBN(0x75F26375, 0xD7014103), TOBN(0xC3A3960A, 0x54E710C3),
TOBN(0xDED4010A, 0xBD0BE621), TOBN(0xC0B857F6, 0x89962856),
TOBN(0xB3CA3F79, 0x71506026), TOBN(0x1CCACB83, 0xE6B486F6),
TOBN(0x67E144E5, 0x14056425), TOBN(0xF6A167B5, 0xA41825D9),
TOBN(0x3AD83477, 0x96524D8E), TOBN(0xF13C6D9A, 0x51BFA4AB),
TOBN(0x2D525267, 0x35488A0E), TOBN(0xB63ACAE1, 0xCAA6B790),
TOBN(0x4FDB70C5, 0x81B23F76), TOBN(0xBC39A0BF, 0x12307F5C),
TOBN(0xB941F54E, 0xB1E59BB8), TOBN(0x6C5BFC11, 0xD45F9088),
TOBN(0x22E0B1EF, 0x4275BF7B), TOBN(0x91F9E672, 0x5B4758C0),
TOBN(0x5A8A9D30, 0x6BCF67ED), TOBN(0x209E0C64, 0x97517ABD),
TOBN(0x3BF4296D, 0x830E9A7C), TOBN(0x16C3D911, 0x34096FAA),
TOBN(0xFAF7DF45, 0x61B2AA30), TOBN(0xE00DF8F1, 0xD61957D4),
TOBN(0x5D2CEED4, 0x435E3B00), TOBN(0x8CEEF608, 0x660DD0F2),
TOBN(0xFFBBD19C, 0x65195999), TOBN(0x87A8E61D, 0xB4B6663C),
};
static const BN_ULONG dh2048_256_g[] = {
TOBN(0x6CC41659, 0x664B4C0F), TOBN(0xEF98C582, 0x5E2327CF),
TOBN(0xD4795451, 0xD647D148), TOBN(0x90F00EF8, 0x2F630784),
TOBN(0x1DB246C3, 0x184B523D), TOBN(0xCDC67EB6, 0xC7891428),
TOBN(0x0DF92B52, 0x7FD02837), TOBN(0x64E0EC37, 0xB3353BBB),
TOBN(0x57CD0915, 0xECD06E15), TOBN(0xDF016199, 0xB7D2BBD2),
TOBN(0x052588B9, 0xC8484B1E), TOBN(0x13D3FE14, 0xDB2A3B73),
TOBN(0xD182EA0A, 0xD052B985), TOBN(0xE83B9C80, 0xA4BD1BFF),
TOBN(0xFB3F2E55, 0xDFC967C1), TOBN(0x767164E1, 0xB5045AF2),
TOBN(0x6F2F9193, 0x1D14348F), TOBN(0x428EBC83, 0x64E67982),
TOBN(0x82D6ED38, 0x8AC376D2), TOBN(0xAAB8A862, 0x777DE62A),
TOBN(0xE9EC144B, 0xDDF463E5), TOBN(0xC77A57F2, 0x0196F931),
TOBN(0x41000A65, 0xA55AE313), TOBN(0xC28CBB18, 0x901228F8),
TOBN(0x7E8C6F62, 0xBC3773BF), TOBN(0x0C6B47B1, 0xBE3A6C1B),
TOBN(0xAC0BB555, 0xFF4FED4A), TOBN(0x77BE463F, 0x10DBC150),
TOBN(0x1A0BA125, 0x07F4793A), TOBN(0x21EF2054, 0x4CA7B18F),
TOBN(0x60EDBD48, 0x2E775066), TOBN(0x73134D0B, 0x3FB32C9B),
TOBN(0x664B4C0F, 0x6CC41659), TOBN(0x5E2327CF, 0xEF98C582),
TOBN(0xD647D148, 0xD4795451), TOBN(0x2F630784, 0x90F00EF8),
TOBN(0x184B523D, 0x1DB246C3), TOBN(0xC7891428, 0xCDC67EB6),
TOBN(0x7FD02837, 0x0DF92B52), TOBN(0xB3353BBB, 0x64E0EC37),
TOBN(0xECD06E15, 0x57CD0915), TOBN(0xB7D2BBD2, 0xDF016199),
TOBN(0xC8484B1E, 0x052588B9), TOBN(0xDB2A3B73, 0x13D3FE14),
TOBN(0xD052B985, 0xD182EA0A), TOBN(0xA4BD1BFF, 0xE83B9C80),
TOBN(0xDFC967C1, 0xFB3F2E55), TOBN(0xB5045AF2, 0x767164E1),
TOBN(0x1D14348F, 0x6F2F9193), TOBN(0x64E67982, 0x428EBC83),
TOBN(0x8AC376D2, 0x82D6ED38), TOBN(0x777DE62A, 0xAAB8A862),
TOBN(0xDDF463E5, 0xE9EC144B), TOBN(0x0196F931, 0xC77A57F2),
TOBN(0xA55AE313, 0x41000A65), TOBN(0x901228F8, 0xC28CBB18),
TOBN(0xBC3773BF, 0x7E8C6F62), TOBN(0xBE3A6C1B, 0x0C6B47B1),
TOBN(0xFF4FED4A, 0xAC0BB555), TOBN(0x10DBC150, 0x77BE463F),
TOBN(0x07F4793A, 0x1A0BA125), TOBN(0x4CA7B18F, 0x21EF2054),
TOBN(0x2E775066, 0x60EDBD48), TOBN(0x3FB32C9B, 0x73134D0B),
};
static const BN_ULONG dh2048_256_q[] = {
TOBN(0x64F5FBD3, 0xA308B0FE), TOBN(0x1EB3750B, 0x99B1A47D),
TOBN(0x40129DA2, 0xB4479976), TOBN(0xA709A097, 0x8CF83642),
TOBN(0xA308B0FE, 0x64F5FBD3), TOBN(0x99B1A47D, 0x1EB3750B),
TOBN(0xB4479976, 0x40129DA2), TOBN(0x8CF83642, 0xA709A097),
};
/* dh1024_safe_prime_1 is hard-coded in Apache httpd 2.2,
* modules/ssl/ssl_engine_dh.c. */
static const BN_ULONG dh1024_safe_prime_1[] = {
TOBN(0x24218EB3, 0xE7393E0F), TOBN(0xE2BD68B0, 0x7DE0F4D6),
TOBN(0x88AEAA74, 0x07DD62DB), TOBN(0x9DDD3305, 0x10EA9FCC),
TOBN(0x74087D15, 0xA7DBCA78), TOBN(0x78045B07, 0xDAE88600),
TOBN(0x1AAD3B72, 0x33168A46), TOBN(0x7BEDDCFD, 0xFF590137),
TOBN(0x7A635E81, 0xFE324A46), TOBN(0x420B2A29, 0x5AC179BA),
TOBN(0x177E16D5, 0x13B4B4D7), TOBN(0x639C72FB, 0x849F912E),
TOBN(0x98BCE951, 0xB88174CB), TOBN(0xA45F520B, 0x0C84D239),
TOBN(0x4AFD0AD5, 0x36D693D3), TOBN(0xCBBBDC19, 0xD67DE440),
TOBN(0xE7393E0F, 0x24218EB3), TOBN(0x7DE0F4D6, 0xE2BD68B0),
TOBN(0x07DD62DB, 0x88AEAA74), TOBN(0x10EA9FCC, 0x9DDD3305),
TOBN(0xA7DBCA78, 0x74087D15), TOBN(0xDAE88600, 0x78045B07),
TOBN(0x33168A46, 0x1AAD3B72), TOBN(0xFF590137, 0x7BEDDCFD),
TOBN(0xFE324A46, 0x7A635E81), TOBN(0x5AC179BA, 0x420B2A29),
TOBN(0x13B4B4D7, 0x177E16D5), TOBN(0x849F912E, 0x639C72FB),
TOBN(0xB88174CB, 0x98BCE951), TOBN(0x0C84D239, 0xA45F520B),
TOBN(0x36D693D3, 0x4AFD0AD5), TOBN(0xD67DE440, 0xCBBBDC19),
};
/* dh1024_safe_prime_2 is hard-coded in nginx,
* src/event/ngx_event_openssl.c. */
static const BN_ULONG dh1024_safe_prime_2[] = {
TOBN(0xCFE16B9B, 0x071DF045), TOBN(0x146757DA, 0x88D0F65D),
TOBN(0x58FAFD49, 0x4A63AB1E), TOBN(0xEF9EA027, 0x35D8CECE),
TOBN(0x70CC9A50, 0x25ECE662), TOBN(0x81DC2CA7, 0xF29BA5DF),
TOBN(0xF7D36CC8, 0x8F68B076), TOBN(0xA757E304, 0x60E91A92),
TOBN(0x9BE67780, 0x87A2BC04), TOBN(0xA5FDF1D2, 0xBEECA565),
TOBN(0x922614C5, 0x5CCBBAA8), TOBN(0xE710800C, 0x6C030276),
TOBN(0x0FB3504C, 0x08EED4EB), TOBN(0x68B42D4B, 0xD958A3F5),
TOBN(0x80E9CFDB, 0x7C43FCF5), TOBN(0xD8467490, 0xBBBC2DCA),
TOBN(0x071DF045, 0xCFE16B9B), TOBN(0x88D0F65D, 0x146757DA),
TOBN(0x4A63AB1E, 0x58FAFD49), TOBN(0x35D8CECE, 0xEF9EA027),
TOBN(0x25ECE662, 0x70CC9A50), TOBN(0xF29BA5DF, 0x81DC2CA7),
TOBN(0x8F68B076, 0xF7D36CC8), TOBN(0x60E91A92, 0xA757E304),
TOBN(0x87A2BC04, 0x9BE67780), TOBN(0xBEECA565, 0xA5FDF1D2),
TOBN(0x5CCBBAA8, 0x922614C5), TOBN(0x6C030276, 0xE710800C),
TOBN(0x08EED4EB, 0x0FB3504C), TOBN(0xD958A3F5, 0x68B42D4B),
TOBN(0x7C43FCF5, 0x80E9CFDB), TOBN(0xBBBC2DCA, 0xD8467490),
};
/* dh1024_safe_prime_3 is offered as a parameter by several high-traffic sites,
* including mozilla.org, as of Jan 2015. */
static const BN_ULONG dh1024_safe_prime_3[] = {
TOBN(0x349E721B, 0x671746AE), TOBN(0xD75E93B2, 0x258A0655),
TOBN(0x25592EB6, 0xD425E6FB), TOBN(0xBF7CDD9A, 0x0C46AB04),
TOBN(0x28968680, 0x0AD0BC99), TOBN(0xD0B7EB49, 0xF53907FB),
TOBN(0xEBC85C1D, 0x202EABB3), TOBN(0x364D8C71, 0x3129C693),
TOBN(0x2D46F195, 0x53728351), TOBN(0x8C76CC85, 0xDF326DD6),
TOBN(0x9188E24E, 0xF898B3F9), TOBN(0x2855DFD2, 0x95EFB13C),
TOBN(0x7B2241FE, 0x1F5DAC48), TOBN(0x99A13D9F, 0x117B6BF7),
TOBN(0x3A3468C7, 0x0F97CDDA), TOBN(0x74A8297B, 0xC9BBF5F7)};
TOBN(0x671746AE, 0x349E721B), TOBN(0x258A0655, 0xD75E93B2),
TOBN(0xD425E6FB, 0x25592EB6), TOBN(0x0C46AB04, 0xBF7CDD9A),
TOBN(0x0AD0BC99, 0x28968680), TOBN(0xF53907FB, 0xD0B7EB49),
TOBN(0x202EABB3, 0xEBC85C1D), TOBN(0x3129C693, 0x364D8C71),
TOBN(0x53728351, 0x2D46F195), TOBN(0xDF326DD6, 0x8C76CC85),
TOBN(0xF898B3F9, 0x9188E24E), TOBN(0x95EFB13C, 0x2855DFD2),
TOBN(0x1F5DAC48, 0x7B2241FE), TOBN(0x117B6BF7, 0x99A13D9F),
TOBN(0x0F97CDDA, 0x3A3468C7), TOBN(0xC9BBF5F7, 0x74A8297B)};
/* dh1024_safe_prime_4 is hard-coded in Apache httpd 2.0,
* modules/ssl/ssl_engine_dh.c. */
static const BN_ULONG dh1024_safe_prime_4[] = {
TOBN(0x0DD5C86B, 0x5085E21F), TOBN(0xD823C650, 0x871538DF),
TOBN(0x262E56A8, 0x125136F7), TOBN(0x839EB5DB, 0x974E9EF1),
TOBN(0x1B13A63C, 0xEA9BAD99), TOBN(0x3D76E05E, 0x6044CF02),
TOBN(0x1BAC9B5C, 0x611EBBBE), TOBN(0x4E5327DF, 0x3E371D79),
TOBN(0x061CBC05, 0x000E6EDD), TOBN(0x20129B48, 0x2F971F3C),
TOBN(0x3048D5A2, 0xA6EF09C4), TOBN(0xCBD523A6, 0xFA15A259),
TOBN(0x4A79A770, 0x2A206490), TOBN(0x51BB055E, 0x91B78182),
TOBN(0xBDD4798E, 0x7CF180C3), TOBN(0x495BE32C, 0xE6969D3D)};
TOBN(0x5085E21F, 0x0DD5C86B), TOBN(0x871538DF, 0xD823C650),
TOBN(0x125136F7, 0x262E56A8), TOBN(0x974E9EF1, 0x839EB5DB),
TOBN(0xEA9BAD99, 0x1B13A63C), TOBN(0x6044CF02, 0x3D76E05E),
TOBN(0x611EBBBE, 0x1BAC9B5C), TOBN(0x3E371D79, 0x4E5327DF),
TOBN(0x000E6EDD, 0x061CBC05), TOBN(0x2F971F3C, 0x20129B48),
TOBN(0xA6EF09C4, 0x3048D5A2), TOBN(0xFA15A259, 0xCBD523A6),
TOBN(0x2A206490, 0x4A79A770), TOBN(0x91B78182, 0x51BB055E),
TOBN(0x7CF180C3, 0xBDD4798E), TOBN(0xE6969D3D, 0x495BE32C)};
static const BN_ULONG bn_two_data[] = {2};
#define STATIC_BIGNUM(x) \
{ \
(BN_ULONG *) x, sizeof(x) / sizeof(BN_ULONG), \
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
}
struct standard_parameters {
BIGNUM p, q, g;
};
@@ -260,7 +247,7 @@ static const BIGNUM dh1024_safe_prime[] = {
STATIC_BIGNUM(dh1024_safe_prime_4)
};
BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
static BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
static DH *get_standard_parameters(const struct standard_parameters *params,
const ENGINE *engine) {

Some files were not shown because too many files have changed in this diff Show More