Browse Source

ecc client certs

toddouska 12 years ago
parent
commit
1c2b84d3dd
6 changed files with 162 additions and 24 deletions
  1. 54 0
      certs/client-ecc-cert.pem
  2. 9 0
      certs/ecc-client-key.pem
  3. 2 0
      cyassl/test.h
  4. 12 0
      examples/client/client.c
  5. 4 0
      examples/server/server.c
  6. 81 24
      src/internal.c

+ 54 - 0
certs/client-ecc-cert.pem

@@ -0,0 +1,54 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            bf:cc:cb:7a:0a:07:42:82
+        Signature Algorithm: ecdsa-with-SHA1
+        Issuer: C=US, ST=Oregon, L=Salem, O=Client ECC, OU=Fast, CN=www.yassl.com/emailAddress=info@yassl.com
+        Validity
+            Not Before: May  1 23:51:33 2012 GMT
+            Not After : Jan 26 23:51:33 2015 GMT
+        Subject: C=US, ST=Oregon, L=Salem, O=Client ECC, OU=Fast, CN=www.yassl.com/emailAddress=info@yassl.com
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+            EC Public Key:
+                pub: 
+                    04:55:bf:f4:0f:44:50:9a:3d:ce:9b:b7:f0:c5:4d:
+                    f5:70:7b:d4:ec:24:8e:19:80:ec:5a:4c:a2:24:03:
+                    62:2c:9b:da:ef:a2:35:12:43:84:76:16:c6:56:95:
+                    06:cc:01:a9:bd:f6:75:1a:42:f7:bd:a9:b2:36:22:
+                    5f:c7:5d:7f:b4
+                ASN1 OID: prime256v1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                EB:D4:4B:59:6B:95:61:3F:51:57:B6:04:4D:89:41:88:44:5C:AB:F2
+            X509v3 Authority Key Identifier: 
+                keyid:EB:D4:4B:59:6B:95:61:3F:51:57:B6:04:4D:89:41:88:44:5C:AB:F2
+                DirName:/C=US/ST=Oregon/L=Salem/O=Client ECC/OU=Fast/CN=www.yassl.com/emailAddress=info@yassl.com
+                serial:BF:CC:CB:7A:0A:07:42:82
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: ecdsa-with-SHA1
+        30:44:02:20:26:08:44:95:35:2e:fa:9d:20:01:a6:79:60:ed:
+        35:a7:0a:dd:7a:0e:75:c5:80:d2:0b:9f:6a:90:d6:31:76:75:
+        02:20:2d:87:a2:bb:d5:e2:42:61:35:19:59:40:1d:fd:71:4f:
+        28:65:96:99:e6:85:1b:09:ad:d4:58:71:56:63:0b:c7
+-----BEGIN CERTIFICATE-----
+MIIC+jCCAqKgAwIBAgIJAL/My3oKB0KCMAkGByqGSM49BAEwgYkxCzAJBgNVBAYT
+AlVTMQ8wDQYDVQQIEwZPcmVnb24xDjAMBgNVBAcTBVNhbGVtMRMwEQYDVQQKEwpD
+bGllbnQgRUNDMQ0wCwYDVQQLEwRGYXN0MRYwFAYDVQQDEw13d3cueWFzc2wuY29t
+MR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0xMjA1MDEyMzUxMzNa
+Fw0xNTAxMjYyMzUxMzNaMIGJMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29u
+MQ4wDAYDVQQHEwVTYWxlbTETMBEGA1UEChMKQ2xpZW50IEVDQzENMAsGA1UECxME
+RmFzdDEWMBQGA1UEAxMNd3d3Lnlhc3NsLmNvbTEdMBsGCSqGSIb3DQEJARYOaW5m
+b0B5YXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARVv/QPRFCaPc6b
+t/DFTfVwe9TsJI4ZgOxaTKIkA2Ism9rvojUSQ4R2FsZWlQbMAam99nUaQve9qbI2
+Il/HXX+0o4HxMIHuMB0GA1UdDgQWBBTr1EtZa5VhP1FXtgRNiUGIRFyr8jCBvgYD
+VR0jBIG2MIGzgBTr1EtZa5VhP1FXtgRNiUGIRFyr8qGBj6SBjDCBiTELMAkGA1UE
+BhMCVVMxDzANBgNVBAgTBk9yZWdvbjEOMAwGA1UEBxMFU2FsZW0xEzARBgNVBAoT
+CkNsaWVudCBFQ0MxDTALBgNVBAsTBEZhc3QxFjAUBgNVBAMTDXd3dy55YXNzbC5j
+b20xHTAbBgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tggkAv8zLegoHQoIwDAYD
+VR0TBAUwAwEB/zAJBgcqhkjOPQQBA0cAMEQCICYIRJU1LvqdIAGmeWDtNacK3XoO
+dcWA0gufapDWMXZ1AiAth6K71eJCYTUZWUAd/XFPKGWWmeaFGwmt1FhxVmMLxw==
+-----END CERTIFICATE-----

