Skip to content

Commit b6c73a2

Browse files
committed
Add X.509 APIs
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent a604be4 commit b6c73a2

17 files changed

+1986
-122
lines changed

src/headers/tomcrypt_custom.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,10 @@
602602
/* Maximum recursion limit when processing nested ASN.1 types. */
603603
#define LTC_DER_MAX_RECURSION 30
604604
#endif
605+
#ifndef LTC_DER_OID_DEFAULT_NODES
606+
/* Default number of nodes when decoding an OID. */
607+
#define LTC_DER_OID_DEFAULT_NODES 12
608+
#endif
605609
#endif
606610

607611
#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH)

src/headers/tomcrypt_macros.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l)
77
#define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__)
88

9+
#define LTC_BIT(n) (1u << (n))
10+
911
/* ---- HELPER MACROS ---- */
1012
#ifdef ENDIAN_NEUTRAL
1113

src/headers/tomcrypt_pk.h

Lines changed: 242 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,10 @@ typedef struct ltc_asn1_list_ {
723723
#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \
724724
do { \
725725
int LTC_TMPVAR(SACP) = (index); \
726+
ltc_asn1_list *LTC_TMPVAR(SACP_list) = (list); \
726727
LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size); \
727728
LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \
728-
list[LTC_TMPVAR(SACP)].used = (int)(Type); \
729+
LTC_TMPVAR(SACP_list)[LTC_TMPVAR(SACP)].used = (int)(Type); \
729730
} while (0)
730731

731732
extern const char* der_asn1_class_to_string_map[];
@@ -933,4 +934,244 @@ int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen,
933934

934935
int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen);
935936

