Browse Source

Add support for :
- PEM public key loading
- set/get KeyUsage in CSR and X.509
- set/get SKID in CSR and X.509
- set/get AKID in X.509
- set/get two Certificate Policies OID in X.509

Ludovic FLAMENT 8 years ago
parent
commit
d2ea6f7ef0

BIN
certs/1024/client-keyPub.der


BIN
certs/client-keyPub.der


BIN
certs/ecc-keyPub.der


+ 24 - 1
configure.ac

@@ -226,7 +226,7 @@ AC_ARG_ENABLE([bump],
 
 if test "$ENABLED_BUMP" = "yes"
 then
-    AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT"
+    AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT -DWOLFSSL_CERT_EXT"
 fi
 
 ENABLED_SLOWMATH="yes"
@@ -638,6 +638,23 @@ then
 fi
 
 
+# CERT REQUEST EXTENSION
+AC_ARG_ENABLE([certext],
+    [  --enable-certext        Enable cert request extensions (default: disabled)],
+    [ ENABLED_CERTEXT=$enableval ],
+    [ ENABLED_CERTEXT=no ]
+    )
+
+if test "$ENABLED_CERTEXT" = "yes"
+then
+    if test "$ENABLED_CERTEXT" = "no"
+    then
+        AC_MSG_ERROR([cannot enable certext without enabling certgen.])
+    fi
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT"
+fi
+
+
 # SEP
 AC_ARG_ENABLE([sep],
     [  --enable-sep            Enable sep extensions (default: disabled)],
@@ -1661,6 +1678,11 @@ then
         ENABLED_CERTREQ="yes"
         AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ"
     fi
+    if test "x$ENABLED_CERTEXT" = "xno"
+    then
+        ENABLED_CERTEXT="yes"
+        AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT"
+    fi
     if test "x$ENABLED_PKCS7" = "xno"
     then
         ENABLED_PKCS7="yes"
@@ -2348,6 +2370,7 @@ echo "   * BLAKE2:                    $ENABLED_BLAKE2"
 echo "   * keygen:                    $ENABLED_KEYGEN"
 echo "   * certgen:                   $ENABLED_CERTGEN"
 echo "   * certreq:                   $ENABLED_CERTREQ"
+echo "   * certext:                   $ENABLED_CERTEXT"
 echo "   * HC-128:                    $ENABLED_HC128"
 echo "   * RABBIT:                    $ENABLED_RABBIT"
 echo "   * CHACHA:                    $ENABLED_CHACHA"

+ 3 - 1
gencertbuf.pl

@@ -20,6 +20,7 @@ my $outputFile = "./wolfssl/certs_test.h";
 
 my @fileList_1024 = (
         [ "./certs/1024/client-key.der", "client_key_der_1024" ],
+        [ "./certs/1024/client-keyPub.der", "client_keypub_der_1024" ],
         [ "./certs/1024/client-cert.der", "client_cert_der_1024" ],
         [ "./certs/1024/dh1024.der", "dh_key_der_1024" ],
         [ "./certs/1024/dsa1024.der", "dsa_key_der_1024" ],
@@ -31,6 +32,7 @@ my @fileList_1024 = (
 
 my @fileList_2048 = (
         [ "./certs/client-key.der", "client_key_der_2048" ],
+        [ "./certs/client-keyPub.der", "client_keypub_der_2048" ],
         [ "./certs/client-cert.der", "client_cert_der_2048" ],
         [ "./certs/dh2048.der", "dh_key_der_2048" ],
         [ "./certs/dsa2048.der", "dsa_key_der_2048" ],
@@ -140,6 +142,6 @@ sub file_to_hex {
 
     print OUT_FILE "\n";
 
-    close($fp); 
+    close($fp);
 }
 

+ 111 - 9
src/ssl.c

@@ -1688,7 +1688,6 @@ int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz,
     return ret;
 }
 
-
 #endif /* !NO_CERTS */
 
 
@@ -2391,14 +2390,15 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
 
     switch (type) {
         case CA_TYPE:       /* same as below */
-        case CERT_TYPE:     header=BEGIN_CERT;     footer=END_CERT;     break;
-        case CRL_TYPE:      header=BEGIN_X509_CRL; footer=END_X509_CRL; break;
-        case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break;
-        case CERTREQ_TYPE:  header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break;
-        case DSA_TYPE:      header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break;
-        case ECC_TYPE:      header=BEGIN_EC_PRIV;  footer=END_EC_PRIV;  break;
-        case RSA_TYPE:      header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break;
-        default:            header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break;
+        case CERT_TYPE:      header=BEGIN_CERT;     footer=END_CERT;     break;
+        case CRL_TYPE:       header=BEGIN_X509_CRL; footer=END_X509_CRL; break;
+        case DH_PARAM_TYPE:  header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break;
+        case CERTREQ_TYPE:   header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break;
+        case DSA_TYPE:       header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break;
+        case ECC_TYPE:       header=BEGIN_EC_PRIV;  footer=END_EC_PRIV;  break;
+        case RSA_TYPE:       header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break;
+        case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY;  footer=END_PUB_KEY;  break;
+        default:             header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break;
     }
 
     switch (type) {
@@ -3968,6 +3968,108 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
 
 #endif /* WOLFSSL_CERT_GEN */
 
+#ifdef WOLFSSL_CERT_EXT
+/* load pem public key from file into der buffer, return der size or error */
+int wolfSSL_PemPubKeyToDer(const char* fileName,
+                           unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force XMALLOC */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  fileBuf = staticBuffer;
+    int    dynamic = 0;
+    int    ret     = 0;
+    long   sz      = 0;
+    XFILE  file    = XFOPEN(fileName, "rb");
+    buffer converted;
+
+    WOLFSSL_ENTER("wolfSSL_PemPubKeyToDer");
+
+    if (file == XBADFILE)
+        ret = SSL_BAD_FILE;
+    else {
+        XFSEEK(file, 0, XSEEK_END);
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz < 0) {
+            ret = SSL_BAD_FILE;
+        }
+        else if (sz > (long)sizeof(staticBuffer)) {
+            fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
+            if (fileBuf == NULL)
+                ret = MEMORY_E;
+            else
+                dynamic = 1;
+        }
+
+        converted.buffer = 0;
+
+        if (ret == 0) {
+            if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0)
+                ret = SSL_BAD_FILE;
+            else
+                ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
+                               0, NULL, NULL);
+
+            if (ret == 0) {
+                if (converted.length < (word32)derSz) {
+                    XMEMCPY(derBuf, converted.buffer, converted.length);
+                    ret = converted.length;
+                }
+                else
+                    ret = BUFFER_E;
+            }
+
+            XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA);
+        }
+
+        XFCLOSE(file);
+        if (dynamic)
+            XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
+    }
+
+    return ret;
+}
+
+/* Return bytes written to buff or < 0 for error */
+int wolfSSL_PubKeyPemToDer(const unsigned char* pem, int pemSz,
+                           unsigned char* buff, int buffSz)
+{
+    int     ret;
+    buffer  der;
+
+    WOLFSSL_ENTER("wolfSSL_PubKeyPemToDer");
+
+    if (pem == NULL || buff == NULL || buffSz <= 0) {
+        WOLFSSL_MSG("Bad pem der args");
+        return BAD_FUNC_ARG;
+    }
+
+    der.buffer = NULL;
+
+    ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL);
+    if (ret < 0) {
+        WOLFSSL_MSG("Bad Pem To Der");
+    }
+    else {
+        if (der.length <= (word32)buffSz) {
+            XMEMCPY(buff, der.buffer, der.length);
+            ret = der.length;
+        }
+        else {
+            WOLFSSL_MSG("Bad der length");
+            ret = BAD_FUNC_ARG;
+        }
+    }
+
+    XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY);
+    return ret;
+}
+
+#endif /* WOLFSSL_CERT_EXT */
 
 int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
                                      int format)

