diff --git a/certs/server-cert.der b/certs/server-cert.der new file mode 100644 index 0000000..d3f75c2 Binary files /dev/null and b/certs/server-cert.der differ diff --git a/certs/server-cert.pem b/certs/server-cert.pem new file mode 100644 index 0000000..09676a0 --- /dev/null +++ b/certs/server-cert.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + fa:24:ef:1a:5a:f2:b2:a4 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL Inc., OU=Engineering, CN=wolfssh/emailAddress=info@wolfssl.com + Validity + Not Before: Aug 15 19:46:24 2014 GMT + Not After : May 11 19:46:24 2017 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL Inc., OU=Engineering, CN=wolfssh/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:c5:7e:5d:0c:c5:47:95:67:ad:89:ff:db:fa:77: + e8:1f:76:d3:ac:6f:10:8a:93:bf:ee:1b:93:9f:5b: + 71:79:4c:d8:d5:6d:8e:d0:d2:b9:6b:e8:75:c8:73: + f5:5d:1c:61:60:27:da:79:40:18:a3:b4:b8:f3:c3: + 79:4e:12:6f:a2:20:46:6c:29:50:5d:f8:b6:82:89: + 34:22:2a:14:00:77:38:ad:fa:e3:61:8d:71:c4:ff: + 76:bc:34:3d:85:b5:ca:96:f8:46:d9:90:0f:e4:05: + 31:4b:cf:2e:9b:5b:58:f8:2e:fc:88:68:d4:36:e0: + 01:4c:0b:a4:ee:58:a0:ce:20:ef:78:b3:e6:50:56: + 51:4d:de:1e:3d:2f:5c:49:6b:3d:78:94:6b:2e:ab: + ae:0c:c0:b2:e8:29:a8:bc:ec:d2:05:a5:ac:3d:87: + 50:55:3e:48:55:b4:b7:91:e5:2e:ce:89:51:02:14: + 60:53:96:d7:7b:3e:61:2b:d3:54:f4:38:8d:55:78: + 48:f0:ad:67:39:fd:41:34:a3:fa:90:02:a0:d9:d4: + 01:fe:7a:8b:52:08:c9:0f:8b:5e:89:42:f1:bd:b7: + 40:35:b0:29:50:3c:66:46:59:31:e3:01:03:9d:16: + e8:87:8a:13:0b:ab:6e:bf:d9:b8:f0:fd:3d:82:4c: + cc:2f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3C:38:D7:FD:0C:54:14:F4:3A:DB:08:04:44:DB:4F:41:5D:E9:E9:DE + X509v3 Authority Key Identifier: + keyid:3C:38:D7:FD:0C:54:14:F4:3A:DB:08:04:44:DB:4F:41:5D:E9:E9:DE + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=wolfssh/emailAddress=info@wolfssl.com + serial:FA:24:EF:1A:5A:F2:B2:A4 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:c2:d1:ee:39:b4:6b:24:06:63:13:37:93:18:4f:e1:5f:12: + 5d:bf:03:88:ef:5b:bb:c8:b6:09:b6:e1:61:a2:df:4c:88:af: + e0:cf:fd:b9:48:52:6d:1c:91:45:e1:4b:51:c4:c1:c5:11:57: + 96:4f:74:d0:4d:58:70:4d:82:43:62:bd:e0:42:e1:76:a5:16: + 55:ca:01:c4:6e:90:ff:09:1c:9e:c9:f3:98:ab:5c:c0:5f:8a: + c3:80:f2:28:11:bd:99:e9:29:a9:ce:3c:aa:6b:fc:76:cc:93: + 8b:60:1f:bb:b3:e9:a2:a2:67:c9:3d:cb:e8:20:a4:bd:00:78: + 23:49:65:4a:96:50:09:db:f1:46:46:c1:08:9d:74:63:10:95: + b4:ec:da:85:a2:96:50:7b:af:e5:54:aa:96:4e:77:3a:88:8c: + f6:0e:5e:24:9f:22:ee:bc:a3:86:5d:11:48:63:65:eb:55:30: + 4b:75:22:5d:e5:14:89:cb:c9:52:21:5f:8f:47:3e:31:2c:58: + cd:5a:09:19:4d:d6:a4:0d:85:8d:86:ef:fe:fa:77:87:8f:c2: + 07:1f:20:ad:86:d9:94:91:e8:63:6a:2f:9d:bb:c1:f1:4e:85: + 02:8e:1d:9a:21:c4:94:28:0a:3d:9a:cb:19:87:4d:e0:a2:4c: + 0f:11:8a:6c +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIJAPok7xpa8rKkMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2VhdHRsZTEV +MBMGA1UEChMMd29sZlNTTCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4G +A1UEAxMHd29sZnNzaDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xNDA4MTUxOTQ2MjRaFw0xNzA1MTExOTQ2MjRaMIGUMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2VhdHRsZTEVMBMGA1UEChMM +d29sZlNTTCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHd29s +ZnNzaDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMV+XQzFR5VnrYn/2/p36B9206xvEIqTv+4b +k59bcXlM2NVtjtDSuWvodchz9V0cYWAn2nlAGKO0uPPDeU4Sb6IgRmwpUF34toKJ +NCIqFAB3OK3642GNccT/drw0PYW1ypb4RtmQD+QFMUvPLptbWPgu/Iho1DbgAUwL +pO5YoM4g73iz5lBWUU3eHj0vXElrPXiUay6rrgzAsugpqLzs0gWlrD2HUFU+SFW0 +t5HlLs6JUQIUYFOW13s+YSvTVPQ4jVV4SPCtZzn9QTSj+pACoNnUAf56i1IIyQ+L +XolC8b23QDWwKVA8ZkZZMeMBA50W6IeKEwurbr/ZuPD9PYJMzC8CAwEAAaOB/DCB ++TAdBgNVHQ4EFgQUPDjX/QxUFPQ62wgERNtPQV3p6d4wgckGA1UdIwSBwTCBvoAU +PDjX/QxUFPQ62wgERNtPQV3p6d6hgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRMwEQYD +VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRUwEwYDVQQKEwx3b2xm +U1NMIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5nMRAwDgYDVQQDEwd3b2xmc3No +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkA+iTvGlrysqQwDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAGMLR7jm0ayQGYxM3kxhP4V8S +Xb8DiO9bu8i2CbbhYaLfTIiv4M/9uUhSbRyRReFLUcTBxRFXlk900E1YcE2CQ2K9 +4ELhdqUWVcoBxG6Q/wkcnsnzmKtcwF+Kw4DyKBG9mekpqc48qmv8dsyTi2Afu7Pp +oqJnyT3L6CCkvQB4I0llSpZQCdvxRkbBCJ10YxCVtOzahaKWUHuv5VSqlk53OoiM +9g5eJJ8i7ryjhl0RSGNl61UwS3UiXeUUicvJUiFfj0c+MSxYzVoJGU3WpA2FjYbv +/vp3h4/CBx8grYbZlJHoY2ovnbvB8U6FAo4dmiHElCgKPZrLGYdN4KJMDxGKbA== +-----END CERTIFICATE----- diff --git a/certs/server-key.der b/certs/server-key.der new file mode 100644 index 0000000..d6813dd Binary files /dev/null and b/certs/server-key.der differ diff --git a/certs/server-key.pem b/certs/server-key.pem new file mode 100644 index 0000000..c9d242c --- /dev/null +++ b/certs/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAxX5dDMVHlWetif/b+nfoH3bTrG8QipO/7huTn1txeUzY1W2O +0NK5a+h1yHP1XRxhYCfaeUAYo7S488N5ThJvoiBGbClQXfi2gok0IioUAHc4rfrj +YY1xxP92vDQ9hbXKlvhG2ZAP5AUxS88um1tY+C78iGjUNuABTAuk7ligziDveLPm +UFZRTd4ePS9cSWs9eJRrLquuDMCy6CmovOzSBaWsPYdQVT5IVbS3keUuzolRAhRg +U5bXez5hK9NU9DiNVXhI8K1nOf1BNKP6kAKg2dQB/nqLUgjJD4teiULxvbdANbAp +UDxmRlkx4wEDnRboh4oTC6tuv9m48P09gkzMLwIDAQABAoIBACB4WSYbXVyUEjUp +KuqwQirCJ6UnEYonJpwoTooZx7tQxim4/I0ayD+UlaDiZ8nqO5xKkSH0RtjLgskZ +L12FrHL0aX+o/zykAqXNlxOy5Vz6PQhlwnKshbME6WmiESdlryxJH6TviZ1MuUEk +jB4g06ziVMS8r39iLvRoybIiQjYBa/p6ElxNGof1xGxgYEd4kUhuGEF7VWUkoarB +0XlUN3lNlRJ4AnkWvWjgix6Zc2+YKgX0Cafc6gZ9Dc+J/jmlr2P4k4VjdhfOEMPa +vB7FfEPMCfCHBHkeF9KYX1MGfpKpITvBSwNug44Z1D78u0Q/yvfIGYFoeJzznh45 +Dwc00rECgYEA9vtYtUk8j08ufW7OUHIRdgZ7dM9tEiDBdDvBoQKUw+GQqXToQydj +i9UgCCIdX9Rc2u3HY3Mu4CblUHKCckw6miV9EG08r+HktqZL+hPlBO/7osLNkMzc +feJVKQt7bjTzat3RSns+7DOP85GWpm2v2Br0i+7Eu+FJQoln/8bK2WcCgYEAzLRt +fVTyZMOjenTKL8qw4mNbry1iguqYO0pdzvcB3QT085OvWfDunEto8hOPNuWPhTX3 +IhXHQ9KryThJgIR/pdZXLdKm+DkKGy1ZTylfnB7eDnzStRgVWBvW6iqzES4Psoob +lFTMpy0yV/tWlzpmxh33BtPeEuRbH2Fan1nEkfkCgYBynx2BLNb1L2tE/Tq0rOub +mdCL2oQlCJyfY+gt4DPIYJOxgTcVi18wkx2FiMeXJMhfNkD1z4vurT55Qlt1zhjY +VxOenwOuIKjzd2QFUFxWGUXwOHYMgHbH2VVqchC7icl6TC2IYoBGQHvLL0L6RCd6 +pK/fjVUyWJCWV4yzcL/NewKBgEGNif53xIPGLsTZP6IcW5az0LmBZCmebI+YGgBc +E2mu265g3eeEgzTj5UCYSOWAj/xNss1kggJTJZXzg343cBUwVYykB7o3sefQFuiF +zEtXiy7ChEtf4f3sNF+auutGf9ph5cETgtIKZDPOlgUpu524HNI/6L7OB+w9peKf +wZYpAoGAEeuFwcwVfvscoz17th/J43qOyAWT+vAk7qZdyGBEF98jg8kA2OcWykI1 +q/KdTLW9dXz0NVWzA2eoLv3SDxD3NgAXdcXq4NhJiNI9/Zrk7kybAcMstPJKtquK +xXYH/xv41HqJ2IpfYjqqifV+HG6e37HeCWQDj1zyZulEMyrRN1s= +-----END RSA PRIVATE KEY----- diff --git a/examples/server/server.c b/examples/server/server.c index 462c8fc..9aecae2 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -47,6 +47,7 @@ typedef int SOCKET_T; static const char* wolfsshIP = "127.0.0.1"; #endif #define SERVER_PORT_NUMBER 22222 +#define SCRATCH_BUFFER_SIZE 1200 #if defined(__MACH__) || defined(USE_WINDOWS_API) #ifndef _SOCKLEN_T @@ -256,6 +257,35 @@ static THREAD_RETURN CYASSL_THREAD server_worker(void* vArgs) } +static int load_file(const char* fileName, uint8_t* buf, uint32_t bufSz) +{ + FILE* file; + uint32_t fileSz; + uint32_t readSz; + + if (fileName == NULL) return 0; + + file = fopen(fileName, "rb"); + if (file == NULL) return 0; + fseek(file, 0, SEEK_END); + fileSz = (uint32_t)ftell(file); + rewind(file); + + if (fileSz > bufSz) { + fclose(file); + return 0; + } + + readSz = (uint32_t)fread(buf, 1, fileSz, file); + if (readSz < fileSz) { + fclose(file); + return 0; + } + + return fileSz; +} + + int main(void) { WOLFSSH_CTX* ctx = NULL; @@ -276,6 +306,33 @@ int main(void) exit(EXIT_FAILURE); } + { + uint8_t buf[SCRATCH_BUFFER_SIZE]; + uint32_t bufSz; + + bufSz = load_file("./certs/server-cert.der", buf, SCRATCH_BUFFER_SIZE); + if (bufSz == 0) { + fprintf(stderr, "Couldn't load certificate file.\n"); + exit(EXIT_FAILURE); + } + if (wolfSSH_CTX_UseCert_buffer(ctx, + buf, bufSz, WOLFSSH_FORMAT_ASN1) < 0) { + fprintf(stderr, "Couldn't use certificate buffer.\n"); + exit(EXIT_FAILURE); + } + + bufSz = load_file("./certs/server-key.der", buf, SCRATCH_BUFFER_SIZE); + if (bufSz == 0) { + fprintf(stderr, "Couldn't load key file.\n"); + exit(EXIT_FAILURE); + } + if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, + buf, bufSz, WOLFSSH_FORMAT_ASN1) < 0) { + fprintf(stderr, "Couldn't use key buffer.\n"); + exit(EXIT_FAILURE); + } + } + tcp_bind(&listenFd, SERVER_PORT_NUMBER, 0); for (;;) { diff --git a/src/internal.c b/src/internal.c index 7082a17..37b064a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -88,6 +88,27 @@ const char* GetErrorString(int err) case WS_RECV_OVERFLOW_E: return "receive buffer overflow"; + case WS_VERSION_E: + return "peer version unsupported"; + + case WS_SEND_OOB_READ_E: + return "attempted to read buffer out of bounds"; + + case WS_INPUT_CASE_E: + return "bad process input state, programming error"; + + case WS_BAD_FILETYPE_E: + return "bad filetype"; + + case WS_UNIMPLEMENTED_E: + return "feature not implemented"; + + case WS_RSA_E: + return "RSA buffer error"; + + case WS_BAD_FILE_E: + return "bad file"; + default: return "Unknown error code"; } diff --git a/src/ssh.c b/src/ssh.c index d2be355..1737879 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include int wolfSSH_Init(void) @@ -94,10 +97,13 @@ WOLFSSH_CTX* wolfSSH_CTX_new(uint8_t side, void* heap) static void CtxResourceFree(WOLFSSH_CTX* ctx) { - /* when context holds resources, free here */ - (void)ctx; - WLOG(WS_LOG_DEBUG, "Enter CtxResourceFree()"); + if (ctx->privateKey) { + WMEMSET(ctx->privateKey, 0, ctx->privateKeySz); + WFREE(ctx->privateKey, heap, DYNTYPE_KEY); + } + WFREE(ctx->cert, heap, DYNTYPE_CERT); + WFREE(ctx->caCert, heap, DYNTYPE_CA); } @@ -291,17 +297,78 @@ int wolfSSH_accept(WOLFSSH* ssh) static int ProcessBuffer(WOLFSSH_CTX* ctx, const uint8_t* in, uint32_t inSz, int format, int type) { - (void)ctx; - (void)in; - (void)inSz; - (void)format; - (void)type; + int dynamicType; + void* heap; + uint8_t* der; + uint32_t derSz; + + if (ctx == NULL || in == NULL || inSz == 0) + return WS_BAD_ARGUMENT; + + if (format != WOLFSSH_FORMAT_ASN1 && format != WOLFSSH_FORMAT_PEM && + format != WOLFSSH_FORMAT_RAW) + return WS_BAD_FILETYPE_E; + + if (type == BUFTYPE_CA) + dynamicType = DYNTYPE_CA; + else if (type == BUFTYPE_CERT) + dynamicType = DYNTYPE_CERT; + else if (type == BUFTYPE_PRIVKEY) + dynamicType = DYNTYPE_KEY; + else + return WS_BAD_ARGUMENT; + + heap = ctx->heap; + + if (format == WOLFSSH_FORMAT_PEM) + return WS_UNIMPLEMENTED_E; + else { + /* format is ASN1 or RAW */ + der = (uint8_t*)WMALLOC(inSz, heap, dynamicType); + if (der == NULL) + return WS_MEMORY_E; + WMEMCPY(der, in, inSz); + derSz = inSz; + } + + /* Maybe decrypt */ + + if (type == BUFTYPE_CERT) { + if (ctx->cert) + WFREE(ctx->cert, heap, dynamicType); + ctx->cert = der; + ctx->certSz = derSz; + } + else if (type == BUFTYPE_PRIVKEY) { + if (ctx->privateKey) + WFREE(ctx->privateKey, heap, dynamicType); + ctx->privateKey = der; + ctx->privateKeySz = derSz; + } + else { + WFREE(der, heap, dynamicType); + return WS_UNIMPLEMENTED_E; + } + + if (type == BUFTYPE_PRIVKEY && format != WOLFSSH_FORMAT_RAW) { + /* Check RSA key */ + RsaKey key; + uint32_t scratch = 0; + + if (InitRsaKey(&key, NULL) < 0) + return WS_RSA_E; + + if (RsaPrivateKeyDecode(der, &scratch, &key, derSz) < 0) + return WS_BAD_FILE_E; + + FreeRsaKey(&key); + } return WS_SUCCESS; } -int wolfSSH_CTX_use_private_key_buffer(WOLFSSH_CTX* ctx, +int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX* ctx, const uint8_t* in, uint32_t inSz, int format) { WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_use_private_key_buffer()"); @@ -309,7 +376,7 @@ int wolfSSH_CTX_use_private_key_buffer(WOLFSSH_CTX* ctx, } -int wolfSSH_CTX_use_cert_buffer(WOLFSSH_CTX* ctx, +int wolfSSH_CTX_UseCert_buffer(WOLFSSH_CTX* ctx, const uint8_t* in, uint32_t inSz, int format) { WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_use_certificate_buffer()"); @@ -317,7 +384,7 @@ int wolfSSH_CTX_use_cert_buffer(WOLFSSH_CTX* ctx, } -int wolfSSH_CTX_use_ca_cert_buffer(WOLFSSH_CTX* ctx, +int wolfSSH_CTX_UseCaCert_buffer(WOLFSSH_CTX* ctx, const uint8_t* in, uint32_t inSz, int format) { WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_use_ca_certificate_buffer()"); diff --git a/wolfssh/error.h b/wolfssh/error.h index 8cd5122..9408613 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -38,7 +38,7 @@ extern "C" { /* main public return values */ -enum WS_ReturnValues { +enum WS_ErrorCodes { WS_SUCCESS = 0, /* function success */ WS_FATAL_ERROR = -1, /* general function failure */ WS_BAD_ARGUMENT = -2, /* bad function argument */ @@ -54,7 +54,11 @@ enum WS_ReturnValues { WS_RECV_OVERFLOW_E = -12, WS_VERSION_E = -13, /* Peer using wrong version of SSH */ WS_SEND_OOB_READ_E = -14, - WS_INPUT_CASE_E = -15 + WS_INPUT_CASE_E = -15, + WS_BAD_FILETYPE_E = -16, + WS_UNIMPLEMENTED_E = -17, + WS_RSA_E = -18, + WS_BAD_FILE_E = -19 }; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 3f8f6d7..41327ef 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -118,6 +118,13 @@ struct WOLFSSH_CTX { void* heap; /* heap hint */ WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */ WS_CallbackIOSend ioSendCb; /* I/O Send Callback */ + + uint8_t* cert; /* Owned by CTX */ + uint32_t certSz; + uint8_t* caCert; /* Owned by CTX */ + uint32_t caCertSz; + uint8_t* privateKey; /* Owned by CTX */ + uint32_t privateKeySz; }; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 04a7ded..9ef7e94 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -76,11 +76,11 @@ WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH*, void*); WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH*); WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH*); -WOLFSSH_API int wolfSSH_CTX_use_private_key_buffer(WOLFSSH_CTX*, +WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*, const uint8_t*, uint32_t, int); -WOLFSSH_API int wolfSSH_CTX_use_cert_buffer(WOLFSSH_CTX*, +WOLFSSH_API int wolfSSH_CTX_UseCert_buffer(WOLFSSH_CTX*, const uint8_t*, uint32_t, int); -WOLFSSH_API int wolfSSH_CTX_use_ca_cert_buffer(WOLFSSH_CTX*, +WOLFSSH_API int wolfSSH_CTX_UseCaCert_buffer(WOLFSSH_CTX*, const uint8_t*, uint32_t, int); WOLFSSH_API int wolfSSH_accept(WOLFSSH* ssh);