Re: AES and EVP_CIPHER question

2022-05-18 Thread Matt Caswell




On 17/05/2022 16:25, Philip Prindeville wrote:



Thanks, and for 1.1.x?




There's nothing equivalent in 1.1.x AFAIK.

Matt


Re: AES and EVP_CIPHER question

2022-05-17 Thread Philip Prindeville



> On May 17, 2022, at 4:32 AM, Matt Caswell  wrote:
> 
> 
> 
> On 16/05/2022 23:48, Philip Prindeville wrote:
>> Sorry, I shouldn't have phrased that inartfully.
>> There is no EVP_CIPHER_CTX_get_padding(), so how does one achieve something 
>> analogous?
> 
> 
> From 3.0, assuming you are using provided ciphers (i.e. not engine ones), 
> then OSSL_CIPHER_PARAM_PADDING is a "gettable" parameter. See the section 
> "Gettable and Settable EVP_CIPHER_CTX parameters" on this page:
> 
> https://www.openssl.org/docs/man3.0/man3/EVP_EncryptInit_ex2.html
> 
> So you can use EVP_CIPHER_CTX_get_params() to obtain that value (documented 
> on the same man page as above). E.g. something like:
> 
> OSSL_PARAM params[2], *p = params;
> unsigned int pad;
> 
> *p++ = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_PADDING,
> &pad);
> *p = OSSL_PARAM_construct_end();
> 
> if (!EVP_CIPHER_CTX_get_params(ctx, params)) {
>/* Error */
> }
> 
> Matt


Thanks, and for 1.1.x?




Re: AES and EVP_CIPHER question

2022-05-17 Thread Matt Caswell




On 16/05/2022 23:48, Philip Prindeville wrote:

Sorry, I shouldn't have phrased that inartfully.

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



From 3.0, assuming you are using provided ciphers (i.e. not engine 
ones), then OSSL_CIPHER_PARAM_PADDING is a "gettable" parameter. See the 
section "Gettable and Settable EVP_CIPHER_CTX parameters" on this page:


https://www.openssl.org/docs/man3.0/man3/EVP_EncryptInit_ex2.html

So you can use EVP_CIPHER_CTX_get_params() to obtain that value 
(documented on the same man page as above). E.g. something like:


OSSL_PARAM params[2], *p = params;
unsigned int pad;

*p++ = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_PADDING,
 &pad);
*p = OSSL_PARAM_construct_end();

if (!EVP_CIPHER_CTX_get_params(ctx, params)) {
/* Error */
}

Matt





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, &outlen, in,
inlen)) <= 0) {
break;
}
/* for ECB, this is a no-op */
if ((res = EVP_CipherFinal(ctx, final, &finallen)) <=
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
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, &outlen, in,
>>> inlen)) <= 0) {
>>>break;
>>>}
>>>/* for ECB, this is a no-op */
>>>if ((res = EVP_CipherFinal(ctx, final, &finallen)) <=
>>> 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, &outlen, in,
>> inlen)) <= 0) {
>> break;
>> }
>> /* for ECB, this is a no-op */
>> if ((res = EVP_CipherFinal(ctx, final, &finallen)) <=
>> 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-15 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, &outlen, in,
> inlen)) <= 0) {
>     break;
>     }
>     /* for ECB, this is a no-op */
>     if ((res = EVP_CipherFinal(ctx, final, &finallen)) <=
> 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-13 Thread Philip Prindeville
Here's a simple/stupid test program and its output, running on Ubuntu 20.04 LTS:

OpenSSL 1.1.1f  31 Mar 2020
EVP_CIPHER_CTX_new returns 0x5627171042a0
EVP_CipherInit returns 1
EVP_CipherUpdate returns 1, outlen = 0
buf: 'Mary had a littl'
EVP_CipherFinal returns 0, finallen = 0
buf: 'Mary had a littl'
final: ''

Arguably, "outlen" should be the same as "inlen" when calling 
EVP_CipherUpdate() for ECB.  EVP_CipherFinal() should return 1... not clear 
what the appropriate value of "outlen" should be in that case, guessing 0?



test.c
Description: Binary data


Re: AES and EVP_CIPHER question

2022-05-13 Thread Philip Prindeville



> On May 13, 2022, at 10:55 AM, Philip Prindeville 
>  wrote:
> 
> 
> 
>> On May 13, 2022, at 10:34 AM, Matt Caswell  wrote:
>> 
>> 
>> 
>> On 13/05/2022 16:49, 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, &outlen, in, inlen)) 
>>> <= 0) {
>>>break;
>>>}
>>>/* for ECB, this is a no-op */
>>>if ((res = EVP_CipherFinal(ctx, final, &finallen)) <= 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.
>> 
>> What value does inlen have? If you're not doing padding then it must be a 
>> multiple of the block size.
> 
> 
> The length is 16, which matches the key size (and the AES-128-ECB block size).


One other bit of debugging information: I thought, "Maybe the EVP_CipherFinal() 
isn't necessary since we're not using padding or Additional Data, etc." but I 
single-stepped through the code, and noticed this:

* after the call to EVP_CipherUpdate() the "out" buffer is still unchanged;
* after the call to EVP_CipherFinal() the "out" buffer gets the plaintext 
deposited into it, even though it returns zero;

So... that's curious.  Is it a bug?  The man page says "EVP_CipherFinal_ex() 
returns 0 for a decryption failure or 1 for success." (Doesn't describe return 
values for EVP_CipherFinal() but imagine it's analogous).

Clearly the decryption *is* succeeding, but the wrong return value is coming 
back.

My test vector is:

const unsigned char key[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01
};
const unsigned char plaintext[16] = "Mary had a littl";
const unsigned char crypttext[16] = {
0xad, 0xc2, 0xcd, 0x9e, 0x6e, 0x8a, 0xda, 0x0c,
0xe7, 0x71, 0xc8, 0x75, 0x52, 0xf9, 0x7d, 0xd5
};

If that helps.

-Philip


> 
> 
>> 
>> Matt
>> 
>> 
>>> 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
> 



Re: AES and EVP_CIPHER question

2022-05-13 Thread Philip Prindeville



> On May 13, 2022, at 10:34 AM, Matt Caswell  wrote:
> 
> 
> 
> On 13/05/2022 16:49, 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, &outlen, in, inlen)) 
>> <= 0) {
>> break;
>> }
>> /* for ECB, this is a no-op */
>> if ((res = EVP_CipherFinal(ctx, final, &finallen)) <= 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.
> 
> What value does inlen have? If you're not doing padding then it must be a 
> multiple of the block size.


The length is 16, which matches the key size (and the AES-128-ECB block size).


> 
> Matt
> 
> 
>> 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



Re: AES and EVP_CIPHER question

2022-05-13 Thread Matt Caswell




On 13/05/2022 16:49, 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, &outlen, in, inlen)) <= 
0) {
 break;
 }
 /* for ECB, this is a no-op */
 if ((res = EVP_CipherFinal(ctx, final, &finallen)) <= 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.


What value does inlen have? If you're not doing padding then it must be 
a multiple of the block size.


Matt




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