File diff suppressed because it is too large
+ 676 - 107
wolfcrypt/src/asn.c


+ 454 - 5
wolfcrypt/test/test.c

@@ -208,7 +208,9 @@ int pbkdf2_test(void);
     int pkcs7enveloped_test(void);
     int pkcs7signed_test(void);
 #endif
-
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)
+int  certext_test(void);
+#endif
 
 /* General big buffer size for many tests. */
 #define FOURK_BUF 4096
@@ -267,6 +269,17 @@ int wolfcrypt_test(void* args)
 #endif /* USE_FAST_MATH */
 #endif /* !NO_BIG_INT */
 
+    if ( (ret = rsa_test()) != 0)
+        return err_sys("RSA EXT test failed!\n", ret);
+    else
+        printf( "RSA EXT test passed!\n");
+
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)
+    if ( (ret = certext_test()) != 0)
+        return err_sys("CERT EXT test failed!\n", ret);
+    else
+        printf( "CERT EXT test passed!\n");
+#endif
 
 #ifndef NO_MD5
     if ( (ret = md5_test()) != 0)
@@ -3300,17 +3313,27 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
 
 #endif /* HAVE_NTRU */
 
+
 #ifndef NO_RSA
 
 #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
     #ifdef FREESCALE_MQX
         static const char* clientKey  = "a:\\certs\\client-key.der";
         static const char* clientCert = "a:\\certs\\client-cert.der";
+        #ifdef WOLFSSL_CERT_EXT
+            static const char* clientKeyPub  = "a:\\certs\\client-keyPub.der";
+        #endif
         #ifdef WOLFSSL_CERT_GEN
             static const char* caKeyFile  = "a:\\certs\\ca-key.der";