+ 9 - 0
certs/ecc-client-key.pem

@@ -0,0 +1,9 @@
+ASN1 OID: prime256v1
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPjPkmu9HijxqKuhI08ydBiIUK1+x+yS+I+XTa9WiWXHoAoGCCqGSM49
+AwEHoUQDQgAEVb/0D0RQmj3Om7fwxU31cHvU7CSOGYDsWkyiJANiLJva76I1EkOE
+dhbGVpUGzAGpvfZ1GkL3vamyNiJfx11/tA==
+-----END EC PRIVATE KEY-----

+ 2 - 0
cyassl/test.h

@@ -107,6 +107,8 @@ static const char* cliKey   = "./certs/client-key.pem";
 static const char* ntruCert = "./certs/ntru-cert.pem";
 static const char* ntruKey  = "./certs/ntru-key.raw";
 static const char* dhParam  = "./certs/dh2048.pem";
+static const char* cliEccKey  = "./certs/ecc-client-key.pem";
+static const char* cliEccCert = "./certs/client-ecc-cert.pem";
 
 typedef struct tcp_ready {
     int ready;              /* predicate */

+ 12 - 0
examples/client/client.c

@@ -146,6 +146,17 @@ void client_test(void* args)
         /* ./client          // plain mode */
         /* for client cert authentication if server requests */
 #ifndef NO_FILESYSTEM
+    #ifdef HAVE_ECC
+        if (CyaSSL_CTX_use_certificate_file(ctx, cliEccCert, SSL_FILETYPE_PEM)
+                != SSL_SUCCESS)
+            err_sys("can't load ecc client cert file, "
+                    "Please run from CyaSSL home dir");
+
+        if (CyaSSL_CTX_use_PrivateKey_file(ctx, cliEccKey, SSL_FILETYPE_PEM)
+                != SSL_SUCCESS)
+            err_sys("can't load ecc client key file, "
+                    "Please run from CyaSSL home dir");
+    #else
         if (CyaSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM)
                 != SSL_SUCCESS)
             err_sys("can't load client cert file, "
@@ -155,6 +166,7 @@ void client_test(void* args)
                 != SSL_SUCCESS)
             err_sys("can't load client key file, "
                     "Please run from CyaSSL home dir");
+    #endif /* HAVE_ECC */
 #else
         load_buffer(ctx, cliCert, CYASSL_CERT);
         load_buffer(ctx, cliKey, CYASSL_KEY);

+ 4 - 0
examples/server/server.c

@@ -115,6 +115,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
                 != SSL_SUCCESS)
             err_sys("can't load server ecc key file, "
                     "Please run from CyaSSL home dir");
+        /* for client auth */
+        if (SSL_CTX_load_verify_locations(ctx, cliEccCert, 0) != SSL_SUCCESS)
+            err_sys("can't load ecc ca file, Please run from CyaSSL home dir");
+
     #elif HAVE_NTRU
         if (SSL_CTX_use_certificate_file(ctx, ntruCert, SSL_FILETYPE_PEM)
                 != SSL_SUCCESS)

+ 81 - 24
src/internal.c

@@ -4552,7 +4552,12 @@ int SetCipherList(Suites* s, const char* list)
         byte              *output;
         int                sendSz = 0, length, ret;
         word32             idx = 0;
+        word32             sigOutSz = 0;
         RsaKey             key;
+        int                usingEcc = 0;
+#ifdef HAVE_ECC
+        ecc_key            eccKey;
+#endif
 
         if (ssl->options.sendVerify == SEND_BLANK_CERT)
             return 0;  /* sent blank cert, can't verify */
@@ -4567,10 +4572,31 @@ int SetCipherList(Suites* s, const char* list)
 
         BuildCertHashes(ssl, &ssl->certHashes);
 
-        /* TODO: when add DSS support check here  */
+#ifdef HAVE_ECC
+        ecc_init(&eccKey);
+#endif
         InitRsaKey(&key, ssl->heap);
         ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