937+
/* X.509 specific enums, structs and APIs */
938+
939+
typedef enum ltc_x509_details {
940+
/* The Serial is an integer, but we provide it as a hex string. */
941+
LTC_X509_SERIAL = 0,
942+
/* The most commonly used elements in an X.509 Name.
943+
* These ones will be converted to a UTF-8 String and
944+
* stored inside the `str` pointer of the `ltc_x509_string`.
945+
*/
946+
/* CommonName */
947+
LTC_X509_CN,
948+
/* Country Code */
949+
LTC_X509_C,
950+
/* Locality */
951+
LTC_X509_L,
952+
/* State or Province */
953+
LTC_X509_ST,
954+
/* Organisation */
955+
LTC_X509_O,
956+
/* OrganisationalUnit */
957+
LTC_X509_OU,
958+
/* EmailAddress */
959+
LTC_X509_EMAIL,
960+
961+
/* GeneralName subtypes
962+
* GeneralName ::= CHOICE {
963+
* otherName [0] OtherName,
964+
* rfc822Name [1] IA5String,
965+
* dNSName [2] IA5String,
966+
* x400Address [3] ORAddress,
967+
* directoryName [4] Name,
968+
* ediPartyName [5] EDIPartyName,
969+
* uniformResourceIdentifier [6] IA5String,
970+
* iPAddress [7] OCTET STRING,
971+
* registeredID [8] OBJECT IDENTIFIER }
972+
*/
973+
LTC_X509_OTHER_NAME = 30,
974+
LTC_X509_RFC822_NAME,
975+
LTC_X509_DNS_NAME,
976+
LTC_X509_X400_ADDRESS,
977+
LTC_X509_DIRECTORY_NAME,
978+
LTC_X509_EDI_PARTY_NAME,
979+
LTC_X509_UNIFORM_RESOURCE_IDENTIFIER,
980+
LTC_X509_IP_ADDRESS,
981+
LTC_X509_REGISTERED_ID,
982+
983+
/* Value was encoded as an OCTET STRING */
984+
LTC_X509_OCTET_STRING,
985+
986+
/* The most commonly used X.509 Certificate Extension. */
987+
/* AuthorityKeyIdentifier */
988+
LTC_X509_CE_AUTHORITY_KEY_ID = 100,
989+
/* SubjectKeyIdentifier */
990+
LTC_X509_CE_SUBJECT_KEY_ID,
991+
/* KeyUsage */
992+
LTC_X509_CE_KEY_USAGE,
993+
/* SubjectAltName */
994+
LTC_X509_CE_SUBJECT_ALT_NAME,
995+
/* BasicConstraints */
996+
LTC_X509_CE_BASIC_CONSTRAINTS,
997+
/* ExtendedKeyUsage */
998+
LTC_X509_CE_EXT_KEY_USAGE,
999+
1000+
/* The rest will not be decoded and has to be treated
1001+
* manually through the `asn1` pointer of the struct.
1002+
*/
1003+
LTC_X509_UNKNOWN = 0x7fff,
1004+
} ltc_x509_details;
1005+
1006+
typedef struct ltc_x509_string {
1007+
ltc_x509_details type;
1008+
const char *str;
1009+
const ltc_asn1_list *asn1;
1010+
} ltc_x509_string;
1011+
1012+
typedef struct ltc_x509_name {
1013+
const ltc_x509_string *names;
1014+
unsigned long names_num;
1015+
const ltc_asn1_list *asn1;
1016+
} ltc_x509_name;
1017+
1018+
typedef struct ltc_x509_time {
1019+
union {
1020+
ltc_utctime *utc;
1021+
ltc_generalizedtime *generalized;
1022+
} u;
1023+
int utc;
1024+
const char *str;
1025+
const ltc_asn1_list *asn1;
1026+
} ltc_x509_time;
1027+
1028+
typedef struct ltc_x509_signature_algorithm {
1029+
enum ltc_pka_id pka;
1030+
const char *hash;
1031+
} ltc_x509_signature_algorithm;
1032+
1033+
typedef struct ltc_x509_validity {
1034+
ltc_x509_time not_before, not_after;
1035+
} ltc_x509_validity;
1036+
1037+
/*
1038+
* Certificate Extensions
1039+
*/
1040+
1041+
/* KeyUsage ::= BIT STRING */
1042+
typedef enum ltc_x509_ce_key_usage {
1043+
/* digitalSignature (0) */
1044+
LTC_KU_DS = LTC_BIT(0),
1045+
/* contentCommitment (1) */
1046+
LTC_KU_CC = LTC_BIT(1),
1047+
/* keyEncipherment (2) */
1048+
LTC_KU_KE = LTC_BIT(2),
1049+
/* dataEncipherment (3) */
1050+
LTC_KU_DE = LTC_BIT(3),
1051+
/* keyAgreement (4) */
1052+
LTC_KU_KA = LTC_BIT(4),
1053+
/* keyCertSign (5) */
1054+
LTC_KU_KCS = LTC_BIT(5),
1055+
/* cRLSign (6) */
1056+
LTC_KU_CRLS = LTC_BIT(6),
1057+
/* encipherOnly (7) */
1058+
LTC_KU_EO = LTC_BIT(7),
1059+
/* decipherOnly (8) */
1060+
LTC_KU_DO = LTC_BIT(8),
1061+
} ltc_x509_ce_key_usage;
1062+
1063+
/* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
1064+
* KeyPurposeId ::= OBJECT IDENTIFIER
1065+
*/
1066+
typedef enum ltc_x509_ce_ext_key_usage {
1067+
/* anyExtendedKeyUsage */
1068+
LTC_EKU_ANY = LTC_BIT(0),
1069+
/* serverAuth */
1070+
LTC_EKU_SA = LTC_BIT(1),
1071+
/* clientAuth */
1072+
LTC_EKU_CA = LTC_BIT(2),
1073+
/* codeSigning */
1074+
LTC_EKU_CS = LTC_BIT(3),
1075+
/* emailProtection */
1076+
LTC_EKU_EP = LTC_BIT(4),
1077+
/* timeStamping */
1078+
LTC_EKU_TS = LTC_BIT(5),
1079+
/* OCSPSigning */
1080+
LTC_EKU_OS = LTC_BIT(6),
1081+
} ltc_x509_ce_ext_key_usage;
1082+
1083+
typedef struct ltc_x509_extensions ltc_x509_extensions;
1084+
1085+
typedef struct ltc_x509_extension {
1086+
ltc_x509_details type;
1087+
const ltc_asn1_list *oid;
1088+
int critical;
1089+
union {
1090+
/* .type = LTC_X509_AUTHORITY_KEY_ID */
1091+
struct {
1092+
ltc_x509_string key_identifier;
1093+
ltc_x509_string authority_cert_issuer;
1094+
ltc_x509_string authority_cert_serial_number;
1095+
} authority_key_id;
1096+
/* .type = LTC_X509_SUBJECT_KEY_ID */
1097+
ltc_x509_string subject_key_identifier;
1098+
/* .type = LTC_X509_KEY_USAGE
1099+
* Bitmask of `enum ltc_x509_ce_key_usage`
1100+
*/
1101+
ulong32 key_usage;
1102+
/* .type = LTC_X509_SUBJECT_ALT_NAME */
1103+
ltc_x509_name subject_alt_name;
1104+
/* .type = LTC_X509_BASIC_CONSTRAINTS */
1105+
struct {
1106+
int ca;
1107+
/* pathLenConstraint is marked as OPTIONAL:
1108+
* -1 -> value missing
1109+
* 0..INT_MAX -> valid values
1110+
*/
1111+
int path_len;
1112+
} basic_constraints;
1113+
/* .type = LTC_X509_EXT_KEY_USAGE
1114+
* Bitmask of `enum ltc_x509_ce_ext_key_usage`
1115+
*/
1116+
ulong32 ext_key_usage;
1117+
} u;
1118+
const ltc_asn1_list *asn1;
1119+
} ltc_x509_extension;
1120+
1121+
struct ltc_x509_extensions {
1122+
const ltc_x509_extension *extensions;
1123+
unsigned long extensions_num;
1124+
const ltc_asn1_list *asn1;
1125+
1126+
const ltc_x509_extension *authority_key_id;
1127+
const ltc_x509_extension *subject_key_identifier;
1128+
const ltc_x509_extension *key_usage;
1129+
const ltc_x509_extension *subject_alt_name;
1130+
const ltc_x509_extension *basic_constraints;
1131+
const ltc_x509_extension *ext_key_usage;
1132+
/* let's pre-reserve this for future extensions */
1133+
const ltc_x509_extension *more[7];
1134+
};
1135+
1136+
typedef struct ltc_x509_tbs_certificate {
1137+
unsigned long version;
1138+
ltc_x509_string serial_number;
1139+
ltc_x509_signature_algorithm signature_algorithm;
1140+
ltc_x509_name issuer;
1141+
ltc_x509_validity validity;
1142+
ltc_x509_name subject;
1143+
ltc_pka_key subject_public_key_info;
1144+
const ltc_asn1_list *issuer_uid;
1145+
const ltc_asn1_list *subject_uid;
1146+
ltc_x509_extensions extensions;
1147+
const ltc_asn1_list *asn1;
1148+
} ltc_x509_tbs_certificate;
1149+
1150+
typedef struct ltc_x509_signature {
1151+
const unsigned char *signature;
1152+
/* The signature length is given in bits, but it is stored as bytes.
1153+
* I.e. a signature of 123 bits will be stored in 128bits resp. 16bytes.
1154+
*/
1155+
unsigned long signature_len;
1156+
const ltc_asn1_list *asn1;
1157+
} ltc_x509_signature;
1158+
1159+
typedef struct ltc_x509_certificate {
1160+
ltc_x509_tbs_certificate tbs_certificate;
1161+
ltc_x509_signature_algorithm signature_algorithm;
1162+
ltc_x509_signature signature;
1163+
const ltc_asn1_list *asn1;
1164+
} ltc_x509_certificate;
1165+
1166+
int x509_import(const unsigned char *asn1_cert, unsigned long asn1_len, const ltc_x509_certificate **out);
1167+
int x509_import_pem(const char *pem, unsigned long *pem_len, const ltc_x509_certificate **out);
1168+
#ifndef LTC_NO_FILE
1169+
int x509_import_pem_filehandle(FILE *f, const ltc_x509_certificate **out);
1170+
#endif
1171+
int x509_cert_is_signed_by(const ltc_x509_certificate *cert, const ltc_pka_key *key, int *stat);
1172+
int x509_cmp_name(const ltc_x509_name *a, const ltc_x509_name *b);
1173+
int x509_name_detail_get(const ltc_x509_name *name, ltc_x509_details type, const ltc_x509_string **str);
1174+
int x509_extension_by_oid(const ltc_x509_certificate *cert, const char *oid, const ltc_x509_extension **extension);
1175+
void x509_free(const ltc_x509_certificate **cert);
1176+
9361177
#endif