+            #ifdef WOLFSSL_CERT_EXT
+                static const char* caKeyPubFile  = "a:\\certs\\ca-keyPub.der";
+            #endif
             static const char* caCertFile = "a:\\certs\\ca-cert.pem";
             #ifdef HAVE_ECC
                 static const char* eccCaKeyFile  = "a:\\certs\\ecc-key.der";
+                #ifdef WOLFSSL_CERT_EXT
+                static const char* eccCaKeyPubFile = "a:\\certs\\ecc-keyPub.der";
+                #endif
                 static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem";
             #endif
         #endif
@@ -3319,13 +3342,25 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
         static char* clientCert = "certs/client-cert.der";
         void set_clientKey(char *key) {  clientKey = key ; }
         void set_clientCert(char *cert) {  clientCert = cert ; }
+        #ifdef WOLFSSL_CERT_EXT
+            static const char* clientKeyPub  = "certs/client-keyPub.der";
+            void set_clientKeyPub(char *key) { clientKeyPub = key ; }
+        #endif
         #ifdef WOLFSSL_CERT_GEN
             static char* caKeyFile  = "certs/ca-key.der";
+            #ifdef WOLFSSL_CERT_EXT
+            static const char* caKeyPubFile  = "certs/ca-keyPub.der";
+            void set_caKeyPubFile (char * key)  { caKeyPubFile = key ; }
+            #endif
             static char* caCertFile = "certs/ca-cert.pem";
             void set_caKeyFile (char * key)  { caKeyFile   = key ; }
             void set_caCertFile(char * cert) { caCertFile = cert ; }
             #ifdef HAVE_ECC
                 static const char* eccCaKeyFile  = "certs/ecc-key.der";
+                #ifdef WOLFSSL_CERT_EXT
+                static const char* eccCaKeyPubFile  = "certs/ecc-keyPub.der";
+                void set_eccCaKeyPubFile(char * key) { eccCaKeyPubFile = key ; }
+                #endif
                 static const char* eccCaCertFile = "certs/server-ecc.pem";
                 void set_eccCaKeyFile (char * key)  { eccCaKeyFile  = key ; }
                 void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; }
@@ -3334,11 +3369,17 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
     #else
         static const char* clientKey  = "./certs/client-key.der";
         static const char* clientCert = "./certs/client-cert.der";
+        #ifdef WOLFSSL_CERT_EXT
+            static const char* clientKeyPub  = "./certs/client-keyPub.der";
+        #endif
         #ifdef WOLFSSL_CERT_GEN
             static const char* caKeyFile  = "./certs/ca-key.der";
             static const char* caCertFile = "./certs/ca-cert.pem";
             #ifdef HAVE_ECC
                 static const char* eccCaKeyFile  = "./certs/ecc-key.der";
+                #ifdef WOLFSSL_CERT_EXT
+                static const char* eccCaKeyPubFile  = "./certs/ecc-keyPub.der";
+                #endif
                 static const char* eccCaCertFile = "./certs/server-ecc.pem";
             #endif
         #endif
