diff --git a/libclamav/asn1.c b/libclamav/asn1.c index 0db1dcc2a..637974d1d 100644 --- a/libclamav/asn1.c +++ b/libclamav/asn1.c @@ -52,6 +52,9 @@ #define OID_1_2_840_113549_1_1_11 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" #define OID_sha256WithRSAEncryption OID_1_2_840_113549_1_1_11 +#define OID_1_2_840_113549_1_1_12 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c" +#define OID_sha384WithRSAEncryption OID_1_2_840_113549_1_1_12 + #define OID_1_2_840_113549_1_1_13 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0d" #define OID_sha512WithRSAEncryption OID_1_2_840_113549_1_1_13 @@ -277,7 +280,19 @@ static int asn1_expect_rsa(fmap_t *map, const void **asn1data, unsigned int *asn if(asn1_expect_objtype(map, obj.content, &avail, &obj, ASN1_TYPE_OBJECT_ID)) return 1; - if(obj.size != lenof(OID_sha1WithRSA) && obj.size != lenof(OID_sha1WithRSAEncryption)) { /* lenof(OID_sha1WithRSAEncryption) = lenof(OID_md5WithRSAEncryption) = 9 */ + + // Two cases to check for: + // obj.size == 5: + // - OID_sha1WithRSA + // + // obj.size == 9: + // - OID_md2WithRSAEncryption + // - OID_md5WithRSAEncryption + // - OID_sha1WithRSAEncryption + // - OID_sha256WithRSAEncryption + // - OID_sha384WithRSAEncryption + // - OID_sha512WithRSAEncryption + if(obj.size != lenof(OID_sha1WithRSA) && obj.size != lenof(OID_sha1WithRSAEncryption)) { cli_dbgmsg("asn1_expect_rsa: expecting OID with size 5 or 9, got %02x with size %u\n", obj.type, obj.size); return 1; } @@ -285,22 +300,33 @@ static int asn1_expect_rsa(fmap_t *map, const void **asn1data, unsigned int *asn cli_dbgmsg("asn1_expect_rsa: failed to read OID\n"); return 1; } - if(obj.size == lenof(OID_sha1WithRSA) && !memcmp(obj.content, OID_sha1WithRSA, lenof(OID_sha1WithRSA))) - *hashtype = CLI_SHA1RSA; /* Obsolete sha1rsa 1.3.14.3.2.29 */ - else if(obj.size == lenof(OID_sha1WithRSAEncryption) && !memcmp(obj.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) - *hashtype = CLI_SHA1RSA; /* sha1withRSAEncryption 1.2.840.113549.1.1.5 */ - else if(obj.size == lenof(OID_md5WithRSAEncryption) && !memcmp(obj.content, OID_md5WithRSAEncryption, lenof(OID_md5WithRSAEncryption))) - *hashtype = CLI_MD5RSA; /* md5withRSAEncryption 1.2.840.113549.1.1.4 */ - else if(obj.size == lenof(OID_md2WithRSAEncryption) && !memcmp(obj.content, OID_md2WithRSAEncryption, lenof(OID_md2WithRSAEncryption))) { - cli_dbgmsg("asn1_expect_rsa: MD2 with RSA (not yet supported)\n"); - return 1; - } - else if(obj.size == lenof(OID_sha256WithRSAEncryption) && !memcmp(obj.content, OID_sha256WithRSAEncryption, lenof(OID_sha256WithRSAEncryption))) { - *hashtype = CLI_SHA256RSA; /* sha256WithRSAEncryption 1.2.840.113549.1.1.11 */ - } - else if(obj.size == lenof(OID_sha512WithRSAEncryption) && !memcmp(obj.content, OID_sha512WithRSAEncryption, lenof(OID_sha512WithRSAEncryption))) { - cli_dbgmsg("asn1_expect_rsa: SHA512 with RSA (not yet supported)\n"); - return 1; + if(obj.size == lenof(OID_sha1WithRSA)) { + + if(!memcmp(obj.content, OID_sha1WithRSA, lenof(OID_sha1WithRSA))) + *hashtype = CLI_SHA1RSA; /* Obsolete sha1rsa 1.3.14.3.2.29 */ + + } else if (obj.size == lenof(OID_sha1WithRSAEncryption)) { + + if(!memcmp(obj.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) + *hashtype = CLI_SHA1RSA; /* sha1withRSAEncryption 1.2.840.113549.1.1.5 */ + + else if(!memcmp(obj.content, OID_md5WithRSAEncryption, lenof(OID_md5WithRSAEncryption))) + *hashtype = CLI_MD5RSA; /* md5withRSAEncryption 1.2.840.113549.1.1.4 */ + + else if(!memcmp(obj.content, OID_md2WithRSAEncryption, lenof(OID_md2WithRSAEncryption))) { + cli_dbgmsg("asn1_expect_rsa: MD2 with RSA (not yet supported)\n"); + return 1; + } + else if(!memcmp(obj.content, OID_sha256WithRSAEncryption, lenof(OID_sha256WithRSAEncryption))) { + *hashtype = CLI_SHA256RSA; /* sha256WithRSAEncryption 1.2.840.113549.1.1.11 */ + } + else if(!memcmp(obj.content, OID_sha384WithRSAEncryption, lenof(OID_sha384WithRSAEncryption))) { + *hashtype = CLI_SHA384RSA; /* sha384WithRSAEncryption 1.2.840.113549.1.1.12 */ + } + else if(!memcmp(obj.content, OID_sha512WithRSAEncryption, lenof(OID_sha512WithRSAEncryption))) { + cli_dbgmsg("asn1_expect_rsa: SHA512 with RSA (not yet supported)\n"); + return 1; + } } else { cli_dbgmsg("asn1_expect_rsa: OID mismatch (size %u)\n", obj.size); @@ -509,35 +535,47 @@ static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size, return 1; do { - if(asn1_expect_objtype(map, *asn1data, size, &crt, ASN1_TYPE_SEQUENCE)) /* SEQUENCE */ + if(asn1_expect_objtype(map, *asn1data, size, &crt, ASN1_TYPE_SEQUENCE)) { /* SEQUENCE */ + cli_dbgmsg("asn1_get_x509: expected SEQUENCE at the x509 start\n"); break; + } *asn1data = crt.next; tbsdata = crt.content; - if(asn1_expect_objtype(map, crt.content, &crt.size, &tbs, ASN1_TYPE_SEQUENCE)) /* SEQUENCE - TBSCertificate */ + if(asn1_expect_objtype(map, crt.content, &crt.size, &tbs, ASN1_TYPE_SEQUENCE)) { /* SEQUENCE - TBSCertificate */ + cli_dbgmsg("asn1_get_x509: expected SEQUENCE at the TBSCertificate start\n"); break; + } tbssize = (uint8_t *)tbs.next - tbsdata; - if(asn1_expect_objtype(map, tbs.content, &tbs.size, &obj, 0xa0)) /* [0] */ + if(asn1_expect_objtype(map, tbs.content, &tbs.size, &obj, 0xa0)) { /* [0] */ + cli_dbgmsg("asn1_get_x509: expected [0] version container in TBSCertificate\n"); break; + } avail = obj.size; next = obj.next; - if(asn1_expect_obj(map, &obj.content, &avail, ASN1_TYPE_INTEGER, 1, "\x02")) /* version 3 only */ + if(asn1_expect_obj(map, &obj.content, &avail, ASN1_TYPE_INTEGER, 1, "\x02")) { /* version 3 only */ + cli_dbgmsg("asn1_get_x509: unexpected type or value for TBSCertificate version\n"); break; + } if(avail) { cli_dbgmsg("asn1_get_x509: found unexpected extra data in version\n"); break; } - if(asn1_expect_objtype(map, next, &tbs.size, &obj, ASN1_TYPE_INTEGER)) /* serialNumber */ + if(asn1_expect_objtype(map, next, &tbs.size, &obj, ASN1_TYPE_INTEGER)) { /* serialNumber */ + cli_dbgmsg("asn1_get_x509: expected x509 serial INTEGER\n"); break; + } if(map_raw(map, obj.content, obj.size, x509.raw_serial)) break; if(map_sha1(map, obj.content, obj.size, x509.serial)) break; - if(asn1_expect_rsa(map, &obj.next, &tbs.size, &hashtype1)) /* algo - Ex: sha1WithRSAEncryption */ + if(asn1_expect_rsa(map, &obj.next, &tbs.size, &hashtype1)) { /* algo - Ex: sha1WithRSAEncryption */ + cli_dbgmsg("asn1_get_x509: unable to parse AlgorithmIdentifier\n"); break; + } if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, ASN1_TYPE_SEQUENCE)) /* issuer */ break; diff --git a/libclamav/clamav.h b/libclamav/clamav.h index d57def524..a8af79d00 100644 --- a/libclamav/clamav.h +++ b/libclamav/clamav.h @@ -578,6 +578,7 @@ extern int cl_scanmap_callback(cl_fmap_t *map, const char *filename, const char #define MD5_HASH_SIZE 16 #define SHA1_HASH_SIZE 20 #define SHA256_HASH_SIZE 32 +#define SHA384_HASH_SIZE 48 /** Generate a hash of data. @param[in] alg The hashing algorithm to use @@ -622,6 +623,15 @@ unsigned char *cl_hash_file_fp(FILE *fp, const char *alg, unsigned int *olen); */ unsigned char *cl_sha256(const void *buf, size_t len, unsigned char *obuf, unsigned int *olen); +/** Generate a sha384 hash of data + @param[in] buf The data to hash + @param[in] len The length of the to-be-hashed data + @param[out] obuf An optional pointer to store the generated hash. Use NULL to dynamically allocate buffer. + @param[out] olen An optional pointer that stores how long the generated hash is. + @return A pointer to the buffer that holds the generated hash + */ +unsigned char *cl_sha384(const void *buf, size_t len, unsigned char *obuf, unsigned int *olen); + /** Generate a sha1 hash of data @param[in] buf The data to hash @param[in] len The length of the to-be-hashed data diff --git a/libclamav/crtmgr.h b/libclamav/crtmgr.h index a2df4919a..3290223c0 100644 --- a/libclamav/crtmgr.h +++ b/libclamav/crtmgr.h @@ -26,7 +26,7 @@ #include "bignum.h" -typedef enum { CLI_SHA1RSA, CLI_MD5RSA, CLI_SHA256RSA } cli_crt_hashtype; +typedef enum { CLI_SHA1RSA, CLI_MD5RSA, CLI_SHA256RSA, CLI_SHA384RSA } cli_crt_hashtype; typedef enum {VRFY_CODE, VRFY_TIME} cli_vrfy_type; #define CRT_RAWMAXLEN 64 @@ -41,7 +41,7 @@ typedef struct cli_crt_t { /* tbshash holds the hash we'll use for verification with data in the sig, * so it must have at least enough space for the largest hash in * cli_crt_hashtype */ - uint8_t tbshash[SHA256_HASH_SIZE]; + uint8_t tbshash[SHA384_HASH_SIZE]; mp_int n; mp_int e; mp_int sig;