src/headers/tomcrypt_private.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,33 @@ enum ltc_oid_id {
6060
LTC_OID_X25519,
6161
LTC_OID_ED25519,
6262
LTC_OID_DH,
63+
LTC_OID_RSA_WITH_MD5,
64+
LTC_OID_RSA_WITH_SHA1,
65+
LTC_OID_RSA_WITH_SHA224,
66+
LTC_OID_RSA_WITH_SHA256,
67+
LTC_OID_RSA_WITH_SHA384,
68+
LTC_OID_RSA_WITH_SHA512,
69+
LTC_OID_RSA_WITH_SHA512_224,
70+
LTC_OID_RSA_WITH_SHA512_512,
71+
LTC_OID_ECDSA_WITH_SHA1,
72+
LTC_OID_ECDSA_WITH_SHA224,
73+
LTC_OID_ECDSA_WITH_SHA256,
74+
LTC_OID_ECDSA_WITH_SHA384,
75+
LTC_OID_ECDSA_WITH_SHA512,
76+
LTC_OID_DSA_WITH_SHA1,
77+
LTC_OID_DSA_WITH_SHA224,
78+
LTC_OID_DSA_WITH_SHA256,
79+
LTC_OID_DSA_WITH_SHA384,
80+
LTC_OID_DSA_WITH_SHA512,
81+
LTC_OID_ECDSA_WITH_SHA3_224,
82+
LTC_OID_ECDSA_WITH_SHA3_256,
83+
LTC_OID_ECDSA_WITH_SHA3_384,
84+
LTC_OID_ECDSA_WITH_SHA3_512,
85+
LTC_OID_RSA_WITH_SHA3_224,
86+
LTC_OID_RSA_WITH_SHA3_256,
87+
LTC_OID_RSA_WITH_SHA3_384,
88+
LTC_OID_RSA_WITH_SHA3_512,
89+
6390
LTC_OID_NUM
6491
};
6592