@@ -3346,11 +3387,200 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
 #endif
 
 
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)
+int certext_test(void)
+{
+    DecodedCert cert;
+    byte*       tmp;
+    size_t      bytes;
+    FILE        *file;
+    int         ret;
+
+    /* created from rsa_test : othercert.der */
+    byte skid_rsa[]   = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54"
+                        "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0";
+
+    /* created from rsa_test : othercert.der */
+    byte akid_rsa[] = "\x27\x8E\x67\x11\x74\xC3\x26\x1D\x3F\xED"
+                      "\x33\x63\xB3\xA4\xD8\x1D\x30\xE5\xE8\xD5";
+
+    /* created from rsa_test : certecc.der */
+    byte akid_ecc[] = "\x5D\x5D\x26\xEF\xAC\x7E\x36\xF9\x9B\x76"
+                      "\x15\x2B\x4A\x25\x02\x23\xEF\xB2\x89\x30";
+
+    /* created from rsa_test : cert.der */
+    byte kid_ca[] = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54"
+                    "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0";
+
+    tmp = (byte*)malloc(FOURK_BUF);
+    if (tmp == NULL)
+        return -200;
+
+    /* load othercert.pem (Cert signed by an authority) */
+#ifdef FREESCALE_MQX
+    file = fopen("a:\\certs\\othercert.der", "rb");
+#else
+    file = fopen("./othercert.der", "rb");
+#endif
+    if (!file) {
+        free(tmp);
+        return -200;
+    }
+
+    bytes = fread(tmp, 1, FOURK_BUF, file);
+    fclose(file);
+
+    InitDecodedCert(&cert, tmp, (word32)bytes, 0);
+
+    ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0);
+    printf("ret = %d\n", ret);
+    if (ret != 0)
+        return -201;
+
+    /* check the SKID from a RSA certificate */
+    if (XMEMCMP(skid_rsa, cert.extSubjKeyId, cert.extSubjKeyIdSz))
+        return -202;
+
+    /* check the AKID from an RSA certificate */
+    if (XMEMCMP(akid_rsa, cert.extAuthKeyId, cert.extAuthKeyIdSz))
+        return -203;
+
+    /* check the Key Usage from an RSA certificate */
+    if (!cert.extKeyUsageSet)
+        return -204;
+
+    if (cert.extKeyUsage != (KEYUSE_KEY_ENCIPHER|KEYUSE_KEY_AGREE))
+        return -205;
+
+    /* check the CA Basic Constraints from an RSA certificate */
+    if (cert.isCA)
+        return -206;
+
+    /* check the Certificate Policies Id */
+    if (cert.extCertPoliciesNb != 1)
+        return -227;
+
+    if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23))
+        return -228;
+
+    FreeDecodedCert(&cert);
+
+
+    /* load certecc.pem (Cert signed by an authority) */
+#ifdef FREESCALE_MQX
+    file = fopen("a:\\certs\\certecc.der", "rb");
+#else
+    file = fopen("./certecc.der", "rb");
+#endif
+    if (!file) {
+        free(tmp);
+        return -210;
+    }
+
+    bytes = fread(tmp, 1, FOURK_BUF, file);
+    fclose(file);
+
+    InitDecodedCert(&cert, tmp, (word32)bytes, 0);
+
+    ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0);
+    if (ret != 0)
+        return -211;
+
+    /* check the SKID from a ECC certificate */
+    if (XMEMCMP(skid_rsa, cert.extSubjKeyId, cert.extSubjKeyIdSz))
+        return -212;
+
+    /* check the AKID from an ECC certificate */
+    if (XMEMCMP(akid_ecc, cert.extAuthKeyId, cert.extAuthKeyIdSz))
+        return -213;
+
+    /* check the Key Usage from an ECC certificate */
+    if (!cert.extKeyUsageSet)
+        return -214;
+
+    if (cert.extKeyUsage != (KEYUSE_DIGITAL_SIG|KEYUSE_CONTENT_COMMIT))
+        return -215;
+
+    /* check the CA Basic Constraints from an ECC certificate */
+    if (cert.isCA)
+        return -216;
+
+    /* check the Certificate Policies Id */
+    if (cert.extCertPoliciesNb != 2)
+        return -217;
+
+    if (strncmp(cert.extCertPolicies[0], "2.4.589440.587.101.2.1.9632587.1", 32))
+        return -218;
+
+    if (strncmp(cert.extCertPolicies[1], "1.2.13025.489.1.113549", 22))
+        return -219;
+
+    FreeDecodedCert(&cert);
+
+    /* load cert.pem (self signed certificate) */
+#ifdef FREESCALE_MQX
+    file = fopen("a:\\certs\\cert.der", "rb");
+#else
+    file = fopen("./cert.der", "rb");
+#endif
+    if (!file) {
+        free(tmp);
+        return -220;
+    }
+
+    bytes = fread(tmp, 1, FOURK_BUF, file);
+    fclose(file);
+
+    InitDecodedCert(&cert, tmp, (word32)bytes, 0);
+
+    ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0);
+    if (ret != 0)
+        return -221;
+
+    /* check the SKID from a CA certificate */
+    if (XMEMCMP(kid_ca, cert.extSubjKeyId, cert.extSubjKeyIdSz))
+        return -222;
+
+    /* check the AKID from an CA certificate */
+    if (XMEMCMP(kid_ca, cert.extAuthKeyId, cert.extAuthKeyIdSz))
+        return -223;
+
+    /* check the Key Usage from CA certificate */
+    if (!cert.extKeyUsageSet)
+        return -224;
+
+    if (cert.extKeyUsage != (KEYUSE_KEY_CERT_SIGN|KEYUSE_CRL_SIGN))
+        return -225;
+
+    /* check the CA Basic Constraints CA certificate */
+    if (!cert.isCA)
+        return -226;
+
+    /* check the Certificate Policies Id */
+    if (cert.extCertPoliciesNb != 2)
+        return -227;
+
+    if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23))
+        return -228;
+
+    if (strncmp(cert.extCertPolicies[1], "1.2.840.113549.1.9.16.6.5", 25))
+        return -229;
+
+    FreeDecodedCert(&cert);
+
+    return 0;
+}
+#endif /* defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) */
+
+
 int rsa_test(void)
 {
     byte*   tmp;
     size_t bytes;
     RsaKey key;
+#ifdef WOLFSSL_CERT_EXT
+    RsaKey keypub;
+#endif
     WC_RNG rng;
     word32 idx = 0;
     int    ret;
@@ -3359,7 +3589,7 @@ int rsa_test(void)
     byte   out[256];
     byte   plain[256];
 #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
-    FILE*  file, * file2;
+    FILE    *file, *file2;
 #endif
 #ifdef WOLFSSL_TEST_CERT
     DecodedCert cert;
@@ -3473,6 +3703,42 @@ int rsa_test(void)
     (void)bytes;
 #endif
 
+#ifdef WOLFSSL_CERT_EXT
+
+#ifdef USE_CERT_BUFFERS_1024
+    XMEMCPY(tmp, client_keypub_der_1024, sizeof_client_keypub_der_1024);
+    bytes = sizeof_client_keypub_der_1024;
+#elif defined(USE_CERT_BUFFERS_2048)
+    XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048);
+    bytes = sizeof_client_keypub_der_2048;
+#else
+    file = fopen(clientKeyPub, "rb");
+    if (!file) {
+        err_sys("can't open ./certs/client-keyPub.der, "
+                "Please run from wolfSSL home dir", -40);
+        free(tmp);
+        return -50;
+    }
+
+    bytes = fread(tmp, 1, FOURK_BUF, file);
+    fclose(file);
+#endif /* USE_CERT_BUFFERS */
+
+    ret = wc_InitRsaKey(&keypub, 0);
+    if (ret != 0) {
+        free(tmp);
+        return -51;
+    }
+    idx = 0;
+
+    ret = wc_RsaPublicKeyDecode(tmp, &idx, &keypub, (word32)bytes);
+    if (ret != 0) {
+        free(tmp);
+        wc_FreeRsaKey(&keypub);
+        return -52;
+    }
+#endif /* WOLFSSL_CERT_EXT */
+
 #ifdef WOLFSSL_KEY_GEN
     {
         byte*  der;
@@ -3634,6 +3900,39 @@ int rsa_test(void)
         myCert.isCA    = 1;
         myCert.sigType = CTC_SHA256wRSA;
 
+#ifdef WOLFSSL_CERT_EXT
+        /* add Policies */
+        strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42",
+                CTC_MAX_CERTPOL_SZ);
+        strncpy(myCert.certPolicies[1], "1.2.840.113549.1.9.16.6.5",
+                CTC_MAX_CERTPOL_SZ);
+        myCert.certPoliciesNb = 2;
+
+        /* add SKID from the Public Key */
+        if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -399;
+        }
+
+         /* add AKID from the Public Key */
+         if (wc_SetAuthKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+             return -399;
+        }
+
+        /* add Key Usage */
+        if (wc_SetKeyUsage(&myCert,"cRLSign,keyCertSign") != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -400;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+
         certSz = wc_MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng);
         if (certSz < 0) {
             free(derCert);
@@ -3775,6 +4074,37 @@ int rsa_test(void)
         strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE);
         strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE);
 
