-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Closed
prchander/openssl
#3Labels
branch: 1.1.1Applies to OpenSSL_1_1_1-stable branch (EOL)Applies to OpenSSL_1_1_1-stable branch (EOL)branch: masterApplies to master branchApplies to master branchtriaged: bugThe issue/pr is/fixes a bugThe issue/pr is/fixes a bug
Description
i2d_RSAPrivateKey() will happily encode an RSA structure where only n and e are present, i.e. a public key. The following program demonstrates it:
#include <stdio.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
static int TEST(const char *expr, int b)
{
if (b)
return 1;
fprintf(stderr, "Failed '%s'\n", expr);
return 0;
}
#define TEST_true(e) TEST(#e " != 0", (e) != 0)
#define TEST_ptr(p) TEST(#p " != NULL", (p) != NULL)
#define TEST_int_le(a,b) TEST(#a " <= " #b, (a) <= (b))
int main()
{
RSA *rsa = NULL;
BIGNUM *n = NULL;
BIGNUM *e = NULL;
int ok = 0;
if (!TEST_ptr(rsa = RSA_new())
|| !TEST_ptr(n = BN_new())
|| !TEST_true(BN_set_word(n, 123456))
|| !TEST_ptr(e = BN_new())
|| !TEST_true(BN_set_word(e, 0x10001))
|| !TEST_true(RSA_set0_key(rsa, n, e, NULL)))
goto end;
n = e = NULL; /* They are now "owned" by |rsa| */
/*
* This SHOULD fail, as we're trying to encode a public key as a private
* key. The private key bits MUST be present for a proper RSAPrivateKey.
*/
if (TEST_int_le(i2d_RSAPrivateKey_fp(stdout, rsa), 0))
ok = 1;
end:
RSA_free(rsa);
BN_free(n);
BN_free(e);
return !ok; /* exit code 0 for ok == 1 and vice versa */
}$ cc -o asn1-RSAPrivateKey asn1-RSAPrivateKey.c -lcrypto
$ ./asn1-RSAPrivateKey > foo.der
Failed 'i2d_RSAPrivateKey_fp(stdout, rsa) <= 0'
$ echo $?
1
$ openssl asn1parse -i -inform d -in foo.der
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :00
5:d=1 hl=2 l= 3 prim: INTEGER :01E240
10:d=1 hl=2 l= 3 prim: INTEGER :010001The ASN.1 structure (https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2) is this:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
This isn't specifically about RSA, it's deep in the ASN.1 encoder, where the code for primitives is a bit lax with regards to zero content... it doesn't check if the item is optional or not.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
branch: 1.1.1Applies to OpenSSL_1_1_1-stable branch (EOL)Applies to OpenSSL_1_1_1-stable branch (EOL)branch: masterApplies to master branchApplies to master branchtriaged: bugThe issue/pr is/fixes a bugThe issue/pr is/fixes a bug