Skip to content

Commit 943da00

Browse files
add support for X509_get_signature_info
1 parent 5ede432 commit 943da00

File tree

8 files changed

+203
-70
lines changed

8 files changed

+203
-70
lines changed

crypto/err/x509.errordata

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ X509,137,SIGNATURE_ALGORITHM_MISMATCH
3939
X509,128,UNKNOWN_KEY_TYPE
4040
X509,129,UNKNOWN_NID
4141
X509,130,UNKNOWN_PURPOSE_ID
42+
X509,145,UNKNOWN_SIGID_ALGS
4243
X509,131,UNKNOWN_TRUST_ID
4344
X509,132,UNSUPPORTED_ALGORITHM
4445
X509,133,WRONG_LOOKUP_TYPE

crypto/x509/internal.h

+17-3
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,21 @@ typedef struct {
139139
// an |X509_NAME|.
140140
DECLARE_ASN1_FUNCTIONS(X509_CINF)
141141

142+
struct x509_sig_info_st {
143+
// NID of message digest.
144+
int digest_nid;
145+
// NID of public key algorithm.
146+
int pubkey_nid;
147+
// Security bits.
148+
int sec_bits;
149+
uint32_t flags;
150+
} /* X509_SIG_INFO */;
151+
142152
struct x509_st {
143153
X509_CINF *cert_info;
144154
X509_ALGOR *sig_alg;
145155
ASN1_BIT_STRING *signature;
156+
X509_SIG_INFO sig_info;
146157
CRYPTO_refcount_t references;
147158
CRYPTO_EX_DATA ex_data;
148159
// These contain copies of various extension values
@@ -341,9 +352,9 @@ struct x509_store_ctx_st {
341352
X509_STORE_CTX_cleanup_fn cleanup;
342353

343354
// The following is built up
344-
int valid; // if 0, rebuild chain
345-
int last_untrusted; // index of last untrusted cert
346-
STACK_OF(X509) *chain; // chain of X509s - built up and trusted
355+
int valid; // if 0, rebuild chain
356+
int last_untrusted; // index of last untrusted cert
357+
STACK_OF(X509) *chain; // chain of X509s - built up and trusted
347358

348359
// When something goes wrong, this is why
349360
int error_depth;
@@ -409,6 +420,9 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
409420
int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
410421
EVP_PKEY *pkey);
411422

423+
// x509_init_signature_info initializes the signature info for |x509|.
424+
int x509_init_signature_info(X509 *x509);
425+
412426

413427
// Path-building functions.
414428

crypto/x509/x509_set.c

+65
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include <openssl/x509.h>
6262

6363
#include "internal.h"
64+
#include "openssl/x509v3.h"
6465

6566

6667
long X509_get_version(const X509 *x509) {
@@ -238,3 +239,67 @@ const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) {
238239
X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509) {
239240
return x509->cert_info->key;
240241
}
242+
243+
static int X509_SIG_INFO_get(const X509_SIG_INFO *sig_info, int *digest_nid,
244+
int *pubkey_nid, int *sec_bits, uint32_t *flags) {
245+
if (digest_nid != NULL) {
246+
*digest_nid = sig_info->digest_nid;
247+
}
248+
if (pubkey_nid != NULL) {
249+
*pubkey_nid = sig_info->pubkey_nid;
250+
}
251+
if (sec_bits != NULL) {
252+
*sec_bits = sig_info->sec_bits;
253+
}
254+
if (flags != NULL) {
255+
*flags = sig_info->flags;
256+
}
257+
return (sig_info->flags & X509_SIG_INFO_VALID) != 0;
258+
}
259+
260+
int X509_get_signature_info(X509 *x509, int *digest_nid, int *pubkey_nid,
261+
int *sec_bits, uint32_t *flags) {
262+
if (!X509_check_purpose(x509, -1, -1)) {
263+
OPENSSL_PUT_ERROR(X509, X509_V_ERR_INVALID_PURPOSE);
264+
return 0;
265+
}
266+
return X509_SIG_INFO_get(&x509->sig_info, digest_nid, pubkey_nid, sec_bits,
267+
flags);
268+
}
269+
270+
int x509_init_signature_info(X509 *x509) {
271+
int pubkey_nid, digest_nid;
272+
const EVP_MD *md;
273+
274+
x509->sig_info.digest_nid = NID_undef;
275+
x509->sig_info.pubkey_nid = NID_undef;
276+
x509->sig_info.sec_bits = -1;
277+
x509->sig_info.flags = 0;
278+
if (!OBJ_find_sigid_algs(OBJ_obj2nid(x509->sig_alg->algorithm), &digest_nid,
279+
&pubkey_nid) ||
280+
pubkey_nid == NID_undef) {
281+
OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_SIGID_ALGS);
282+
return 0;
283+
}
284+
x509->sig_info.pubkey_nid = pubkey_nid;
285+
x509->sig_info.digest_nid = digest_nid;
286+
x509->sig_info.flags |= X509_SIG_INFO_VALID;
287+
288+
md = EVP_get_digestbynid(digest_nid);
289+
if (md == NULL) {
290+
// Some valid signature algorithms have an undefined digest. See
291+
// crypto/obj/obj_xref.c.
292+
return 1;
293+
}
294+
// Security bits: half number of bits in digest.
295+
x509->sig_info.sec_bits = (int)EVP_MD_size(md) * 4;
296+
297+
switch (digest_nid) {
298+
case NID_sha1:
299+
case NID_sha256:
300+
case NID_sha384:
301+
case NID_sha512:
302+
x509->sig_info.flags |= X509_SIG_INFO_TLS;
303+
}
304+
return 1;
305+
}

crypto/x509/x509_test.cc

+31
Original file line numberDiff line numberDiff line change
@@ -7049,3 +7049,34 @@ TEST(X509Test, GetTextByOBJ) {
70497049
}
70507050
}
70517051
}
7052+
7053+
TEST(X509Test, GetSigInfo) {
7054+
bssl::UniquePtr<X509> cert(CertFromPEM(kLeafPEM));
7055+
ASSERT_TRUE(cert);
7056+
7057+
int digest_nid, pubkey_nid, sec_bits;
7058+
uint32_t flags;
7059+
EXPECT_TRUE(X509_get_signature_info(cert.get(), &digest_nid, &pubkey_nid,
7060+
&sec_bits, &flags));
7061+
7062+
EXPECT_EQ(digest_nid, NID_sha256);
7063+
EXPECT_EQ(pubkey_nid, NID_rsaEncryption);
7064+
EXPECT_EQ(sec_bits, (int)EVP_MD_size(EVP_sha256()) * 4);
7065+
EXPECT_TRUE(flags & (X509_SIG_INFO_VALID | X509_SIG_INFO_TLS));
7066+
7067+
cert = CertFromPEM(kEd25519Cert);
7068+
EXPECT_TRUE(X509_get_signature_info(cert.get(), &digest_nid, &pubkey_nid,
7069+
&sec_bits, &flags));
7070+
EXPECT_EQ(digest_nid, NID_undef);
7071+
EXPECT_EQ(pubkey_nid, NID_ED25519);
7072+
EXPECT_EQ(sec_bits, -1);
7073+
EXPECT_TRUE(flags & X509_SIG_INFO_VALID);
7074+
7075+
cert = CertFromPEM(kExampleRsassaPssCert);
7076+
EXPECT_TRUE(X509_get_signature_info(cert.get(), &digest_nid, &pubkey_nid,
7077+
&sec_bits, &flags));
7078+
EXPECT_EQ(digest_nid, NID_undef);
7079+
EXPECT_EQ(pubkey_nid, NID_rsaEncryption);
7080+
EXPECT_EQ(sec_bits, -1);
7081+
EXPECT_TRUE(flags & X509_SIG_INFO_VALID);
7082+
}