+#ifdef WOLFSSL_CERT_EXT
+        /* add Policies */
+        strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42",
+                CTC_MAX_CERTPOL_SZ);
+        myCert.certPoliciesNb =1;
+
+        /* add SKID from the Public Key */
+        if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -399;
+        }
+
+        /* add AKID from the CA certificate */
+        if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -399;
+        }
+
+        /* add Key Usage */
+        if (wc_SetKeyUsage(&myCert,"keyEncipherment,keyAgreement") != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -400;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+
         ret = wc_SetIssuer(&myCert, caCertFile);
         if (ret < 0) {
             free(derCert);
@@ -3803,7 +4133,6 @@ int rsa_test(void)
             return -408;
         }
 
-
 #ifdef WOLFSSL_TEST_CERT
         InitDecodedCert(&decode, derCert, certSz, 0);
         ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0);
@@ -3887,6 +4216,9 @@ int rsa_test(void)
         size_t      bytes3;
         word32      idx3 = 0;
         FILE*       file3;
+#ifdef WOLFSSL_CERT_EXT
+        ecc_key     caKeyPub;
+#endif
 #ifdef WOLFSSL_TEST_CERT
         DecodedCert decode;
 #endif
@@ -3935,6 +4267,72 @@ int rsa_test(void)
         strncpy(myCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
         strncpy(myCert.subject.email, "info@wolfssl.com", CTC_NAME_SIZE);
 
+#ifdef WOLFSSL_CERT_EXT
+        /* add Policies */
+        strncpy(myCert.certPolicies[0], "2.4.589440.587.101.2.1.9632587.1",
+                CTC_MAX_CERTPOL_SZ);
+        strncpy(myCert.certPolicies[1], "1.2.13025.489.1.113549",
+                CTC_MAX_CERTPOL_SZ);
+        myCert.certPoliciesNb = 2;
+
+
+        file3 = fopen(eccCaKeyPubFile, "rb");
+        if (!file3) {
+            free(derCert);
+            free(pem);
+            free(tmp);
+            return -5500;
+        }
+
+        bytes3 = fread(tmp, 1, FOURK_BUF, file3);
+        fclose(file3);
+
+        wc_ecc_init(&caKeyPub);
+        if (ret != 0) {
+            free(derCert);
+            free(pem);
+            free(tmp);
+            return -5501;
+        }
+
+        idx3 = 0;
+        ret = wc_EccPublicKeyDecode(tmp, &idx3, &caKeyPub, (word32)bytes3);
+        if (ret != 0) {
+            free(derCert);
+            free(pem);
+            free(tmp);
+            wc_ecc_free(&caKeyPub);
+            return -5502;
+        }
+
+        /* add SKID from the Public Key */
+        if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            wc_ecc_free(&caKeyPub);
+            return -5503;
+        }
+
+        /* add AKID from the Public Key */
+        if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caKeyPub) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            wc_ecc_free(&caKeyPub);
+            return -5504;
+        }
+        wc_ecc_free(&caKeyPub);
+
+        /* add Key Usage */
+        if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation") != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -5505;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+
         ret = wc_SetIssuer(&myCert, eccCaCertFile);
         if (ret < 0) {
             free(pem);
@@ -3944,7 +4342,7 @@ int rsa_test(void)
             return -5405;
         }
 
