From 7e2674c29a7cadbd305e52afdb83a4782b65fb5d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 15 Aug 2014 14:20:42 -0700 Subject: [PATCH] 1. Added test certificate and private key. 2. Added code to load single certificate and private key from buffers. --- certs/server-cert.der | Bin 0 -> 1198 bytes certs/server-cert.pem | 87 ++++++++++++++++++++++++++++++++++++++ certs/server-key.der | Bin 0 -> 1190 bytes certs/server-key.pem | 27 ++++++++++++ examples/server/server.c | 57 +++++++++++++++++++++++++ src/internal.c | 21 +++++++++ src/ssh.c | 89 ++++++++++++++++++++++++++++++++++----- wolfssh/error.h | 8 +++- wolfssh/internal.h | 7 +++ wolfssh/ssh.h | 6 +-- 10 files changed, 286 insertions(+), 16 deletions(-) create mode 100644 certs/server-cert.der create mode 100644 certs/server-cert.pem create mode 100644 certs/server-key.der create mode 100644 certs/server-key.pem diff --git a/certs/server-cert.der b/certs/server-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..d3f75c219f57d46f882ba7c42a6497a1b9691c7d GIT binary patch literal 1198 zcmXqLVp(O-#5`#MGZP~d6DPwjmG@FnpEfNq;AP{~YV&CO&dbQi%F1BSIK`0LfRl|m zl!Z;0DKywn*gz1(;SlBuPb|*J%u6rH&odM--~$P=3$q8OCYF@sq#BAE2!lkpgn7#I zbJBu?eH1+NlJyKl41_?!+``BzWZ_JGlcd&#?q1?LprS8RS35EkfrPtI09 z#xvWtVoJ8&>UBH^HoeeXvFFVt)}?D~+XF)FJVLi@pZHYoTxTGYNJ8+m>(zFN+LuGV zSoDTgczjr!Zu!^IWbv;FObc#aVfEqt*4yGG418maVA`KriGS3xz z(cUG@y*h9I%^e^9+BW%|(Pv_2WMEv}_{X5}ColythsyG?h_Q&+SX}?h6C(1(>NW?9 z%WZ$h*q1Nw88n^*$t$xo9yDm&*ML>c!p2!k8mAA^w9tf<=XgL~5oTdEU}j|ekDNe& zIS`mY7#SoEU3_P`C0m6pS=fBCg#W{Mq1gS*9q*%epV-E^?P21g`#v4(ADsWY(<3NX zW}@pu@4zDmj|zrQ^DnvJ8&Tlf=1a|$=WJGG|0z2&xjR9A_vV+27NwuGJ^eyq$zFyEWzSTvX#t$KKf1Xc)2we0ij%+Y8M@cli4Ow2C=0|5X50)hbmAb43O8(mzK5;Z9*>aap8!Y8FC5sD`!oG4C; z8OOU&#wob`jT*>5l$D_3XUXb2oJx@)^hVgrg2@>#U4^W2^l5*n|2(7urOlTUvgKU* zJqTsOa;$~31nFs_5hrD@EJ+`v?}?pExj`h19w5`K;#9=EuYY1L^k~VlB0@F+Yx;T; zTumB>^~7voU`Ke7NNyNGdsSs5p{l{rc~m!fO_dUO0(lm_XyA(;nR9QLDh2cjr`+lW zeGSiv{yC+uWB8MWV|EwL5X0KM9>sh^%n9&^1bH48(wJXU27Z#MAv?iK18#$k8Pq=f zyF@?A_sAK6Xn36So*p?52Q<>L0)c@5_WM}1Nj#5FE`4s!P;wD=277eRZ4w~CbUVSJ z0+hqykg0U&LnmX4)gTBW9beR3+U>_&}e0)c@5 z%(QKNRPtoQqk448FUqjuV_UB+VuI?JJ4#*7_W|7m^z)OiS@7Fk2d9xg*Epg z6~{x;tI0S?fP{ag)>kdkruaDu8!cH+DPNo(-VS`ywHOsx8`kP7vk@*2vWgp&RLrL> zGFSUnmpW#~9rp&)-V)?nA7NUbS;Ud~0)c>XpB;fL*7YxIMEyFntm~VZ(2LrHB?z3K zW9Tj5Gss|*v4J-gi(fF49fgR;mn6tvHbC{yi|(yHc|u!t&KTHN6P}*~t{|xMcVq=n zTvi!H@Hlo1fOf~(Rcdk&yNStqOf86FfJQ)j%P&IuL??QruiuSTGFXt7SB$f8zs-9B zfq+4ciT-!QgT^kz**~HjTb8rXxq)OUo@|ep8US1qX|CI@VBP10gEZsiK$uA7fRFr5 zvdv_I0#hZG^Migja1}6BjHCy;H?il?7U+e{OIM37!h}m-;r;A1Uz)n>Mt|C2<-rqz z(h6iV&Xxr!yPdck(m&|F&Ijy0rQ)B#mMH>(fD!A3!ORtY`y8V^d$u3R<9d$B1(W*l zB<`kN$Y4Yl-y?&`0NCdi%0e}(@|{ezy>)!_HC3|%XQ(dy(hm^#HUJlO#p>YLNr=)t z{hH+NOq&72EVS}UwyTQ8b_f3(_|$rd*ot3bI;x5FejIL|-?82aWCM>}@@DBoGb+(H ETX=ayjQ{`u literal 0 HcmV?d00001 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);