-                                  ssl->buffers.key.length); 
+                                  ssl->buffers.key.length);
+        if (ret == 0)
+            sigOutSz = RsaEncryptSize(&key);
+        else {
+    #ifdef HAVE_ECC
+            CYASSL_MSG("Trying ECC client cert, RSA didn't work");
+           
+            idx = 0; 
+            ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &eccKey,
+                                      ssl->buffers.key.length);
+            if (ret == 0) {
+                CYASSL_MSG("Using ECC client cert");
+                usingEcc = 1;
+                sigOutSz = ecc_sig_size(&eccKey);
+            }
+            else {
+                CYASSL_MSG("Bad client cert type");
+            }
+    #endif
+        }
         if (ret == 0) {
             byte*  verify = (byte*)&output[RECORD_HEADER_SZ +
                                            HANDSHAKE_HEADER_SZ];
@@ -4583,34 +4609,45 @@ int SetCipherList(Suites* s, const char* list)
                 if (ssl->options.dtls)
                     verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
             #endif
-            length = RsaEncryptSize(&key);
+            length = sigOutSz;
             if (IsAtLeastTLSv1_2(ssl)) {
                 verify[0] = sha_mac;
-                verify[1] = rsa_sa_algo;
+                verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo;
                 extraSz = HASH_SIG_SIZE;
             }
             c16toa((word16)length, verify + extraSz); /* prepend verify header*/
 
-            if (IsAtLeastTLSv1_2(ssl)) {
-                byte* digest;
-                int   typeH;
-                int   digestSz;
-
-                /* sha1 for now */
-                digest   = ssl->certHashes.sha;
-                typeH    = SHAh;
-                digestSz = SHA_DIGEST_SIZE;
-
-                signSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
-                signBuffer = encodedSig;
+            if (usingEcc) {
+#ifdef HAVE_ECC
+                word32 localSz = sigOutSz;
+                ret = ecc_sign_hash(signBuffer + MD5_DIGEST_SIZE,
+                              SHA_DIGEST_SIZE, verify + extraSz + VERIFY_HEADER,
+                              &localSz, &ssl->rng, &eccKey);
+#endif
             }
+            else {
+                if (IsAtLeastTLSv1_2(ssl)) {
+                    byte* digest;
+                    int   typeH;
+                    int   digestSz;
+
+                    /* sha1 for now */
+                    digest   = ssl->certHashes.sha;
+                    typeH    = SHAh;
+                    digestSz = SHA_DIGEST_SIZE;
+
+                    signSz = EncodeSignature(encodedSig, digest,digestSz,typeH);
+                    signBuffer = encodedSig;
+                }
 
-            ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
-                  VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
-
-            if (ret > 0) {
-                ret = 0;  /* reset */
+                ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
+                                  VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
 
+                if (ret > 0)
+                    ret = 0;  /* RSA reset */
+            }
+            
+            if (ret == 0) {
                 AddHeaders(output, length + extraSz + VERIFY_HEADER,
                            certificate_verify, ssl);
 
@@ -4625,6 +4662,9 @@ int SetCipherList(Suites* s, const char* list)
         }
 
         FreeRsaKey(&key);
+#ifdef HAVE_ECC
+        ecc_free(&eccKey);
+#endif
 
         if (ret == 0) {
             #ifdef CYASSL_CALLBACKS
@@ -5548,8 +5588,11 @@ int SetCipherList(Suites* s, const char* list)
 
         sig = &input[i];
         *inOutsz = i + sz;
-        /* TODO: when add DSS support check here  */
+
+        /* RSA */
         if (ssl->peerRsaKeyPresent != 0) {
+            CYASSL_MSG("Doing RSA peer cert verify");
+
             outLen = RsaSSL_VerifyInline(sig, sz, &out, &ssl->peerRsaKey);
 
             if (IsAtLeastTLSv1_2(ssl)) {
@@ -5567,14 +5610,28 @@ int SetCipherList(Suites* s, const char* list)
                 sigSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
 
                 if (outLen == (int)sigSz && XMEMCMP(out, encodedSig,sigSz) == 0)
-                    ret = 0;
+                    ret = 0;  /* verified */
             }
             else {
                 if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out,
                              ssl->certHashes.md5, sizeof(ssl->certHashes)) == 0)
-                    ret = 0;
+                    ret = 0;  /* verified */
             }
         }
+#ifdef HAVE_ECC
+        else if (ssl->peerEccDsaKeyPresent) {
+            int verify =  0;
+            int err    = -1;
+
+            CYASSL_MSG("Doing ECC peer cert verify");
+
+            err = ecc_verify_hash(sig, sz, ssl->certHashes.sha, SHA_DIGEST_SIZE,
+                                  &verify, &ssl->peerEccDsaKey);
+
+            if (err == 0 && verify == 1)
+               ret = 0;   /* verified */ 
+        }
+#endif
         return ret;
     }