-        certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, NULL, &caKey, &rng);
+        certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng);
         if (certSz < 0) {
             free(pem);
             free(derCert);
@@ -4045,7 +4443,7 @@ int rsa_test(void)
         FILE*       ntruPrivFile;
         int         certSz;
         int         pemSz;
-        word32      idx3;
+        word32      idx3 = 0;
 #ifdef WOLFSSL_TEST_CERT
         DecodedCert decode;
 #endif
@@ -4144,6 +4542,35 @@ int rsa_test(void)
         strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE);
         strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE);
 
+#ifdef WOLFSSL_CERT_EXT
+
+        /* add SKID from the Public Key */
+        if (wc_SetSubjectKeyIdFromNtruPublicKey(&myCert, public_key,
+                                                public_key_len) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -496;
+        }
+
+        /* add AKID from the CA certificate */
+        if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -495;
+        }
+
+        /* add Key Usage */
+        if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation,"
+                                   "keyEncipherment,keyAgreement") != 0) {
+            free(pem);
+            free(derCert);
+            free(tmp);
+            return -494;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+
         ret = wc_SetIssuer(&myCert, caCertFile);
         if (ret < 0) {
             free(derCert);
@@ -4279,6 +4706,25 @@ int rsa_test(void)
         strncpy(req.subject.email, "info@yassl.com", CTC_NAME_SIZE);
         req.sigType = CTC_SHA256wRSA;
 
+#ifdef WOLFSSL_CERT_EXT
+        /* add SKID from the Public Key */
+        if (wc_SetSubjectKeyIdFromPublicKey(&req, &keypub, NULL) != 0) {
+            free(pem);
+            free(der);
+            free(tmp);
+            return -496;
+        }
+
+        /* add Key Usage */
+        if (wc_SetKeyUsage(&req,"digitalSignature,nonRepudiation,"
+                                "keyEncipherment,keyAgreement") != 0) {
+            free(pem);
+            free(der);
+            free(tmp);
+            return -494;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+
         derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL);
         if (derSz < 0) {
             free(pem);
@@ -4352,6 +4798,9 @@ int rsa_test(void)
 #endif /* WOLFSSL_CERT_GEN */
 
     wc_FreeRsaKey(&key);
+#ifdef WOLFSSL_CERT_EXT
+    wc_FreeRsaKey(&keypub);
+#endif
 #ifdef HAVE_CAVIUM
     wc_RsaFreeCavium(&key);
 #endif

+ 10 - 5
wolfssl/ssl.h

@@ -1069,11 +1069,16 @@ WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version);
 WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version);
 WOLFSSL_API int wolfSSL_GetObjectSize(void);  /* object size based on build */
 WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version);
-WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int sz, unsigned char*,
-                                  int, const char*);
-WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int sz, unsigned char*,
-                                   int, int);
-
+WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int,
+                                    unsigned char*, int, const char*);
+WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int,
+                                     unsigned char*, int, int);
+#ifdef WOLFSSL_CERT_EXT
+WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName,
+                                       unsigned char* derBuf, int derSz);
+WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int,
+                                       unsigned char*, int);
+#endif /* WOLFSSL_CERT_EXT */
 typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
 typedef void (*CbMissingCRL)(const char* url);
 typedef int  (*CbOCSPIO)(void*, const char*, int,

+ 30 - 10
wolfssl/wolfcrypt/asn.h

@@ -172,12 +172,20 @@ enum Misc_ASN {
         MAX_ATTRIB_SZ   = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 +
                           MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */
     #endif
-    #ifdef WOLFSSL_ALT_NAMES
+    #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT)
         MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE,
     #else
         MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + MAX_CA_SZ,
     #endif
                                    /* Max total extensions, id + len + others */
+#endif
+#ifdef WOLFSSL_CERT_EXT
+    MAX_KID_SZ			= 45,	   /* Max encoded KID length (SHA-256 case) */
+    MAX_KEYUSAGE_SZ     = 18,      /* Max encoded Key Usage length */
+    MAX_OID_SZ          = 32,      /* Max DER length of OID*/
+    MAX_OID_STRING_SZ   = 64,      /* Max string length representation of OID*/
+    MAX_CERTPOL_NB      = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */
+    MAX_CERTPOL_SZ      = CTC_MAX_CERTPOL_SZ,
 #endif
     MAX_OCSP_EXT_SZ     = 58,      /* Max OCSP Extension length */
     MAX_OCSP_NONCE_SZ   = 18,      /* OCSP Nonce size           */
@@ -277,17 +285,23 @@ enum VerifyType {
     VERIFY    = 1
 };
 
+#ifdef WOLFSSL_CERT_EXT
+enum KeyIdType {
+    SKID_TYPE = 0,
+    AKID_TYPE = 1
+};
+#endif
 
 /* Key usage extension bits */
-#define KEYUSE_DIGITAL_SIG    0x0100
-#define KEYUSE_CONTENT_COMMIT 0x0080
-#define KEYUSE_KEY_ENCIPHER   0x0040
-#define KEYUSE_DATA_ENCIPHER  0x0020
-#define KEYUSE_KEY_AGREE      0x0010
-#define KEYUSE_KEY_CERT_SIGN  0x0008
-#define KEYUSE_CRL_SIGN       0x0004
-#define KEYUSE_ENCIPHER_ONLY  0x0002
-#define KEYUSE_DECIPHER_ONLY  0x0001
+#define KEYUSE_DIGITAL_SIG    0x0080
+#define KEYUSE_CONTENT_COMMIT 0x0040
+#define KEYUSE_KEY_ENCIPHER   0x0020
+#define KEYUSE_DATA_ENCIPHER  0x0010
+#define KEYUSE_KEY_AGREE      0x0008
+#define KEYUSE_KEY_CERT_SIGN  0x0004
+#define KEYUSE_CRL_SIGN       0x0002
+#define KEYUSE_ENCIPHER_ONLY  0x0001
+#define KEYUSE_DECIPHER_ONLY  0x8000
 
 #define EXTKEYUSE_ANY         0x08
 #define EXTKEYUSE_OCSP_SIGN   0x04
@@ -475,6 +489,10 @@ struct DecodedCert {
         byte    extCertPolicyCrit;
     #endif /* OPENSSL_EXTRA */
 #endif /* WOLFSSL_SEP */
+#ifdef WOLFSSL_CERT_EXT
+    char    extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
+    int     extCertPoliciesNb;
+#endif /* WOLFSSL_CERT_EXT */
 };
 
 extern const char* BEGIN_CERT;
@@ -495,6 +513,8 @@ extern const char* BEGIN_EC_PRIV;
 extern const char* END_EC_PRIV;
 extern const char* BEGIN_DSA_PRIV;
 extern const char* END_DSA_PRIV;
+extern const char* BEGIN_PUB_KEY;
+extern const char* END_PUB_KEY;
 
 #ifdef NO_SHA
     #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE

+ 68 - 7
wolfssl/wolfcrypt/asn_public.h

@@ -47,7 +47,10 @@ enum CertType {
     CERTREQ_TYPE,
     DSA_TYPE,
     ECC_TYPE,
-    RSA_TYPE
+    RSA_TYPE,
+    PUBLICKEY_TYPE,
+    RSA_PUBLICKEY_TYPE,
+    ECC_PUBLICKEY_TYPE
 };
 
 
@@ -79,10 +82,18 @@ enum Ctc_Encoding {
 #endif
 
 enum Ctc_Misc {
-    CTC_NAME_SIZE    =    64,
-    CTC_DATE_SIZE    =    32,
-    CTC_MAX_ALT_SIZE = 16384,   /* may be huge */
-    CTC_SERIAL_SIZE  =     8
+    CTC_NAME_SIZE     =    64,
+    CTC_DATE_SIZE     =    32,
+    CTC_MAX_ALT_SIZE  = 16384,   /* may be huge */
+    CTC_SERIAL_SIZE   =     8,
+#ifdef WOLFSSL_CERT_EXT
+    /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum
+     * We support only hash */
+    CTC_MAX_SKID_SIZE = SHA256_DIGEST_SIZE,
+    CTC_MAX_AKID_SIZE = SHA256_DIGEST_SIZE,
+    CTC_MAX_CERTPOL_SZ = 64,
+    CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */
+#endif /* WOLFSSL_CERT_EXT */
 };
 
 typedef struct CertName {
@@ -125,6 +136,15 @@ typedef struct Cert {
     byte     afterDate[CTC_DATE_SIZE];   /* after date copy */
     int      afterDateSz;                /* size of copy */
 #endif
+#ifdef WOLFSSL_CERT_EXT
+    byte    skid[CTC_MAX_SKID_SIZE];     /* Subject Key Identifier */
+    int     skidSz;                      /* SKID size in bytes */
+    byte    akid[CTC_MAX_AKID_SIZE];     /* Authority Key Identifier */
+    int     akidSz;                      /* AKID size in bytes */
+    word16  keyUsage;                    /* Key Usage */
+    char    certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ];
+    word16  certPoliciesNb;              /* Number of Cert Policy */
+#endif
 #ifdef WOLFSSL_CERT_REQ
     char     challengePw[CTC_NAME_SIZE];
 #endif
@@ -168,6 +188,43 @@ WOLFSSL_API int  wc_SetSubjectBuffer(Cert*, const byte*, int);
 WOLFSSL_API int  wc_SetAltNamesBuffer(Cert*, const byte*, int);
 WOLFSSL_API int  wc_SetDatesBuffer(Cert*, const byte*, int);
 
+#ifdef WOLFSSL_CERT_EXT
+WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
+                                             ecc_key *eckey);
+WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz);
+WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file);
+WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
+                                                ecc_key *eckey);
+WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file);
+
+#ifdef HAVE_NTRU
+WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey,
+                                                    word16 ntruKeySz);
+#endif
+
+/* Set the KeyUsage.
+ * Value is a string separated tokens with ','. Accepted tokens are :
+ * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign,
+ * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly.
+ *
+ * nonRepudiation and contentCommitment are for the same usage.
+ */
+WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value);
+
+/* encode Certificate Policies, return total bytes written
+ * each input value must be ITU-T X.690 formatted : a.b.c...
+ * input must be an array of values with a NULL terminated for the latest
+ * RFC5280 : non-critical */
+WOLFSSL_API int wc_SetCertificatePolicies(Cert *cert, const char **input);
+
+/* forward from wolfssl */
+WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName,
+                                       unsigned char* derBuf, int derSz);
+/* forward from wolfssl */
+WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int,
+                                       unsigned char*, int);
+#endif /* WOLFSSL_CERT_EXT */
+
     #ifdef HAVE_NTRU
         WOLFSSL_API int  wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz,
                                      const byte* ntruKey, word16 keySz,