crypto/x509v3/v3_purp.c

+3
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@ int x509v3_cache_extensions(X509 *x) {
565565
break;
566566
}
567567
}
568+
if (!x509_init_signature_info(x)) {
569+
x->ex_flags |= EXFLAG_INVALID;
570+
}
568571
x->ex_flags |= EXFLAG_SET;
569572

570573
CRYPTO_MUTEX_unlock_write(&x->lock);

generated-src/err_data.c

+66-64
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ const uint32_t kOpenSSLReasonValues[] = {
233233
0x2c403998,
234234
0x2c4093a9,
235235
0x2c4139a9,
236-
0x2c41b9bc,
236+
0x2c41b9cf,
237237
0x2c42136f,
238-
0x2c42b9cd,
238+
0x2c42b9e0,
239239
0x2c43076d,
240240
0x2c43b8b3,
241241
0x2c4437fb,
@@ -247,6 +247,7 @@ const uint32_t kOpenSSLReasonValues[] = {
247247
0x2c4738ea,
248248
0x2c47b923,
249249
0x2c48380d,
250+
0x2c48b9bc,
250251
0x30320000,
251252
0x30328015,
252253
0x3033001f,
@@ -705,71 +706,71 @@ const uint32_t kOpenSSLReasonValues[] = {
705706
0x4c4197bc,
706707
0x4c421925,
707708
0x4c429704,
708-
0x503239df,
709-
0x5032b9ee,
710-
0x503339f9,
711-
0x5033ba09,
712-
0x50343a22,
713-
0x5034ba3c,
714-
0x50353a4a,
715-
0x5035ba60,
716-
0x50363a72,
717-
0x5036ba88,
718-
0x50373aa1,
719-
0x5037bab4,
720-
0x50383acc,
721-
0x5038badd,
722-
0x50393af2,
723-
0x5039bb06,
724-
0x503a3b26,
725-
0x503abb3c,
726-
0x503b3b54,
727-
0x503bbb66,
728-
0x503c3b82,
729-
0x503cbb99,
730-
0x503d3bb2,
731-
0x503dbbc8,
732-
0x503e3bd5,
733-
0x503ebbeb,
734-
0x503f3bfd,
709+
0x503239f2,
710+
0x5032ba01,
711+
0x50333a0c,
712+
0x5033ba1c,
713+
0x50343a35,
714+
0x5034ba4f,
715+
0x50353a5d,
716+
0x5035ba73,
717+
0x50363a85,
718+
0x5036ba9b,
719+
0x50373ab4,
720+
0x5037bac7,
721+
0x50383adf,
722+
0x5038baf0,
723+
0x50393b05,
724+
0x5039bb19,
725+
0x503a3b39,
726+
0x503abb4f,
727+
0x503b3b67,
728+
0x503bbb79,
729+
0x503c3b95,
730+
0x503cbbac,
731+
0x503d3bc5,
732+
0x503dbbdb,
733+
0x503e3be8,
734+
0x503ebbfe,
735+
0x503f3c10,
735736
0x503f83b3,
736-
0x50403c10,
737-
0x5040bc20,
738-
0x50413c3a,
739-
0x5041bc49,
740-
0x50423c63,
741-
0x5042bc80,
742-
0x50433c90,
743-
0x5043bca0,
744-
0x50443cbd,
737+
0x50403c23,
738+
0x5040bc33,
739+
0x50413c4d,
740+
0x5041bc5c,
741+
0x50423c76,
742+
0x5042bc93,
743+
0x50433ca3,
744+
0x5043bcb3,
745+
0x50443cd0,
745746
0x50448469,
746-
0x50453cd1,
747-
0x5045bcef,
748-
0x50463d02,
749-
0x5046bd18,
750-
0x50473d2a,
751-
0x5047bd3f,
752-
0x50483d65,
753-
0x5048bd73,
754-
0x50493d86,
755-
0x5049bd9b,
756-
0x504a3db1,
757-
0x504abdc1,
758-
0x504b3de1,
759-
0x504bbdf4,
760-
0x504c3e17,
761-
0x504cbe45,
762-
0x504d3e72,
763-
0x504dbe8f,
764-
0x504e3eaa,
765-
0x504ebec6,
766-
0x504f3ed8,
767-
0x504fbeef,
768-
0x50503efe,
747+
0x50453ce4,
748+
0x5045bd02,
749+
0x50463d15,
750+
0x5046bd2b,
751+
0x50473d3d,
752+
0x5047bd52,
753+
0x50483d78,
754+
0x5048bd86,
755+
0x50493d99,
756+
0x5049bdae,
757+
0x504a3dc4,
758+
0x504abdd4,
759+
0x504b3df4,
760+
0x504bbe07,
761+
0x504c3e2a,
762+
0x504cbe58,
763+
0x504d3e85,
764+
0x504dbea2,
765+
0x504e3ebd,
766+
0x504ebed9,
767+
0x504f3eeb,
768+
0x504fbf02,
769+
0x50503f11,
769770
0x50508729,
770-
0x50513f11,
771-
0x5051bcaf,
772-
0x50523e57,
771+
0x50513f24,
772+
0x5051bcc2,
773+
0x50523e6a,
773774
0x583210b7,
774775
0x5c3293b5,
775776
0x5c3313ce,
@@ -1534,6 +1535,7 @@ const char kOpenSSLReasonStringData[] =
15341535
"SIGNATURE_ALGORITHM_MISMATCH\0"
15351536
"UNKNOWN_KEY_TYPE\0"
15361537
"UNKNOWN_PURPOSE_ID\0"
1538+
"UNKNOWN_SIGID_ALGS\0"
15371539
"UNKNOWN_TRUST_ID\0"
15381540
"WRONG_LOOKUP_TYPE\0"
15391541
"BAD_IP_ADDRESS\0"

include/openssl/base.h

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ typedef struct X509_name_entry_st X509_NAME_ENTRY;
300300
typedef struct X509_name_st X509_NAME;
301301
typedef struct X509_pubkey_st X509_PUBKEY;
302302
typedef struct X509_req_st X509_REQ;
303+
typedef struct x509_sig_info_st X509_SIG_INFO;
303304
typedef struct X509_sig_st X509_SIG;
304305
typedef struct bignum_ctx BN_CTX;
305306
typedef struct bignum_st BIGNUM;

include/openssl/x509.h

+19-3
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,21 @@ OPENSSL_EXPORT X509_EXTENSION *X509_get_ext(const X509 *x, int loc);
258258
// but they will be rejected when verifying.
259259
OPENSSL_EXPORT const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x509);
260260

261+
// X509_SIG_INFO_* are flags for |X509_get_signature_info|.
262+
// X509_SIG_INFO_VALID means that the signature info is valid.
263+
#define X509_SIG_INFO_VALID 0x1
264+
// X509_SIG_INFO_TLS means that the signature is suitable for TLS use.
265+
#define X509_SIG_INFO_TLS 0x2
266+
267+
// X509_get_signature_info retrieves information about the signature of |x509|.
268+
// The NID of the signing digest is written to |*digest_nid|, the public key
269+
// algorithm to |*pubkey_nid|, the effective security bits to |*sec_bits|, and
270+
// flag details to |*flags|. Parameters other than |*x509| can be set to NULL if
271+
// the information is not required.
272+
OPENSSL_EXPORT int X509_get_signature_info(X509 *x509, int *digest_nid,
273+
int *pubkey_nid, int *sec_bits,
274+
uint32_t *flags);
275+
261276
// X509_get0_signature sets |*out_sig| and |*out_alg| to the signature and
262277
// signature algorithm of |x509|, respectively. Either output pointer may be
263278
// NULL to ignore the value.
@@ -1838,7 +1853,8 @@ OPENSSL_EXPORT int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
18381853
// This function outputs a legacy format that does not correctly handle string
18391854
// encodings and other cases. Prefer |X509_NAME_print_ex| if printing a name for
18401855
// debugging purposes.
1841-
OPENSSL_EXPORT char *X509_NAME_oneline(const X509_NAME *name, char *buf, int size);
1856+
OPENSSL_EXPORT char *X509_NAME_oneline(const X509_NAME *name, char *buf,
1857+
int size);
18421858

18431859
// X509_NAME_print_ex_fp behaves like |X509_NAME_print_ex| but writes to |fp|.
18441860
OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm,
@@ -3029,8 +3045,7 @@ OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx,
30293045
// may be |X509_LU_X509| or |X509_LU_CRL|, and the subject name from the store
30303046
// in |vs|. If found and |ret| is not NULL, it increments the reference count
30313047
// and stores the object in |ret|.
3032-
OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs,
3033-
int type,
3048+
OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, int type,
30343049
X509_NAME *name,
30353050
X509_OBJECT *ret);
30363051

@@ -3206,5 +3221,6 @@ BSSL_NAMESPACE_END
32063221
#define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 142
32073222
#define X509_R_NO_CRL_FOUND 143
32083223
#define X509_R_INVALID_POLICY_EXTENSION 144
3224+
#define X509_R_UNKNOWN_SIGID_ALGS 145
32093225

32103226
#endif // OPENSSL_HEADER_X509_H

0 commit comments

Comments
 (0)