Why does 'SSL_export_keying_material' return a different value than whats printed to the NSS keylog file?

2022-05-16 Thread Ian Spence via openssl-users
I am trying to wrap my head around the keying material I can access
within my TLS client application using OpenSSL 3.0.3

I have `SSL_CTX_set_keylog_callback` set to just printf() the lines.

I also have the following code to extract the client random:


unsigned char * keymat = malloc(48);
const char * label = "CLIENT_RANDOM";
SSL_export_keying_material(ssl, keymat, 48, label, strnlen(label), NULL, 0, 0);
printf("[EXPORT] %s: ", label.UTF8String);
for (int i = 0; i < 48; i++) {
printf("%02x", keymat[i]);
}
printf("\n");


Looking in ssl_local.h I found definitions for the various labels.
I've omitted the code from this email for brevity sake, but I print
out the value for each of the labels.

What I don't understand is why I'm getting different values from the
two. When connecting to a TLS1.3 server I see the following:


[NSS_KEYLOG] SERVER_HANDSHAKE_TRAFFIC_SECRET
f60a59b1ca9629281d4ee45b9966f19277de0652fb12513d71d388d9a8545077
882c1c081f9fe2708cee4067956717caf1936e60511d8d01b2e63541378e44671903e15c5a4b5b7fb3208452d71681e3
[NSS_KEYLOG] EXPORTER_SECRET
f60a59b1ca9629281d4ee45b9966f19277de0652fb12513d71d388d9a8545077
6333438b11e60e3ebd3a4795d7bd8400c08b878854e181ae2d084f95a264192e92ab108a2bd0cb284f7f82dd78a6b4eb
[NSS_KEYLOG] SERVER_TRAFFIC_SECRET_0
f60a59b1ca9629281d4ee45b9966f19277de0652fb12513d71d388d9a8545077
eabc8a14fc818707f03c2e0d7456011aa6aed025cfc43c25591aa7444ee6a045f643bc05b0daf9de9a1e863e7254681e
[NSS_KEYLOG] CLIENT_HANDSHAKE_TRAFFIC_SECRET
f60a59b1ca9629281d4ee45b9966f19277de0652fb12513d71d388d9a8545077
ef410252e24f3bc03d62218aa42d5f002d5a5bbf12d5f0f3e356ed2b56bc5e5151b26995f0dcb57564d2192fd2b6a1e8
[NSS_KEYLOG] CLIENT_TRAFFIC_SECRET_0
f60a59b1ca9629281d4ee45b9966f19277de0652fb12513d71d388d9a8545077
c88e7cc09e1c5b271aa5c722b527aa3a3f9744011c28cddce9a258be853dac6798aac67588bfbb57108cdbaae3c76130
[EXPORT] CLIENT_RANDOM:
a5ec0b54b796ef98bd1c8fad4f2459b657f6850d0b222a351444fd9deafa125d86991612cbec030e4ca2ee46eadb66ab
[EXPORT] CLIENT_EARLY_TRAFFIC_SECRET:
ae2cca098e941c88b574f068a52ea1cabbc2100a7b52afe3a1ba7981220111f348f5a0925092f619576649e3ddf15921
[EXPORT] CLIENT_HANDSHAKE_TRAFFIC_SECRET:
f916455fb08173176794188bb52bef126517248f04e6da47d6426a71c4e9b6a9d4381cfa89f4fcbf8a79de5183589725
[EXPORT] SERVER_HANDSHAKE_TRAFFIC_SECRET:
e6c60c26694e9d1eaaf97fd83f030dd3d9a0133231a2f803169d131f2238343dffd0a5328b561549cfc32cb30f7955c8
[EXPORT] CLIENT_TRAFFIC_SECRET_0:
e84885f1be1a25cd798768c2cf07d5593173ebe8ec6d2ed0959ff0332d6ad6a3ce6a38abe528db6be4a25500ad81cabe
[EXPORT] SERVER_TRAFFIC_SECRET_0:
643296314df063c06642faf895075afa2d8b9ec3922fcc94a46e69e1be628d09deb62c43fda18f2acdfe27d3b986f1dd
[EXPORT] EARLY_EXPORTER_SECRET:
c78b3e4ba7caca9318621f795100811cd6fbf4090f551e44bde0002e6ecdad78d211e9dc6a459fe44f305d35631c34bf
[EXPORT] EXPORTER_SECRET:
02fec8ac7a633d6b532e1ee0699a455f5a454cecbd684f9ed1c573cd820196a8a2a764726fa9236c168f356d776a5f60


Looking at the implementation of ssl_log_secret in ssl_lib.c I see
that the first parameter to the NSS log is the client random, but then
when I ask for CLIENT_RANDOM why do I get a different value?