@@ -186,9 +243,13 @@ WOLFSSL_API int  wc_SetDatesBuffer(Cert*, const byte*, int);
 
 #ifdef HAVE_ECC
     /* private key helpers */
-    WOLFSSL_API int wc_EccPrivateKeyDecode(const byte* input,word32* inOutIdx,
-                                         ecc_key*,word32);
+    WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,
+                                           ecc_key*, word32);
     WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen);
+
+    /* public key helper */
+    WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,
+                                              ecc_key*, word32);
 #endif
 
 /* DER encode signature */

+ 8 - 0
wolfssl/wolfcrypt/error-crypt.h

@@ -155,6 +155,14 @@ enum {
     SRP_VERIFY_E        = -218,  /* SRP proof verification failed. */
     SRP_BAD_KEY_E       = -219,  /* SRP bad ephemeral values. */
 
+    ASN_NO_SKID         = -220,  /* ASN no Subject Key Identifier found */
+    ASN_NO_AKID         = -221,  /* ASN no Authority Key Identifier found */
+    ASN_NO_KEYUSAGE     = -223,  /* ASN no Key Usage found */
+    SKID_E              = -224,  /* setting Subject Key Identifier error */
+    AKID_E              = -225,  /* setting Authority Key Identifier error */
+    KEYUSAGE_E          = -226,  /* Bad Key Usage value */
+    CERTPOLICIES_E      = -227,  /* setting Certificate Policies error */
+
     MIN_CODE_E          = -300   /* errors -101 - -299 */
 };
 

+ 4 - 0
wolfssl/wolfcrypt/logging.h

@@ -25,6 +25,10 @@
 #ifndef WOLFSSL_LOGGING_H
 #define WOLFSSL_LOGGING_H
 
+#ifdef DEBUG_WOLFSSL
+#include <stdio.h>
+#endif
+
 #include <wolfssl/wolfcrypt/types.h>
 
 #ifdef __cplusplus

+ 1 - 0
wolfssl/wolfcrypt/types.h

@@ -190,6 +190,7 @@
 
 	#ifndef STRING_USER
 	    #include <string.h>
+        #include <stdio.h> /* for snprintf */
 	    char* mystrnstr(const char* s1, const char* s2, unsigned int n);
 
 	    #define XMEMCPY(d,s,l)    memcpy((d),(s),(l))

Some files were not shown because too many files changed in this diff