server-tls.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* server-tls.c
  2. *
  3. * Copyright (C) 2006-2022 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. /* socket includes */
  25. #include <sys/socket.h>
  26. #include <arpa/inet.h>
  27. #include <netinet/in.h>
  28. #include <unistd.h>
  29. /* wolfSSL */
  30. #include <wolfssl/options.h>
  31. #include <wolfssl/ssl.h>
  32. #include <wolfssl/wolfcrypt/ecc.h>
  33. #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h> /* functions for blob/cover*/
  34. #define DEFAULT_PORT 11111
  35. #define ECC_KEY_SIZE 32
  36. #undef USE_CERT_BUFFERS_256
  37. #define USE_CERT_BUFFERS_256
  38. #include <wolfssl/certs_test.h>
  39. /* creates a blob then opens it, returns 0 on success */
  40. static int test_blob(byte* key, int keySz)
  41. {
  42. int ret, i;
  43. byte out[keySz + WC_CAAM_BLOB_SZ];
  44. int outSz;
  45. int keyOutSz;
  46. byte keymod[WC_CAAM_BLACK_KEYMOD_SZ];
  47. int keymodSz = WC_CAAM_BLACK_KEYMOD_SZ;
  48. /* using a key mod of all 1's */
  49. XMEMSET(keymod, 1, keymodSz);
  50. /* example of creating black blog with key for later */
  51. outSz = keySz + WC_CAAM_BLOB_SZ;
  52. ret = wc_caamCreateBlob_ex(key, keySz, out, (word32*)&outSz,
  53. WC_CAAM_BLOB_BLACK, keymod, keymodSz);
  54. if (ret != 0) {
  55. printf("Error creating black blob\n");
  56. return -1;
  57. }
  58. printf("created black blob :");
  59. for (i = 0; i < outSz; i++)
  60. printf("%02X,", out[i]);
  61. printf("\n");
  62. /* open black blob and overwrite key, this is to show that the opened blob
  63. * can be used for the upcoming TLS connection */
  64. memset(key, 0, keySz);
  65. keyOutSz = keySz;
  66. ret = wc_caamOpenBlob_ex(out, outSz, key, (word32*)&keyOutSz,
  67. WC_CAAM_BLOB_BLACK, keymod, keymodSz);
  68. if (ret != 0) {
  69. printf("Error opening black blob\n");
  70. }
  71. return ret;
  72. }
  73. /* example of covering an existing key and then making a black blob with it
  74. * note that generating an ECC completely in secure memory already covered can
  75. * be done by call wc_ecc_make_key */
  76. int cover(ecc_key* keyOut, const byte* der, word32 derSz)
  77. {
  78. int ret;
  79. ecc_key notSecure;
  80. word32 idx = 0;
  81. /* format bit plus public key x and y parameter */
  82. byte x963[(ECC_KEY_SIZE*2) + 1];
  83. word32 x963Sz = (ECC_KEY_SIZE*2) + 1;
  84. /* uncovered private key */
  85. byte d[ECC_KEY_SIZE];
  86. word32 dSz = ECC_KEY_SIZE;
  87. byte blackKey[ECC_KEY_SIZE + WC_CAAM_MAC_SZ];
  88. word32 blackKeySz = ECC_KEY_SIZE + WC_CAAM_MAC_SZ;
  89. /* The DER buffer for test case does not contain a black key, here we will
  90. * extract the key information, cover it (make it a black key), and then
  91. * import that into 'keyOut' which will create a secure partition on import.
  92. *
  93. * These steps of covering and importing can be avoided with a call to
  94. * wc_ecc_make_key which creates a new black key that never leaves the CAAM.
  95. * The cover process is only being used to make use of an existing key that
  96. * matches the test certificate.
  97. */
  98. wc_ecc_init(&notSecure);
  99. if (wc_EccPrivateKeyDecode(der, &idx, &notSecure, derSz) != 0) {
  100. printf("Error extracting ECC der buffer\n");
  101. ret = -1;
  102. goto done;
  103. }
  104. /* Get the uncovered key values */
  105. if (wc_ecc_export_private_raw(&notSecure, NULL, NULL, NULL, NULL, d, &dSz)
  106. != 0) {
  107. printf("Error getting ecc key values\n");
  108. ret = -1;
  109. goto done;
  110. }
  111. if (wc_ecc_export_x963(&notSecure, x963, &x963Sz) != 0) {
  112. printf("Error getting ecc public key\n");
  113. ret = -1;
  114. goto done;
  115. }
  116. /* Cover up the private key (make it a black key, encrypting with AES-CCM)*/
  117. XMEMSET(blackKey, 0, blackKeySz);
  118. if (wc_caamCoverKey(d, dSz, blackKey, &blackKeySz, 0) != 0) {
  119. printf("Error covering up the private key\n");
  120. ret = -1;
  121. goto done;
  122. }
  123. /* Sanity check to compare covered key versus plain text */
  124. if (XMEMCMP(d, blackKey, dSz) == 0) {
  125. printf("Something went wrong with key cover!!\n");
  126. ret = -1;
  127. goto done;
  128. }
  129. if (test_blob(blackKey, blackKeySz - WC_CAAM_MAC_SZ) != 0) {
  130. printf("test blob failed\n");
  131. ret = -1;
  132. goto done;
  133. }
  134. /* zero out the plain text buffer and free key */
  135. XMEMSET(d, 0, dSz);
  136. /* Import the black key into a ecc_key structure (this step tries to create
  137. * a partition of secure memory marked CPS)
  138. */
  139. ret = wc_ecc_import_private_key(blackKey, blackKeySz, x963, x963Sz, keyOut);
  140. if (ret != 0) {
  141. printf("Error importing black key into secure memory %d\n", ret);
  142. wc_ecc_free(keyOut);
  143. goto done;
  144. }
  145. printf("blackKeySz = %d, virtual secure address ecc_key.blackKey = 0x%08X\n",
  146. blackKeySz, keyOut->blackKey);
  147. ret = 0;
  148. done:
  149. wc_ecc_free(&notSecure);
  150. return ret;
  151. }
  152. /* callback function for creating ECC signatures */
  153. static int TLS_ECC_Sign_callback(WOLFSSL* ssl, const unsigned char* in,
  154. unsigned int inSz, unsigned char* out, word32* outSz,
  155. const unsigned char* keyDer, unsigned int keySz,
  156. void* ctx)
  157. {
  158. ecc_key* blackKey;
  159. printf("Using ECC sign callback\n");
  160. if (ctx == NULL) {
  161. printf("Was expecting a black key passed along with WOLFSSL\n");
  162. return -1;
  163. }
  164. blackKey = (ecc_key*)ctx;
  165. return wc_ecc_sign_hash(in, inSz, out, outSz, NULL, blackKey);
  166. }
  167. /* callback function to do ECDH operation in TLS handshake */
  168. static int TLS_ECDH_callback(WOLFSSL* ssl, struct ecc_key* otherKey,
  169. unsigned char* pubKeyDer, word32* pubKeySz,
  170. unsigned char* out, word32* outlen,
  171. int side, void* ctx)
  172. {
  173. int ret= -1;
  174. printf("Using ECDH callback\n");
  175. if (ctx == NULL) {
  176. printf("Was expecting a black key passed along with WOLFSSH\n");
  177. return -1;
  178. }
  179. /* this is being called from client end */
  180. if (side == WOLFSSL_CLIENT_END) {
  181. }
  182. /* this is being called from server end */
  183. if (side == WOLFSSL_SERVER_END) {
  184. ecc_key pub;
  185. wc_ecc_init(&pub);
  186. if (wc_ecc_import_x963(pubKeyDer, *pubKeySz, &pub) != 0) {
  187. printf("Issue decoding the public key to generate shared secret\n");
  188. wc_ecc_free(&pub);
  189. return -1;
  190. }
  191. /* otherKey is the ephemeral private key created with ECDHE cipher
  192. * suites. As long as EccKeyGenCb has not been set this key was created
  193. * with wc_ecc_make_key_ex, which when used with NIST P256 it will
  194. * automatically try to create a secure black key
  195. */
  196. ret = wc_ecc_shared_secret(otherKey, &pub, out, outlen);
  197. wc_ecc_free(&pub);
  198. }
  199. return ret;
  200. }
  201. int main()
  202. {
  203. int sockfd;
  204. int connd = 0;
  205. struct sockaddr_in servAddr;
  206. struct sockaddr_in clientAddr;
  207. socklen_t size = sizeof(clientAddr);
  208. char buff[256];
  209. size_t len;
  210. int ret;
  211. const char* reply = "I hear ya fa shizzle!\n";
  212. ecc_key blackKey;
  213. /* declare wolfSSL objects */
  214. WOLFSSL_CTX* ctx = NULL;
  215. WOLFSSL* ssl = NULL;
  216. /* Initialize wolfSSL */
  217. if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
  218. fprintf(stderr, "issue with wolfSSL_Init()\n");
  219. return -1;
  220. }
  221. wolfSSL_Debugging_ON();
  222. wc_ecc_init(&blackKey);
  223. /* Create a socket that uses an internet IPv4 address,
  224. * Sets the socket to be stream based (TCP),
  225. * 0 means choose the default protocol. */
  226. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  227. fprintf(stderr, "ERROR: failed to create the socket\n");
  228. goto end;
  229. }
  230. /* Create and initialize WOLFSSL_CTX */
  231. if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) {
  232. fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
  233. goto end;
  234. }
  235. /* Load server certificates into WOLFSSL_CTX */
  236. if (wolfSSL_CTX_use_certificate_buffer(ctx, serv_ecc_der_256,
  237. sizeof_serv_ecc_der_256, SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
  238. printf("error loading in certificate buffer\n");
  239. goto end;
  240. }
  241. // wolfSSL_CTX_use_PrivateKey_buffer(ctx, ecc_key_der_256, sizeof_ecc_key_der_256, SSL_FILETYPE_ASN1);
  242. if (cover(&blackKey, ecc_key_der_256, sizeof_ecc_key_der_256) != 0) {
  243. printf("error covering up key\n");
  244. goto end;
  245. }
  246. /* set signing callback to use during TLS connection */
  247. wolfSSL_CTX_SetEccSignCb(ctx, TLS_ECC_Sign_callback);
  248. /* set ECDH shared secret callback to use during TLS connection */
  249. wolfSSL_CTX_SetEccSharedSecretCb(ctx, TLS_ECDH_callback);
  250. /* Initialize the server address struct with zeros */
  251. memset(&servAddr, 0, sizeof(servAddr));
  252. /* Fill in the server address */
  253. servAddr.sin_family = AF_INET; /* using IPv4 */
  254. servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */
  255. servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */
  256. /* Bind the server socket to our port */
  257. if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) {
  258. fprintf(stderr, "ERROR: failed to bind\n");
  259. goto end;
  260. }
  261. /* Listen for a new connection, allow 5 pending connections */
  262. if (listen(sockfd, 5) == -1) {
  263. fprintf(stderr, "ERROR: failed to listen\n");
  264. goto end;
  265. }
  266. /* Continue to accept clients until shutdown is issued */
  267. printf("Waiting for a connection...\n");
  268. /* Accept client connections */
  269. if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size)) == -1) {
  270. fprintf(stderr, "ERROR: failed to accept the connection\n\n");
  271. goto end;
  272. }
  273. /* Create a WOLFSSL object */
  274. if ((ssl = wolfSSL_new(ctx)) == NULL) {
  275. fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
  276. goto end;
  277. }
  278. /* Attach wolfSSL to the socket */
  279. wolfSSL_set_fd(ssl, connd);
  280. /* associate the covered up black key with the WOLFSSH structure,
  281. * this will then get passed as the last argument to the callbacks */
  282. wolfSSL_SetEccSignCtx(ssl, (void*)&blackKey);
  283. wolfSSL_SetEccSharedSecretCtx(ssl, (void*)&blackKey);
  284. /* Establish TLS connection */
  285. ret = wolfSSL_accept(ssl);
  286. if (ret != SSL_SUCCESS) {
  287. fprintf(stderr, "wolfSSL_accept error = %d\n",
  288. wolfSSL_get_error(ssl, ret));
  289. goto end;
  290. }
  291. printf("Client connected successfully\n");
  292. /* Read the client data into our buff array */
  293. memset(buff, 0, sizeof(buff));
  294. if (wolfSSL_read(ssl, buff, sizeof(buff)-1) == -1) {
  295. fprintf(stderr, "ERROR: failed to read\n");
  296. goto end;
  297. }
  298. /* Print to stdout any data the client sends */
  299. printf("Client: %s\n", buff);
  300. /* Write our reply into buff */
  301. memset(buff, 0, sizeof(buff));
  302. memcpy(buff, reply, strlen(reply));
  303. len = strnlen(buff, sizeof(buff));
  304. /* Reply back to the client */
  305. if (wolfSSL_write(ssl, buff, len) != len) {
  306. fprintf(stderr, "ERROR: failed to write\n");
  307. goto end;
  308. }
  309. end:
  310. /* Cleanup after this connection */
  311. wolfSSL_free(ssl); /* Free the wolfSSL object */
  312. close(connd); /* Close the connection to the client */
  313. wc_ecc_free(&blackKey);
  314. printf("Shutdown complete\n");
  315. /* Cleanup and return */
  316. wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
  317. wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
  318. close(sockfd); /* Close the socket listening for clients */
  319. return 0; /* Return reporting a success */
  320. }