I can reproduce this behaviour as well using the s_client: openssl
s_client ... -keymatexport "CLIENT_RANDOM" -keymatexportlen 48
-keylogfile keylog.txt


Thanks in advanced!
- Ian


Re: AES and EVP_CIPHER question

2022-05-16 Thread Philip Prindeville
Sorry, I shouldn't have phrased that inartfully.

There is no EVP_CIPHER_CTX_get_padding(), so how does one achieve something 
analogous?


> On May 16, 2022, at 1:00 PM, Philip Prindeville 
>  wrote:
> 
> Thanks.  That fixed the return value of EVP_CipherFinal().
> 
> Is there a reciprocal EVP_CIPHER_CTX_get_padding() method to find out what 
> the default padding method is for ECB?
> 
> 
> 
>> On May 16, 2022, at 12:41 AM, Tomas Mraz  wrote:
>> 
>> The EVP_CIPHER_CTX_set_padding(ctx, 0) must be called after the
>> EVP_CipherInit() to have an effect.
>> 
>> Also what is the AST_CRYPTO_AES_BLOCKSIZE value? Is it in bits (i.e,
>> 128)?
>> 
>> Also res should be initialized to -1 so you do not return uninitialized
>> value on error.
>> 
>> Tomas Mraz
>> 
>> On Fri, 2022-05-13 at 09:49 -0600, Philip Prindeville wrote:
>>> Hi,
>>> 
>>> I'm trying to rewrite some legacy AES_* code to use EVP_CIPHER_* so
>>> it's forward compatible into 3.x.
>>> 
>>> My code, in a nutshell, looks like:
>>> 
>>> static int evp_cipher_aes_decrypt(const unsigned char *in, unsigned
>>> char *out, unsigned inlen, const ast_aes_decrypt_key *key)
>>> {
>>>EVP_CIPHER_CTX *ctx;
>>>int res, outlen, finallen;
>>>unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8];
>>> 
>>>if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
>>>return -1;
>>>}
>>> 
>>>EVP_CIPHER_CTX_set_padding(ctx, 0);
>>> 
>>>do {
>>>if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(),
>>> key->raw, NULL, 0)) <= 0) {
>>>break;
>>>}
>>>if ((res = EVP_CipherUpdate(ctx, out, , in,
>>> inlen)) <= 0) {
>>>break;
>>>}
>>>/* for ECB, this is a no-op */
>>>if ((res = EVP_CipherFinal(ctx, final, )) <=
>>> 0) {
>>>break;
>>>}
>>> 
>>>res = outlen;
>>>} while (0);
>>> 
>>>EVP_CIPHER_CTX_free(ctx);
>>> 
>>>return res;
>>> }
>>> 
>>> It's ECB, so there's no IV.  Or padding.  The block size and key size
>>> are both 128 bits.
>>> 
>>> One thing I noticed right away is that EVP_CipherUpdate() returns 1,
>>> and sees "outlen" to zero.
>>> 
>>> And then EVP_CipherFinal() returns 0, and sets "finallen" to zero.
>>> 
>>> What's wrong with this code?
>>> 
>>> I'm trying to write "naive" code that counts on the primitives to
>>> indicate how much resultant output is generated for the input I've
>>> given (yes, I know that it's 1:1 in the case of ECB, but I shouldn't
>>> have to hard-code that in case I want to use the same code with
>>> multiple block modes).
>>> 
>>> The function is supposed to return <= 0 on error, otherwise the
>>> number of bytes decrypted into "out" on success.
>>> 
>>> Thanks,
>>> 
>>> -Philip
>>> 
>> 
>> -- 
>> Tomáš Mráz, OpenSSL
>> 
>> 
> 



Re: AES and EVP_CIPHER question

2022-05-16 Thread Philip Prindeville
Thanks.  That fixed the return value of EVP_CipherFinal().

Is there a reciprocal EVP_CIPHER_CTX_get_padding() method to find out what the 
default padding method is for ECB?



