diff --git a/src/x509.c b/src/x509.c index 46dfd38ed4..39d12c80c5 100644 --- a/src/x509.c +++ b/src/x509.c @@ -11711,14 +11711,33 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_sk_X509_OBJECT_deep_copy( cert->isCA = req->isCa; cert->basicConstSet = req->basicConstSet; #ifdef WOLFSSL_CERT_EXT - if (req->subjKeyIdSz != 0) { - XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz); - cert->skidSz = (int)req->subjKeyIdSz; + if (req->subjKeyIdSz > CTC_MAX_SKID_SIZE) { + WOLFSSL_MSG("Subject Key ID too large"); + WOLFSSL_ERROR_VERBOSE(BUFFER_E); + cert->skidSz = 0; + ret = WOLFSSL_FAILURE; + } + else if (req->subjKeyIdSz > 0) { + if (req->subjKeyId == NULL) { + WOLFSSL_MSG("Subject Key ID missing"); + WOLFSSL_ERROR_VERBOSE(BAD_FUNC_ARG); + cert->skidSz = 0; + ret = WOLFSSL_FAILURE; + } + else { + XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz); + cert->skidSz = (int)req->subjKeyIdSz; + } + } + else { + cert->skidSz = 0; } - if (req->keyUsageSet) - cert->keyUsage = req->keyUsage; + if (ret == WOLFSSL_SUCCESS) { + if (req->keyUsageSet) + cert->keyUsage = req->keyUsage; - cert->extKeyUsage = req->extKeyUsage; + cert->extKeyUsage = req->extKeyUsage; + } #endif XMEMCPY(cert->challengePw, req->challengePw, CTC_NAME_SIZE); diff --git a/tests/api/test_x509.c b/tests/api/test_x509.c index 47780e6dc4..f6863c7853 100644 --- a/tests/api/test_x509.c +++ b/tests/api/test_x509.c @@ -875,3 +875,182 @@ int test_x509_CertFromX509_akid_overflow(void) #endif return EXPECT_RESULT(); } + +/* Test that ReqCertFromX509 rejects an oversized SubjectKeyIdentifier + * extension when re-encoding a parsed CSR. */ +int test_x509_ReqCertFromX509_skid_overflow(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) && !defined(NO_BIO) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) +#ifdef WOLFSSL_SMALL_STACK + unsigned char* buf = NULL; +#else + unsigned char buf[16384]; +#endif + size_t pos = 0; + WOLFSSL_X509* req = NULL; + WOLFSSL_BIO* bio = NULL; + unsigned char* der = NULL; + +#ifdef WOLFSSL_SMALL_STACK + buf = (unsigned char*)XMALLOC(16384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ExpectNotNull(buf); + if (buf == NULL) + return EXPECT_RESULT(); +#endif + + #define PUT1(b) do { buf[pos++] = (b); } while(0) + #define PUTN(p, n) do { XMEMCPY(buf + pos, (p), (n)); pos += (n); } while(0) + + #define TLV_HDR(tag, n, out, hlen) do { \ + size_t _i = 0; \ + (out)[_i++] = (tag); \ + if ((n) < 0x80u) { (out)[_i++] = (unsigned char)(n); } \ + else if ((n) < 0x100u) { (out)[_i++] = 0x81; \ + (out)[_i++] = (unsigned char)(n); } \ + else if ((n) < 0x10000u) { (out)[_i++] = 0x82; \ + (out)[_i++] = (unsigned char)((n)>>8); \ + (out)[_i++] = (unsigned char)(n); } \ + (hlen) = _i; \ + } while(0) + + #define WRAP(start, tag) do { \ + size_t _len = pos - (start); \ + unsigned char _hdr[6]; size_t _hlen; \ + TLV_HDR((tag), _len, _hdr, _hlen); \ + XMEMMOVE(buf + (start) + _hlen, buf + (start), _len); \ + XMEMCPY(buf + (start), _hdr, _hlen); \ + pos += _hlen; \ + } while(0) + + { + size_t req_start = pos; + size_t s; + int i; + + /* CertificationRequestInfo */ + s = pos; + /* version = v1 */ + PUT1(0x02); PUT1(0x01); PUT1(0x00); + + /* subject: CN=A */ + { + size_t name = pos, rdn = pos, atv = pos; + unsigned char cn[] = {0x06,0x03,0x55,0x04,0x03}; + PUTN(cn, sizeof(cn)); + PUT1(0x0C); PUT1(0x01); PUT1('A'); + WRAP(atv, 0x30); + WRAP(rdn, 0x31); + WRAP(name, 0x30); + } + + /* subjectPublicKeyInfo: EC P-256 with generator point */ + { + size_t spki = pos, alg = pos, bs; + unsigned char ecpk[] = {0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x02,0x01}; + unsigned char p256[] = {0x06,0x08,0x2A,0x86,0x48,0xCE, + 0x3D,0x03,0x01,0x07}; + static const unsigned char p256G[64] = { + 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47, + 0xF8,0xBC,0xE6,0xE5,0x63,0xA4,0x40,0xF2, + 0x77,0x03,0x7D,0x81,0x2D,0xEB,0x33,0xA0, + 0xF4,0xA1,0x39,0x45,0xD8,0x98,0xC2,0x96, + 0x4F,0xE3,0x42,0xE2,0xFE,0x1A,0x7F,0x9B, + 0x8E,0xE7,0xEB,0x4A,0x7C,0x0F,0x9E,0x16, + 0x2B,0xCE,0x33,0x57,0x6B,0x31,0x5E,0xCE, + 0xCB,0xB6,0x40,0x68,0x37,0xBF,0x51,0xF5 + }; + PUTN(ecpk, sizeof(ecpk)); + PUTN(p256, sizeof(p256)); + WRAP(alg, 0x30); + bs = pos; + PUT1(0x00); + PUT1(0x04); + PUTN(p256G, sizeof(p256G)); + WRAP(bs, 0x03); + WRAP(spki, 0x30); + } + + /* attributes [0]: extensionRequest(subjectKeyIdentifier) */ + { + size_t attrs = pos, attr = pos, values, exts; + size_t ext, extVal, skid; + unsigned char extReqOid[] = {0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x09,0x0E}; + unsigned char skidOid[] = {0x06,0x03,0x55,0x1D,0x0E}; + + PUTN(extReqOid, sizeof(extReqOid)); + values = pos; + exts = pos; + ext = pos; + PUTN(skidOid, sizeof(skidOid)); + extVal = pos; + skid = pos; + for (i = 0; i < CTC_MAX_SKID_SIZE + 1; i++) { + PUT1((unsigned char)(0x41 + (i % 16))); + } + WRAP(skid, 0x04); + WRAP(extVal, 0x04); + WRAP(ext, 0x30); + WRAP(exts, 0x30); + WRAP(values, 0x31); + WRAP(attr, 0x30); + WRAP(attrs, 0xA0); + } + WRAP(s, 0x30); + + /* signatureAlgorithm: ecdsa-with-SHA256 */ + s = pos; + { + unsigned char oid[] = {0x06,0x08,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x03,0x02}; + PUTN(oid, sizeof(oid)); + } + WRAP(s, 0x30); + + /* signatureValue: parser does not verify this for the regression */ + s = pos; + { + size_t sig; + + PUT1(0x00); + sig = pos; + PUT1(0x02); PUT1(0x01); PUT1(0x01); + PUT1(0x02); PUT1(0x01); PUT1(0x01); + WRAP(sig, 0x30); + } + WRAP(s, 0x03); + WRAP(req_start, 0x30); + } + + req = wolfSSL_X509_REQ_d2i(NULL, buf, (int)pos); + ExpectNotNull(req); + if (req != NULL) { + ExpectIntEQ((int)req->subjKeyIdSz, CTC_MAX_SKID_SIZE + 1); + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + ExpectNotNull(bio); + if ((req != NULL) && (bio != NULL)) { + ExpectIntEQ(wolfSSL_i2d_X509_REQ_bio(bio, req), WOLFSSL_FAILURE); + ExpectIntEQ(wolfSSL_i2d_X509_REQ(req, &der), + WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); + ExpectNull(der); + } + + wolfSSL_BIO_free(bio); + wolfSSL_X509_free(req); +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + #undef PUT1 + #undef PUTN + #undef TLV_HDR + #undef WRAP +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_x509.h b/tests/api/test_x509.h index adbc980f8b..ffeae91e50 100644 --- a/tests/api/test_x509.h +++ b/tests/api/test_x509.h @@ -28,6 +28,7 @@ int test_x509_set_serialNumber(void); int test_x509_verify_cert_hostname_check(void); int test_x509_time_field_overread_via_tls(void); int test_x509_CertFromX509_akid_overflow(void); +int test_x509_ReqCertFromX509_skid_overflow(void); #define TEST_X509_DECLS \ TEST_DECL_GROUP("x509", test_x509_rfc2818_verification_callback), \ @@ -35,6 +36,7 @@ int test_x509_CertFromX509_akid_overflow(void); TEST_DECL_GROUP("x509", test_x509_set_serialNumber), \ TEST_DECL_GROUP("x509", test_x509_verify_cert_hostname_check), \ TEST_DECL_GROUP("x509", test_x509_time_field_overread_via_tls), \ - TEST_DECL_GROUP("x509", test_x509_CertFromX509_akid_overflow) + TEST_DECL_GROUP("x509", test_x509_CertFromX509_akid_overflow), \ + TEST_DECL_GROUP("x509", test_x509_ReqCertFromX509_skid_overflow) #endif /* WOLFCRYPT_TEST_X509_H */