@@ -400,13 +427,14 @@ int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng);
400427

401428
int pk_get_oid(enum ltc_oid_id id, const char **st);
402429
int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka);
430+
int pk_get_sig_alg(enum ltc_oid_id id, ltc_x509_signature_algorithm *sig_alg);
403431
int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid);
432+
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen);
433+
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen);
404434
#ifdef LTC_DER
405435
int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id);
436+
int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
406437
#endif
407-
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen);
408-
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen);
409-
410438
int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size);
411439

412440
/* ---- DH Routines ---- */
@@ -573,6 +601,7 @@ int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen,
573601
#define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t)))
574602

575603
/* DER handling */
604+
int der_decode_sequence_flexi_limited(const unsigned char *in, unsigned long *inlen, long max_depth, ltc_asn1_list **out);
576605
int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
577606
ltc_asn1_list *root,
578607
ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
@@ -588,6 +617,12 @@ int der_length_asn1_length(unsigned long len, unsigned long *outlen);
588617
int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
589618
unsigned long *outlen, unsigned long *payloadlen);
590619

620+
621+
int der_decode_ia5_string_data(const unsigned char *in, unsigned long inlen,
622+
char *out, unsigned long *outlen);
623+
int der_decode_object_identifier_data(const unsigned char *in, unsigned long inlen,
624+
unsigned long *words, unsigned long *outlen);
625+
591626
unsigned long der_object_identifier_bits(unsigned long x);
592627

593628
int der_ia5_char_encode(int c);
@@ -656,10 +691,12 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i
656691
enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len,
657692
ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len);
658693

659-
int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka);
694+
int x509_get_pka(const ltc_asn1_list *pub, enum ltc_pka_id *pka);
695+
int x509_get_sig_alg(const ltc_asn1_list *pub, ltc_x509_signature_algorithm *sig_alg);
660696
int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root);
661-
662-
int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
697+
int x509_get_extensions(const ltc_asn1_list *seq, ltc_x509_extensions *extensions);
698+
void x509_free_extensions(const ltc_x509_extensions *extensions);
699+
int x509_get_serial(const ltc_asn1_list *asn1, ltc_x509_string *serial);
663700

664701
#endif /* LTC_DER */
665702

src/misc/crypt/crypt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ const char *crypt_build_settings =
455455
#if defined(LTC_DER)
456456
" DER "
457457
" " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
458+
" " NAME_VALUE(LTC_DER_OID_DEFAULT_NODES) " "
458459
#endif
459460
#if defined(LTC_PKCS_1)
460461
" PKCS#1 "

0 commit comments

Comments
 (0)