> On May 16, 2022, at 12:41 AM, Tomas Mraz  wrote:
> 
> The EVP_CIPHER_CTX_set_padding(ctx, 0) must be called after the
> EVP_CipherInit() to have an effect.
> 
> Also what is the AST_CRYPTO_AES_BLOCKSIZE value? Is it in bits (i.e,
> 128)?
> 
> Also res should be initialized to -1 so you do not return uninitialized
> value on error.
> 
> Tomas Mraz
> 
> On Fri, 2022-05-13 at 09:49 -0600, Philip Prindeville wrote:
>> Hi,
>> 
>> I'm trying to rewrite some legacy AES_* code to use EVP_CIPHER_* so
>> it's forward compatible into 3.x.
>> 
>> My code, in a nutshell, looks like:
>> 
>> static int evp_cipher_aes_decrypt(const unsigned char *in, unsigned
>> char *out, unsigned inlen, const ast_aes_decrypt_key *key)
>> {
>> EVP_CIPHER_CTX *ctx;
>> int res, outlen, finallen;
>> unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8];
>> 
>> if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
>> return -1;
>> }
>> 
>> EVP_CIPHER_CTX_set_padding(ctx, 0);
>> 
>> do {
>> if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(),
>> key->raw, NULL, 0)) <= 0) {
>> break;
>> }
>> if ((res = EVP_CipherUpdate(ctx, out, , in,
>> inlen)) <= 0) {
>> break;
>> }
>> /* for ECB, this is a no-op */
>> if ((res = EVP_CipherFinal(ctx, final, )) <=
>> 0) {
>> break;
>> }
>> 
>> res = outlen;
>> } while (0);
>> 
>> EVP_CIPHER_CTX_free(ctx);
>> 
>> return res;
>> }
>> 
>> It's ECB, so there's no IV.  Or padding.  The block size and key size
>> are both 128 bits.
>> 
>> One thing I noticed right away is that EVP_CipherUpdate() returns 1,
>> and sees "outlen" to zero.
>> 
>> And then EVP_CipherFinal() returns 0, and sets "finallen" to zero.
>> 
>> What's wrong with this code?
>> 
>> I'm trying to write "naive" code that counts on the primitives to
>> indicate how much resultant output is generated for the input I've
>> given (yes, I know that it's 1:1 in the case of ECB, but I shouldn't
>> have to hard-code that in case I want to use the same code with
>> multiple block modes).
>> 
>> The function is supposed to return <= 0 on error, otherwise the
>> number of bytes decrypted into "out" on success.
>> 
>> Thanks,
>> 
>> -Philip
>> 
> 
> -- 
> Tomáš Mráz, OpenSSL
> 
> 



Re: openssl 1.1.1 minor patches to build on SCO OpenServer 5.0.7

2022-05-16 Thread Matt Caswell

Hi Kevin,

The patch in s_socket.c is likely to be acceptable. It looks reasonable 
to me, it may well be useful on other systems and can probably be 
described as a bug fix.


The other changes require the new OPENSSL_SYS_SCO5 define and are 
essentially adding support for a new platform into the codebase.


We have a couple of policies which describe acceptable changes in this area.

Our platform policy says:

"Support for a new platform should only be added if it is being adopted 
as a primary, secondary or community platform."


https://www.openssl.org/policies/platformpolicy.html

Essentially this means that someone has to volunteer to be a community 
maintainer of the platform moving forwards, i.e. they are the contact 
point for any bug fixes/problems that may arise on that platform. You 
don't need to be a committer on the project to be a platform maintainer.


You are proposing updates to an existing stable branch (1.1.1) - as 
opposed to the latest dev branch (master). 1.1.1 also happens to be a 
Long Term Support (LTS) release. In that case our Stable Release Updates 
Policy applies which says this about new platforms:


"The addition of new platforms to LTS branches is acceptable so long as 
the required changes consist solely of additions to configuration."


https://www.openssl.org/policies/technical/stable-release-updates.html

In this case the changes are more than just configuration changes - they 
actually require code changes. Therefore they will not be acceptable on 
the 1.1.1 branch.


If the changes were only on the master branch (and therefore the stable 
release updates policy does not apply) then the changes are likely to be 
acceptable assuming that there is a volunteer to be the community 
maintainer. That's all subject to the standard PR review process of course.



Matt


On 13/05/2022 17:54, Kevin R. Bulgrien wrote:

It was necessary to apply 5 minor patches to openssl 1.1.1n to build it for
SCO OpenServer 5.0.7.  One patch fixing a missing #ifdef AF_INET6 is
already applied to current development for this base version.

The reason for the build is to get TLS1.3 capability on an ancient system.
As it is well-known that TLS1.3 is not going to fix the security issues
on SCO OpenServer 5.0.7, so there's likly no real value to opening a
discussion on that matter.

Is the project interested in receiving the patches?  The curl project has
accepted various patches against SCO OpenServer 5.0.7 for similar issues.

To pull this off, it was necessary to build perl 5.10.1.  At the moment,
all tests are broken (probably requiring some perl modules needed to
support them).  That should be doable, as builds of latest revisions of
of many CPAN perl modules related to build and test have successfully
built for perl 5.8.8 on this system.

The main challenge left to resolve is to build an entropy source for the
system (probably EGD), but, informal tests seem to show that TLS1.3 is
functional after using a Configure command like:

  ./Configure \
