diff --git a/certs/test/include.am b/certs/test/include.am index 588603380..fef473888 100644 --- a/certs/test/include.am +++ b/certs/test/include.am @@ -47,6 +47,9 @@ EXTRA_DIST += \ certs/test/server-badaltname.pem \ certs/test/server-localhost.der \ certs/test/server-localhost.pem \ + certs/test/smime-test.p7s \ + certs/test/smime-test-multipart.p7s \ + certs/test/smime-test-multipart-badsig.p7s \ certs/crl/server-goodaltCrl.pem \ certs/crl/server-goodcnCrl.pem \ certs/crl/server-goodaltwildCrl.pem \ diff --git a/certs/test/smime-test-multipart-badsig.p7s b/certs/test/smime-test-multipart-badsig.p7s new file mode 100755 index 000000000..26f87b375 --- /dev/null +++ b/certs/test/smime-test-multipart-badsig.p7s @@ -0,0 +1,63 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----B38034378A5510A6E45EAE0B6DAA1D08" + +This is an S/MIME signed message + +------B38034378A5510A6E45EAE0B6DAA1D08 +Content-Type: text/plain + +This is a test S/MIME message. Its content was modified without +updating the signature, so verification should fail. + +------B38034378A5510A6E45EAE0B6DAA1D08 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIIJwYJKoZIhvcNAQcCoIIIGDCCCBQCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggUhMIIFHTCCBAWgAwIBAgIURUWBguY6vaLjBg66LEV0S77AOREw +DQYJKoZIhvcNAQELBQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5h +MRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNV +BAsMEFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEf +MB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMDA2MTkxMzIzNDFa +Fw0yMzAzMTYxMzIzNDFaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFu +YTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYD +VQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDDA9Er/jmkMkU7U8iEKyp8dJq9qipSB0fWpjayBzKO +0Lppe8bDRJ7UgUj9LWiii2e7oXXINixK0hv3i7rPDfnv7PGBHnubA0eav2XMf2Uk +aaboFIlb5DT3xbAUk/Vnezp6eOEBVlaRphNCjdI8QJxM79GG3zdRGwyhO/Xxo0o1 +5OHOlt8bfr9Ol9AQ6KgIMIGvIAtDFMV0Z7Qygm+NhsKIQJk2g7oeQHIiF9dSZSRz +sM7vGc2u/3hse8ASA9ROcg1QbTujO6OZXp3I2QyFs9mK2VQm2236rLv/JUzE0Xn0 +cdOGQBgTsGO1ck4wxJeEhi1WL9cV93/ArvX8W+X7obrTAgMBAAGjggFPMIIBSzAd +BgNVHQ4EFgQUM9hFZtdohxh+VA1wJ5HHJteFZcAwgd4GA1UdIwSB1jCB04AUM9hF +Ztdohxh+VA1wJ5HHJteFZcChgaSkgaEwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIw +NDgxGTAXBgNVBAsMEFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIURUWBguY6 +vaLjBg66LEV0S77AOREwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxl +LmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI +hvcNAQELBQADggEBAMEGOcjO9YFJVeE6VaqRXWTxS9wzHjEV5xBxFg21ANy7Ig2B +2RJcDN1h4a+14vd9i+Zh/cpFOmHnGFYsJvLfFPHgPX9iEl/YBEQGDHKxilByZ3d0 +Af95ZBFus4RRGSK2QxAGDTlGWsZXCkOhlAIoChI4hQQOeFJIKH5s2fBLBFV8OQHB +tF9QBs/abyC4lPdRGiPLMOMhtKNzrUj7lmnvLlC2Z7xk7id2Q3o0WY60V1N9lX5Q +fmRMKWj+gU9zISS1qaJJX1R/DcKWx/U2gY7AAK+0EGsOvBo68abd/Y5jITPUMjEf +vqN8UoUmyG5QbKw9LsD5UO3ITc0TUM5e3hWJ0fsxggLKMIICxgIBATCBtzCBnjEL +MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x +FTATBgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0 +ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tAhRFRYGC5jq9ouMGDrosRXRLvsA5ETANBglghkgBZQMEAgEF +AKCB5DAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0y +MDEyMDUwMDI5MThaMC8GCSqGSIb3DQEJBDEiBCDKdWDpHqZ6UCZu+bTJOi4N9u5X +zfbWv9/S3YoSYPFlvDB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglg +hkgBZQMEARYwCwYJYIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIA +gDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG +9w0BAQEFAASCAQC2H9c4xZ6+n0nc3iBlMlS/5l/d5cWOLww2PctNzB8cZHu8uiRc +KeU5QWV0KLNZk/qOkJkVwPuV49YbtGefJkg3DlBTX9zxcHAVeKCiLMetNBW/uVhe +fwN3zzMX5SfzFrFMhKBfih+8PjB9LGteF0xKEnfz36ajGQLPYf9l9pUdrfSYHOPA +u4brxPvg/nImXdqQ21eQS9acdS/6QV5hk4TJF9qZVqaCuk4uESoKMWQtAVS33kwZ +3XozYEyBIV4rD8S5HhP0KAsbalk3qd1YuIUekvwZiiSh9Cm/4XnQgD2JfZ2CJT+V +DaxA77QhvPIrLwxy3/4hhuxDimcWm2FZYwQ7 + +------B38034378A5510A6E45EAE0B6DAA1D08-- + diff --git a/certs/test/smime-test-multipart.p7s b/certs/test/smime-test-multipart.p7s new file mode 100755 index 000000000..91def3a2d --- /dev/null +++ b/certs/test/smime-test-multipart.p7s @@ -0,0 +1,62 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----B38034378A5510A6E45EAE0B6DAA1D08" + +This is an S/MIME signed message + +------B38034378A5510A6E45EAE0B6DAA1D08 +Content-Type: text/plain + +This is a test S/MIME message. + +------B38034378A5510A6E45EAE0B6DAA1D08 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIIJwYJKoZIhvcNAQcCoIIIGDCCCBQCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggUhMIIFHTCCBAWgAwIBAgIURUWBguY6vaLjBg66LEV0S77AOREw +DQYJKoZIhvcNAQELBQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5h +MRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNV +BAsMEFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEf +MB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMDA2MTkxMzIzNDFa +Fw0yMzAzMTYxMzIzNDFaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFu +YTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYD +VQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDDA9Er/jmkMkU7U8iEKyp8dJq9qipSB0fWpjayBzKO +0Lppe8bDRJ7UgUj9LWiii2e7oXXINixK0hv3i7rPDfnv7PGBHnubA0eav2XMf2Uk +aaboFIlb5DT3xbAUk/Vnezp6eOEBVlaRphNCjdI8QJxM79GG3zdRGwyhO/Xxo0o1 +5OHOlt8bfr9Ol9AQ6KgIMIGvIAtDFMV0Z7Qygm+NhsKIQJk2g7oeQHIiF9dSZSRz +sM7vGc2u/3hse8ASA9ROcg1QbTujO6OZXp3I2QyFs9mK2VQm2236rLv/JUzE0Xn0 +cdOGQBgTsGO1ck4wxJeEhi1WL9cV93/ArvX8W+X7obrTAgMBAAGjggFPMIIBSzAd +BgNVHQ4EFgQUM9hFZtdohxh+VA1wJ5HHJteFZcAwgd4GA1UdIwSB1jCB04AUM9hF +Ztdohxh+VA1wJ5HHJteFZcChgaSkgaEwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIw +NDgxGTAXBgNVBAsMEFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIURUWBguY6 +vaLjBg66LEV0S77AOREwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxl +LmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI +hvcNAQELBQADggEBAMEGOcjO9YFJVeE6VaqRXWTxS9wzHjEV5xBxFg21ANy7Ig2B +2RJcDN1h4a+14vd9i+Zh/cpFOmHnGFYsJvLfFPHgPX9iEl/YBEQGDHKxilByZ3d0 +Af95ZBFus4RRGSK2QxAGDTlGWsZXCkOhlAIoChI4hQQOeFJIKH5s2fBLBFV8OQHB +tF9QBs/abyC4lPdRGiPLMOMhtKNzrUj7lmnvLlC2Z7xk7id2Q3o0WY60V1N9lX5Q +fmRMKWj+gU9zISS1qaJJX1R/DcKWx/U2gY7AAK+0EGsOvBo68abd/Y5jITPUMjEf +vqN8UoUmyG5QbKw9LsD5UO3ITc0TUM5e3hWJ0fsxggLKMIICxgIBATCBtzCBnjEL +MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x +FTATBgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0 +ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tAhRFRYGC5jq9ouMGDrosRXRLvsA5ETANBglghkgBZQMEAgEF +AKCB5DAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0y +MDEyMDUwMDI5MThaMC8GCSqGSIb3DQEJBDEiBCDKdWDpHqZ6UCZu+bTJOi4N9u5X +zfbWv9/S3YoSYPFlvDB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglg +hkgBZQMEARYwCwYJYIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIA +gDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG +9w0BAQEFAASCAQC2H9c4xZ6+n0nc3iBlMlS/5l/d5cWOLww2PctNzB8cZHu8uiRc +KeU5QWV0KLNZk/qOkJkVwPuV49YbtGefJkg3DlBTX9zxcHAVeKCiLMetNBW/uVhe +fwN3zzMX5SfzFrFMhKBfih+8PjB9LGteF0xKEnfz36ajGQLPYf9l9pUdrfSYHOPA +u4brxPvg/nImXdqQ21eQS9acdS/6QV5hk4TJF9qZVqaCuk4uESoKMWQtAVS33kwZ +3XozYEyBIV4rD8S5HhP0KAsbalk3qd1YuIUekvwZiiSh9Cm/4XnQgD2JfZ2CJT+V +DaxA77QhvPIrLwxy3/4hhuxDimcWm2FZYwQ7 + +------B38034378A5510A6E45EAE0B6DAA1D08-- + diff --git a/certs/test/smime-test.p7s b/certs/test/smime-test.p7s new file mode 100755 index 000000000..e8e8c884e --- /dev/null +++ b/certs/test/smime-test.p7s @@ -0,0 +1,51 @@ +MIME-Version: 1.0 +Content-Disposition: attachment; filename="smime.p7m" +Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m" +Content-Transfer-Encoding: base64 + +MIIIZwYJKoZIhvcNAQcCoIIIWDCCCFQCAQExDzANBglghkgBZQMEAgEFADBLBgkq +hkiG9w0BBwGgPgQ8Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNClRoaXMgaXMg +YSB0ZXN0IFMvTUlNRSBtZXNzYWdlLg0KoIIFITCCBR0wggQFoAMCAQICFEVFgYLm +Or2i4wYOuixFdEu+wDkRMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMGA1UECgwMd29s +ZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgwFgYDVQQDDA93 +d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20w +HhcNMjAwNjE5MTMyMzQxWhcNMjMwMzE2MTMyMzQxWjCBnjELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTATBgNVBAoMDHdv +bGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwPRK/45pDJFO1PIhCsq +fHSavaoqUgdH1qY2sgcyjtC6aXvGw0Se1IFI/S1oootnu6F1yDYsStIb94u6zw35 +7+zxgR57mwNHmr9lzH9lJGmm6BSJW+Q098WwFJP1Z3s6enjhAVZWkaYTQo3SPECc +TO/Rht83URsMoTv18aNKNeThzpbfG36/TpfQEOioCDCBryALQxTFdGe0MoJvjYbC +iECZNoO6HkByIhfXUmUkc7DO7xnNrv94bHvAEgPUTnINUG07ozujmV6dyNkMhbPZ +itlUJttt+qy7/yVMxNF59HHThkAYE7BjtXJOMMSXhIYtVi/XFfd/wK71/Fvl+6G6 +0wIDAQABo4IBTzCCAUswHQYDVR0OBBYEFDPYRWbXaIcYflQNcCeRxybXhWXAMIHe +BgNVHSMEgdYwgdOAFDPYRWbXaIcYflQNcCeRxybXhWXAoYGkpIGhMIGeMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMG +A1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgw +FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb22CFEVFgYLmOr2i4wYOuixFdEu+wDkRMAwGA1UdEwQFMAMBAf8wHAYD +VR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0lBBYwFAYIKwYBBQUHAwEG +CCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQDBBjnIzvWBSVXhOlWqkV1k8Uvc +Mx4xFecQcRYNtQDcuyINgdkSXAzdYeGvteL3fYvmYf3KRTph5xhWLCby3xTx4D1/ +YhJf2AREBgxysYpQcmd3dAH/eWQRbrOEURkitkMQBg05RlrGVwpDoZQCKAoSOIUE +DnhSSCh+bNnwSwRVfDkBwbRfUAbP2m8guJT3URojyzDjIbSjc61I+5Zp7y5Qtme8 +ZO4ndkN6NFmOtFdTfZV+UH5kTClo/oFPcyEktamiSV9Ufw3Clsf1NoGOwACvtBBr +DrwaOvGm3f2OYyEz1DIxH76jfFKFJshuUGysPS7A+VDtyE3NE1DOXt4VidH7MYIC +yjCCAsYCAQEwgbcwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAw +DgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsM +EFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbQIURUWBguY6vaLjBg66LEV0S77A +OREwDQYJYIZIAWUDBAIBBQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc +BgkqhkiG9w0BCQUxDxcNMjAxMjA1MDAyOTQyWjAvBgkqhkiG9w0BCQQxIgQgynVg +6R6melAmbvm0yTouDfbuV8321r/f0t2KEmDxZbwweQYJKoZIhvcNAQkPMWwwajAL +BglghkgBZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0D +BzAOBggqhkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZI +hvcNAwICASgwDQYJKoZIhvcNAQEBBQAEggEAaL7Di8KPGETeWWVPloWMBzkzT+px +NJGE1V0iOsUvDLb80jN2UJJlxVK9O0nV5FzMKhNdSILlraBFjgJctDj9KfB7GMwR +V+KbizOYRzwyWvGl8rsZStNVpQ6Fo+lnCwL/fVLfT5df0fJzRaC5gmNYEVbUhcbX +o/ICvDCv6dNxaFQc36l6285n7/rZvH6GvlfEZN12gyz7qoEan7HAO9cNp1KuWykf ++CS/sr2Hm5vssyPdw4RTN38wKLQmGYWIlZOTc82FBUFaL5AUNQcDaTdloSqCiUtG +q6nZ7nk3wsrRNe8jBpkEl8gkMVXeXsvLvnokrzHEmnk5ub61SdxvNEK3hQ== + diff --git a/configure.ac b/configure.ac index 8fb4ff51b..46149d53b 100644 --- a/configure.ac +++ b/configure.ac @@ -394,6 +394,8 @@ then if test "$ENABLED_FIPS" = "no" then test "$enable_openssh" = "" && enable_openssh=yes + # S/MIME support requires PKCS7, which requires no FIPS. + test "$enable_smime" = "" && enable_smime=yes fi test "$enable_opensslextra" = "" && enable_opensslextra=yes test "$enable_opensslall" = "" && enable_opensslall=yes @@ -862,6 +864,12 @@ then AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COEXIST" fi +# S/MIME +AC_ARG_ENABLE([smime], + [AS_HELP_STRING([--enable-smime],[Enable S/MIME (default: disabled)])], + [ ENABLED_SMIME=$enableval ], + [ ENABLED_SMIME=no ] + ) # OPENSSL Compatibility ALL AC_ARG_ENABLE([opensslall], @@ -869,7 +877,7 @@ AC_ARG_ENABLE([opensslall], [ ENABLED_OPENSSLALL=$enableval ], [ ENABLED_OPENSSLALL=no ] ) -if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" +if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" || test "$ENABLED_SMIME" = "yes" then ENABLED_OPENSSLALL="yes" fi @@ -3672,7 +3680,6 @@ AC_ARG_ENABLE([pkcs7], [ ENABLED_PKCS7=no ] ) - # wolfSSH Options AC_ARG_ENABLE([ssh], [AS_HELP_STRING([--enable-ssh],[Enable wolfSSH options (default: disabled)])], @@ -3721,6 +3728,15 @@ then fi fi +if test "x$ENABLED_SMIME" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_SMIME" + # Requires PKCS7 + if test "x$ENABLED_PKCS7" = "xno" + then + ENABLED_PKCS7="yes" + fi +fi # Simple Certificate Enrollment Protocol (SCEP) AC_ARG_ENABLE([scep], @@ -5660,6 +5676,10 @@ AS_IF([test "x$ENABLED_OCSP" = "xyes" && \ test "x$ENABLED_ASN" = "xno"], [AC_MSG_ERROR([please enable asn if enabling ocsp.])]) +AS_IF([test "x$ENABLED_SMIME" = "xyes" && \ + test "x$ENABLED_ASN" = "xno"], + [AC_MSG_ERROR([please enable asn if enabling S/MIME.])]) + AS_IF([test "x$ENABLED_OCSP" = "xyes" && \ test "x$ENABLED_RSA" = "xno" && \ test "x$ENABLED_ECC" = "xno"], @@ -6122,6 +6142,7 @@ AM_CONDITIONAL([BUILD_TRUST_PEER_CERT],[test "x$ENABLED_TRUSTED_PEER_CERT" = "xy AM_CONDITIONAL([BUILD_PKI],[test "x$ENABLED_PKI" = "xyes"]) AM_CONDITIONAL([BUILD_DES3],[test "x$ENABLED_DES3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_PKCS7],[test "x$ENABLED_PKCS7" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SMIME],[test "x$ENABLED_SMIME" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_HASHFLAGS],[test "x$ENABLED_HASHFLAGS" = "xyes"]) AM_CONDITIONAL([BUILD_LINUXKM],[test "$ENABLED_LINUXKM" = "yes"]) AM_CONDITIONAL([BUILD_NO_LIBRARY],[test "$ENABLED_NO_LIBRARY" = "yes"]) @@ -6426,6 +6447,7 @@ echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * Fallback SCSV: $ENABLED_FALLBACK_SCSV" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * PKCS#7 $ENABLED_PKCS7" +echo " * S/MIME $ENABLED_SMIME" echo " * wolfSSH $ENABLED_WOLFSSH" echo " * wolfTPM $ENABLED_WOLFTPM" echo " * wolfSCEP $ENABLED_WOLFSCEP" diff --git a/src/ssl.c b/src/ssl.c index 7077b8c88..22741d250 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -51105,11 +51105,28 @@ void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7) } PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +{ + return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0); +} + +/***************************************************************************** +* wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len +* into a PKCS7 object. Optionally, accepts a byte buffer of content which +* is stored as the PKCS7 object's content, to support detached signatures. +* @param content The content which is signed, in case the signature is +* detached. Ignored if NULL. +* @param contentSz The size of the passed in content. +* +* RETURNS: +* returns pointer to a PKCS7 structure on success, otherwise returns NULL +*/ +PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len, + byte* content, word32 contentSz) { WOLFSSL_PKCS7* pkcs7 = NULL; word32 idx = 0; - WOLFSSL_ENTER("wolfSSL_d2i_PKCS7"); + WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex"); if (in == NULL || *in == NULL) return NULL; @@ -51129,10 +51146,16 @@ PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) return NULL; } XMEMCPY(pkcs7->data, *in, pkcs7->len); + + if (content != NULL) { + pkcs7->pkcs7.content = content; + pkcs7->pkcs7.contentSz = contentSz; + } if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) != 0) { wolfSSL_PKCS7_free((PKCS7*)pkcs7); return NULL; } + if (p7 != NULL) *p7 = (PKCS7*)pkcs7; *in += pkcs7->len; @@ -51567,6 +51590,296 @@ error: } return WOLFSSL_FAILURE; } + +#ifdef HAVE_SMIME +/***************************************************************************** +* wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into +* a PKCS7 object. In case of a multipart message, stores the signed data in +* bcont. +* +* RETURNS: +* returns pointer to a PKCS7 structure on success, otherwise returns NULL +*/ +WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, + WOLFSSL_BIO** bcont) +{ + MimeHdr* allHdrs = NULL; + MimeHdr* curHdr = NULL; + MimeParam* curParam = NULL; + int inLen = 0; + byte* bcontMem = NULL; + int bcontMemSz = 0; + int sectionLen = 0; + int ret = -1; + char* section = NULL; + PKCS7* pkcs7 = NULL; + word32 outLen = 0; + byte* out = NULL; + byte* outHead = NULL; + + int lineLen = 0; + int remainLen = 0; + byte isEnd = 0; + size_t boundLen = 0; + char* boundary = NULL; + + static const char* kContType = "Content-Type"; + static const char* kCTE = "Content-Transfer-Encoding"; + static const char* kMultSigned = "multipart/signed"; + static const char* kAppPkcsSign = "application/pkcs7-signature"; + static const char* kAppXPkcsSign = "application/x-pkcs7-signature"; + static const char* kAppPkcs7Mime = "application/pkcs7-mime"; + static const char* kAppXPkcs7Mime = "application/x-pkcs7-mime"; + + + if (in == NULL || bcont == NULL) { + goto error; + } + inLen = wolfSSL_BIO_get_len(in); + if (inLen <= 0) { + goto error; + } + remainLen = wolfSSL_BIO_get_len(in); + if (remainLen <= 0) { + goto error; + } + + section = (char*)XMALLOC((remainLen+1)*sizeof(char), NULL, + DYNAMIC_TYPE_PKCS7); + if (section == NULL) { + goto error; + } + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while(isEnd == 0 && remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen); + if (lineLen <= 0) { + goto error; + } + /* Line with just newline signals end of headers. */ + if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], + "\r\n", 2)) || + (lineLen==1 && (section[sectionLen] == '\r' || + section[sectionLen] == '\n'))) { + isEnd = 1; + } + } + section[sectionLen] = '\0'; + ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); + if (ret < 0) { + WOLFSSL_MSG("Parsing MIME headers failed.\n"); + goto error; + } + isEnd = 0; + section[0] = '\0'; + sectionLen = 0; + + curHdr = wc_MIME_find_header_name(kContType, allHdrs); + if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned, + XSTR_SIZEOF(kMultSigned))) { + curParam = wc_MIME_find_param_attr("protocol", curHdr->params); + if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign, + XSTR_SIZEOF(kAppPkcsSign)) || + !XSTRNCMP(curParam->value, kAppXPkcsSign, + XSTR_SIZEOF(kAppXPkcsSign)))) { + curParam = wc_MIME_find_param_attr("boundary", curHdr->params); + if (curParam == NULL) { + goto error; + } + + boundLen = XSTRLEN(curParam->value) + 2; + boundary = (char*)XMALLOC((boundLen+1)*sizeof(char), NULL, + DYNAMIC_TYPE_PKCS7); + if (boundary == NULL) { + goto error; + } + XMEMSET(boundary, 0, (word32)((boundLen+1)*sizeof(char))); + boundary[0] = boundary[1] = '-'; + XSTRNCPY(&boundary[2], curParam->value, boundLen-2); + + /* Parse up to first boundary, ignore everything here. */ + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while(XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + + section[0] = '\0'; + sectionLen = 0; + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + while(XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + sectionLen--; + /* Strip the final trailing newline. Support \r, \n or \r\n. */ + if (section[sectionLen] == '\n') { + sectionLen--; + if (section[sectionLen] == '\r') { + sectionLen--; + } + } + else if (section[sectionLen] == '\r') { + sectionLen--; + } + section[sectionLen+1] = '\0'; + + *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + ret = wolfSSL_BIO_write(*bcont, section, (int)XSTRLEN(section)); + if (ret != (int)XSTRLEN(section)) { + goto error; + } + if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem)) < 0) { + goto error; + } + + + wc_MIME_free_hdrs(allHdrs); + section[0] = '\0'; + sectionLen = 0; + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while(isEnd == 0 && remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + /* Line with just newline signals end of headers. */ + if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], + "\r\n", 2)) || + (lineLen==1 && (section[sectionLen] == '\r' || + section[sectionLen] == '\n'))) { + isEnd = 1; + } + } + section[sectionLen] = '\0'; + ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); + if (ret < 0) { + WOLFSSL_MSG("Parsing MIME headers failed.\n"); + goto error; + } + curHdr = wc_MIME_find_header_name(kContType, allHdrs); + if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign, + XSTR_SIZEOF(kAppPkcsSign)) && + XSTRNCMP(curHdr->body, kAppXPkcsSign, + XSTR_SIZEOF(kAppXPkcsSign)))) { + WOLFSSL_MSG("S/MIME headers not found inside " + "multipart message.\n"); + goto error; + } + + section[0] = '\0'; + sectionLen = 0; + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + while(XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + + XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); + } + } + else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime, + XSTR_SIZEOF(kAppPkcs7Mime)) || + !XSTRNCMP(curHdr->body, kAppXPkcs7Mime, + XSTR_SIZEOF(kAppXPkcs7Mime)))) { + sectionLen = wolfSSL_BIO_get_len(in); + if (sectionLen <= 0) { + goto error; + } + ret = wolfSSL_BIO_read(in, section, sectionLen); + if (ret < 0 || ret != sectionLen) { + WOLFSSL_MSG("Error reading input BIO.\n"); + goto error; + } + } + else { + WOLFSSL_MSG("S/MIME headers not found.\n"); + goto error; + } + + curHdr = wc_MIME_find_header_name(kCTE, allHdrs); + if (curHdr == NULL) { + WOLFSSL_MSG("Content-Transfer-Encoding header not found, " + "assuming base64 encoding."); + } + else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) { + WOLFSSL_MSG("S/MIME encodings other than base64 are not " + "currently supported.\n"); + goto error; + } + + if (section == NULL || sectionLen <= 0) { + goto error; + } + outLen = ((sectionLen*3+3)/4)+1; + out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7); + outHead = out; + if (outHead == NULL) { + goto error; + } + /* Strip trailing newlines. */ + while ((section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n') && + sectionLen > 0) { + sectionLen--; + } + section[sectionLen] = '\0'; + ret = Base64_Decode((const byte*)section, sectionLen, out, &outLen); + if (ret < 0) { + WOLFSSL_MSG("Error base64 decoding S/MIME message.\n"); + goto error; + } + pkcs7 = wolfSSL_d2i_PKCS7_ex(NULL, (const unsigned char**)&out, outLen, + bcontMem, bcontMemSz); + + + wc_MIME_free_hdrs(allHdrs); + XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); + + + return pkcs7; + +error: + wc_MIME_free_hdrs(allHdrs); + XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); + wolfSSL_BIO_free(*bcont); + + return NULL; +} +#endif /* HAVE_SMIME */ #endif /* !NO_BIO */ #endif /* OPENSSL_ALL && HAVE_PKCS7 */ diff --git a/tests/api.c b/tests/api.c index 5e8639663..46df24c5c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -37173,6 +37173,50 @@ static void test_wolfSSL_PEM_write_bio_PKCS7(void) #endif } + +#ifdef HAVE_SMIME +static void test_wolfSSL_SMIME_read_PKCS7(void) +{ +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) + PKCS7* pkcs7 = NULL; + BIO* bio = NULL; + BIO* bcont = NULL; + XFILE smimeTestFile = XFOPEN("./certs/test/smime-test.p7s", "r"); + + printf(testingFmt, "wolfSSL_SMIME_read_PKCS7()"); + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + AssertNotNull(bio); + AssertIntEQ(wolfSSL_BIO_set_fp(bio, smimeTestFile, BIO_CLOSE), SSL_SUCCESS); + pkcs7 = wolfSSL_SMIME_read_PKCS7(bio, &bcont); + AssertNotNull(pkcs7); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, bcont, NULL, PKCS7_NOVERIFY), SSL_SUCCESS); + XFCLOSE(smimeTestFile); + if (bcont) BIO_free(bcont); + wolfSSL_PKCS7_free(pkcs7); + + smimeTestFile = XFOPEN("./certs/test/smime-test-multipart.p7s", "r"); + AssertIntEQ(wolfSSL_BIO_set_fp(bio, smimeTestFile, BIO_CLOSE), SSL_SUCCESS); + pkcs7 = wolfSSL_SMIME_read_PKCS7(bio, &bcont); + AssertNotNull(pkcs7); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, bcont, NULL, PKCS7_NOVERIFY), SSL_SUCCESS); + XFCLOSE(smimeTestFile); + if (bcont) BIO_free(bcont); + wolfSSL_PKCS7_free(pkcs7); + + smimeTestFile = XFOPEN("./certs/test/smime-test-multipart-badsig.p7s", "r"); + AssertIntEQ(wolfSSL_BIO_set_fp(bio, smimeTestFile, BIO_CLOSE), SSL_SUCCESS); + pkcs7 = wolfSSL_SMIME_read_PKCS7(bio, &bcont); + AssertNull(pkcs7); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, bcont, NULL, PKCS7_NOVERIFY), SSL_FAILURE); + BIO_free(bio); + if (bcont) BIO_free(bcont); + wolfSSL_PKCS7_free(pkcs7); + + printf(resultFmt, passed); +#endif +} +#endif /* HAVE_SMIME*/ #endif /* !NO_BIO */ /*----------------------------------------------------------------------------* @@ -40428,6 +40472,9 @@ void ApiTest(void) test_wolfSSL_PKCS7_SIGNED_new(); #ifndef NO_BIO test_wolfSSL_PEM_write_bio_PKCS7(); +#ifdef HAVE_SMIME + test_wolfSSL_SMIME_read_PKCS7(); +#endif #endif /* wolfCrypt ASN tests */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index ca30c7def..8bd75d8d3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -18502,6 +18502,291 @@ int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz) #endif /* WOLFSSL_CERT_PIV */ + +#ifdef HAVE_SMIME + +/***************************************************************************** +* wc_MIME_parse_headers - Reads the char array in and parses out MIME headers +* and parameters into headers. Will continue until in has no more content. +* +* RETURNS: +* returns zero on success, non-zero on error. +*/ +int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) +{ + MimeHdr* nextHdr = NULL; + MimeHdr* curHdr = NULL; + MimeParam* nextParam = NULL; + size_t start = 0; + size_t end = 0; + char* nameAttr = NULL; + char* bodyVal = NULL; + MimeTypes mimeType = MIME_HDR; + MimeStatus mimeStatus = MIME_NAMEATTR; + int ret = -1; + size_t pos = 0; + size_t lineLen = 0; + char* curLine = NULL; + char* ptr = NULL; + + if (in == NULL || inLen <= 0 || in[inLen] != '\0' || headers == NULL) { + ret = BAD_FUNC_ARG; + goto error; + } + nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, DYNAMIC_TYPE_PKCS7); + nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL, + DYNAMIC_TYPE_PKCS7); + if (nextHdr == NULL || nextParam == NULL) { + ret = MEMORY_E; + goto error; + } + XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr)); + XMEMSET(nextParam, 0, (word32)sizeof(MimeParam)); + + curLine = XSTRTOK(in, "\r\n", &ptr); + if (curLine == NULL) { + ret = ASN_PARSE_E; + goto error; + } + + while (curLine != NULL) { + /* Leftover from previous line, add params to previous header. */ + if (curLine[0] == ' ' && curHdr) { + mimeType = MIME_PARAM; + } + else { + mimeType = MIME_HDR; + } + start = end = 0; + lineLen = XSTRLEN(curLine); + + for (pos = 0; pos < lineLen; pos++) { + char cur = curLine[pos]; + + if (mimeStatus == MIME_NAMEATTR && ((cur == ':' && + mimeType == MIME_HDR) || (cur == '=' && + mimeType == MIME_PARAM))) { + mimeStatus = MIME_BODYVAL; + end = pos-1; + ret = wc_MIME_header_strip(curLine, &nameAttr, start, end); + if (ret) { + goto error; + } + start = pos+1; + } + else if (mimeStatus == MIME_BODYVAL && cur == ';') { + end = pos-1; + ret = wc_MIME_header_strip(curLine, &bodyVal, start, end); + if (ret) { + goto error; + } + if (mimeType == MIME_HDR) { + nextHdr->name = nameAttr; + nextHdr->body = bodyVal; + nextHdr->next = curHdr; + curHdr = nextHdr; + nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, + DYNAMIC_TYPE_PKCS7); + if (nextHdr == NULL) { + ret = MEMORY_E; + goto error; + } + XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr)); + } + else { + nextParam->attribute = nameAttr; + nextParam->value = bodyVal; + nextParam->next = curHdr->params; + curHdr->params = nextParam; + nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL, + DYNAMIC_TYPE_PKCS7); + if (nextParam == NULL) { + ret = MEMORY_E; + goto error; + } + XMEMSET(nextParam, 0, (word32)sizeof(MimeParam)); + } + mimeType = MIME_PARAM; + mimeStatus = MIME_NAMEATTR; + start = pos+1; + } + } + + end = lineLen-1; + /* Omit newline characters. */ + while ((curLine[end] == '\r' || curLine[end] == '\n') && end > 0) { + end--; + } + if (end >= start && mimeStatus == MIME_BODYVAL) { + ret = wc_MIME_header_strip(curLine, &bodyVal, start, end); + if (ret) { + goto error; + } + if (mimeType == MIME_HDR) { + nextHdr->name = nameAttr; + nextHdr->body = bodyVal; + nextHdr->next = curHdr; + curHdr = nextHdr; + nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, + DYNAMIC_TYPE_PKCS7); + if (nextHdr == NULL) { + ret = MEMORY_E; + goto error; + } + XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr)); + } else { + nextParam->attribute = nameAttr; + nextParam->value = bodyVal; + nextParam->next = curHdr->params; + curHdr->params = nextParam; + nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL, + DYNAMIC_TYPE_PKCS7); + if (nextParam == NULL) { + ret = MEMORY_E; + goto error; + } + XMEMSET(nextParam, 0, (word32)sizeof(MimeParam)); + } + } + + curLine = XSTRTOK(NULL, "\r\n", &ptr); + mimeStatus = MIME_NAMEATTR; + } + + *headers = curHdr; + XFREE(nextHdr, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(nextParam, NULL, DYNAMIC_TYPE_PKCS7); + + return 0; + +error: + wc_MIME_free_hdrs(curHdr); + wc_MIME_free_hdrs(nextHdr); + XFREE(nameAttr, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(bodyVal, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(nextParam, NULL, DYNAMIC_TYPE_PKCS7); + + return ret; +} + +/***************************************************************************** +* wc_MIME_header_strip - Reads the string in from indices start to end, strips +* out disallowed/separator characters and places the rest into *out. +* +* RETURNS: +* returns zero on success, non-zero on error. +*/ +int wc_MIME_header_strip(char* in, char** out, size_t start, size_t end) +{ + size_t inPos = start; + size_t outPos = 0; + size_t inLen = 0; + + if (end < start || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + inLen = XSTRLEN(in); + if (start > inLen || end > inLen) { + return BAD_FUNC_ARG; + } + + *out = (char*)XMALLOC(((end-start)+2)*sizeof(char), NULL, + DYNAMIC_TYPE_PKCS7); + if (*out == NULL) { + return MEMORY_E; + } + + while (inPos <= end) { + if (in[inPos] >= MIME_HEADER_ASCII_MIN && in[inPos] <= + MIME_HEADER_ASCII_MAX && in[inPos] != ';' && in[inPos] != '\"') { + (*out)[outPos] = in[inPos]; + outPos++; + } + inPos++; + } + (*out)[outPos] = '\0'; + + return 0; +} + +/***************************************************************************** +* wc_MIME_find_header_name - Searches through all given headers until a header with +* a name matching the provided name is found. +* +* RETURNS: +* returns a pointer to the found header, if no match was found, returns NULL. +*/ +MimeHdr* wc_MIME_find_header_name(const char* name, MimeHdr* header) +{ + size_t len = XSTRLEN(name); + + while (header) { + if (!XSTRNCMP(name, header->name, len)) { + return header; + } + header = header->next; + } + + return header; +} + +/***************************************************************************** +* wc_MIME_find_param_attr - Searches through all parameters until a parameter +* with a attribute matching the provided attribute is found. +* +* RETURNS: +* returns a pointer to the found parameter, if no match was found, +* returns NULL. +*/ +MimeParam* wc_MIME_find_param_attr(const char* attribute, + MimeParam* param) +{ + size_t len = XSTRLEN(attribute); + + while (param) { + if (!XSTRNCMP(attribute, param->attribute, len)) { + return param; + } + param = param->next; + } + + return param; +} + +/***************************************************************************** +* wc_MIME_free_hdrs - Frees all MIME headers, parameters and strings starting from +* the provided header pointer. +* +* RETURNS: +* returns zero on success, non-zero on error. +*/ +int wc_MIME_free_hdrs(MimeHdr* head) +{ + MimeHdr* curHdr = NULL; + MimeParam* curParam = NULL; + + while (head) { + while (head->params) { + curParam = head->params; + head->params = head->params->next; + XFREE(curParam->attribute, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(curParam->value, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(curParam, NULL, DYNAMIC_TYPE_PKCS7); + } + curHdr = head; + head = head->next; + XFREE(curHdr->name, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(curHdr->body, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(curHdr, NULL, DYNAMIC_TYPE_PKCS7); + } + + return 0; +} + +#endif /* HAVE_SMIME */ + + #undef ERROR_OUT #endif /* !NO_ASN */ diff --git a/wolfssl/openssl/pkcs7.h b/wolfssl/openssl/pkcs7.h index ce444d51d..53ab4436e 100644 --- a/wolfssl/openssl/pkcs7.h +++ b/wolfssl/openssl/pkcs7.h @@ -37,7 +37,6 @@ #define PKCS7_NOINTERN 0x0010 #define PKCS7_NOVERIFY 0x0020 - typedef struct WOLFSSL_PKCS7 { PKCS7 pkcs7; @@ -53,6 +52,8 @@ WOLFSSL_API void wolfSSL_PKCS7_free(PKCS7* p7); WOLFSSL_API void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7); WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len); +WOLFSSL_LOCAL PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, + int len, byte* content, word32 contentSz); WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7); WOLFSSL_API int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7); WOLFSSL_API int wolfSSL_PKCS7_verify(PKCS7* p7, WOLFSSL_STACK* certs, @@ -63,6 +64,10 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7); WOLFSSL_API WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* p7, WOLFSSL_STACK* certs, int flags); WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7); +#if defined(HAVE_SMIME) +WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, WOLFSSL_BIO** bcont); +#endif /* HAVE_SMIME */ + #define PKCS7_new wolfSSL_PKCS7_new #define PKCS7_SIGNED_new wolfSSL_PKCS7_SIGNED_new @@ -74,6 +79,9 @@ WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7); #define PKCS7_verify wolfSSL_PKCS7_verify #define PKCS7_get0_signers wolfSSL_PKCS7_get0_signers #define PEM_write_bio_PKCS7 wolfSSL_PEM_write_bio_PKCS7 +#if defined(HAVE_SMIME) +#define SMIME_read_PKCS7 wolfSSL_SMIME_read_PKCS7 +#endif /* HAVE_SMIME */ #endif /* OPENSSL_ALL && HAVE_PKCS7 */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index e7dec24ec..e412c1d06 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1050,6 +1050,42 @@ struct TrustedPeerCert { #define WOLFSSL_ASN_API WOLFSSL_LOCAL #endif +#ifdef HAVE_SMIME +#define MIME_HEADER_ASCII_MIN 33 +#define MIME_HEADER_ASCII_MAX 126 + +typedef struct MimeParam MimeParam; +typedef struct MimeHdr MimeHdr; + +struct MimeParam +{ + MimeParam* next; + char* attribute; + char* value; +}; + +struct MimeHdr +{ + MimeHdr* next; + MimeParam* params; + char* name; + char* body; +}; + +typedef enum MimeTypes +{ + MIME_HDR, + MIME_PARAM +} MimeTypes; + +typedef enum MimeStatus +{ + MIME_NAMEATTR, + MIME_BODYVAL +} MimeStatus; +#endif /* HAVE_SMIME */ + + WOLFSSL_LOCAL int CalcHashId(const byte* data, word32 len, byte* hash); WOLFSSL_LOCAL int GetName(DecodedCert* cert, int nameType, int maxIdx); @@ -1237,6 +1273,16 @@ WOLFSSL_LOCAL void FreeDer(DerBuffer** der); #endif /* !NO_CERTS */ +#ifdef HAVE_SMIME +WOLFSSL_LOCAL int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** hdrs); +WOLFSSL_LOCAL int wc_MIME_header_strip(char* in, char** out, size_t start, size_t end); +WOLFSSL_LOCAL int wc_MIME_create_header(char* name, char* body, MimeHdr** hdr); +WOLFSSL_LOCAL int wc_MIME_create_parameter(char* attribute, char* value, MimeParam** param); +WOLFSSL_LOCAL MimeHdr* wc_MIME_find_header_name(const char* name, MimeHdr* hdr); +WOLFSSL_LOCAL MimeParam* wc_MIME_find_param_attr(const char* attribute, MimeParam* param); +WOLFSSL_LOCAL int wc_MIME_free_hdrs(MimeHdr* head); +#endif /* HAVE_SMIME */ + #ifdef WOLFSSL_CERT_GEN enum cert_enums {