--prefix="${PKG_PRFX}" \
--openssldir="${PKG_PRFX}/openssl" \
sco5-gcc \
no-threads \
no-asm \
no-comp \
shared \
-D_REENTRANT \
PERL=/usr/local/bin/perl \
HASHBANGPERL=/usr/local/bin/perl

The test involved creating a random number source file from another
system's /dev/urandom, and then using it in lieu of a local entropy
source.

$ scp $APP:rnd1 .

Proof-of-concept, as this is unfamiliar territory, was to test with
the SCO-provided openssl:

$ openssl s_client -crlf -rand rnd1 -connect tls13.cloudflare.com:443
...
5120 semi-random bytes loaded
CONNECTED(0003)
...
SSL-Session:
 Protocol  : TLSv1
 Cipher: AES128-SHA
...

Apparently some DNS issues are left to resolve in the new build also,
but using an IP address:

$ uname -mrsv
SCO_SV 3.2 5.0.7 i386

$ ./apps/openssl version -b -f -o -p -r -v
OpenSSL 1.1.1n  15 Mar 2022
built on: Fri May 13 04:28:57 2022 UTC
platform: sco5-gcc
options:  bn(64,32) rc4(int) des(long) idea(int) blowfish(ptr)
compiler: gcc -fPIC -O3 -fomit-frame-pointer  -DOPENSSL_PIC -DNDEBUG 
-D_REENTRANT
Seeding source: os-specific

$ ./apps/openssl s_client -crlf -rand rnd1 -connect 104.16.132.229:443
CONNECTED(0003)
...
SSL-Session:
 Protocol  : TLSv1.3
 Cipher: TLS_AES_256_GCM_SHA384
...

All patches are trivial and all but the define OPENSSL_SYS_SCO5 and SHUT_*
patches piggy back onto other #ifdefs, so it seems somewhat reasonable to
think they might be acceptable for a merge.

A synopsis of the patches:

---
openssl-1.1.1n-i686-pc-sco3.2v5.0.7-1.patch
   #ifdef AF_INET6
---

--- openssl-1.1.1n/apps/s_socket.c.orig 2022-03-15 09:37:47.0 -0500
+++ openssl-1.1.1n/apps/s_socket.c  2022-04-26 22:05:51.0 -0500
@@ 

Re: AES and EVP_CIPHER question

2022-05-16 Thread Tomas Mraz
The EVP_CIPHER_CTX_set_padding(ctx, 0) must be called after the
EVP_CipherInit() to have an effect.

Also what is the AST_CRYPTO_AES_BLOCKSIZE value? Is it in bits (i.e,
128)?

Also res should be initialized to -1 so you do not return uninitialized
value on error.

Tomas Mraz

On Fri, 2022-05-13 at 09:49 -0600, Philip Prindeville wrote:
> Hi,
> 
> I'm trying to rewrite some legacy AES_* code to use EVP_CIPHER_* so
> it's forward compatible into 3.x.
> 
> My code, in a nutshell, looks like:
> 
> static int evp_cipher_aes_decrypt(const unsigned char *in, unsigned
> char *out, unsigned inlen, const ast_aes_decrypt_key *key)
> {
>     EVP_CIPHER_CTX *ctx;
>     int res, outlen, finallen;
>     unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8];
> 
>     if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
>     return -1;
>     }
> 
>     EVP_CIPHER_CTX_set_padding(ctx, 0);
> 
>     do {
>     if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(),
> key->raw, NULL, 0)) <= 0) {
>     break;
>     }
>     if ((res = EVP_CipherUpdate(ctx, out, , in,
> inlen)) <= 0) {
>     break;
>     }
>     /* for ECB, this is a no-op */
>     if ((res = EVP_CipherFinal(ctx, final, )) <=
> 0) {
>     break;
>     }
> 
>     res = outlen;
>     } while (0);
> 
>     EVP_CIPHER_CTX_free(ctx);
> 
>     return res;
> }
> 
> It's ECB, so there's no IV.  Or padding.  The block size and key size
> are both 128 bits.
> 
> One thing I noticed right away is that EVP_CipherUpdate() returns 1,
> and sees "outlen" to zero.
> 
> And then EVP_CipherFinal() returns 0, and sets "finallen" to zero.
> 
> What's wrong with this code?
> 
> I'm trying to write "naive" code that counts on the primitives to
> indicate how much resultant output is generated for the input I've
> given (yes, I know that it's 1:1 in the case of ECB, but I shouldn't
> have to hard-code that in case I want to use the same code with
> multiple block modes).
> 
> The function is supposed to return <= 0 on error, otherwise the
> number of bytes decrypted into "out" on success.
> 
> Thanks,
> 
> -Philip
> 

-- 
Tomáš Mráz, OpenSSL