Changes In Branch crypto Through [0cd384c2ff] Excluding Merge-Ins
This is equivalent to a diff from ec0cc9fbdf to 0cd384c2ff
2023-10-28
| ||
17:20 | Optimized TLS channel type definition check-in: 914ac6b2a4 user: bohagan tags: trunk | |
2023-10-10
| ||
02:43 | Added hash command to calculate hash using any OpenSSL digest. Added convenience commands for md4, md5, sha1, and sha-256 digests. check-in: cafd2dc6ba user: bohagan tags: crypto | |
00:06 | Created cryptography branch check-in: 0cd384c2ff user: bohagan tags: crypto | |
2023-10-09
| ||
19:08 | Updated to latest TEA and Tcl Config check-in: ec0cc9fbdf user: bohagan tags: trunk | |
2023-09-24
| ||
20:12 | Moved definition of Append to List macros to tlsInt.h. Updated tls.c to use Append to List macros. check-in: 28d6418fa7 user: bohagan tags: trunk | |
Modified generic/tls.c from [f4a59d7949] to [a4b3c334bf].
︙ | ︙ | |||
442 443 444 445 446 447 448 | cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("error", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); if (msg != NULL) { Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(msg, -1)); | | | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("error", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); if (msg != NULL) { Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(msg, -1)); } else if ((msg = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), NULL)) != NULL) { Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(msg, -1)); } else { listPtr = Tcl_NewListObj(0, NULL); while ((err = ERR_get_error()) != 0) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(ERR_reason_error_string(err), -1)); } |
︙ | ︙ | |||
549 550 551 552 553 554 555 | } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) statePtr); /* If successful, pass back password string and truncate if too long */ if (code == TCL_OK) { | | | | | | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) statePtr); /* If successful, pass back password string and truncate if too long */ if (code == TCL_OK) { int len; char *ret = (char *) Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len); if (len > size-1) { len = size-1; } strncpy(buf, ret, (size_t) len); buf[len] = '\0'; Tcl_Release((ClientData) interp); return(len); } Tcl_Release((ClientData) interp); return -1; } /* *------------------------------------------------------------------- |
︙ | ︙ | |||
611 612 613 614 615 616 617 | cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("session", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); /* Session id */ session_id = SSL_SESSION_get_id(session, &ulen); | | | | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 | cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("session", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); /* Session id */ session_id = SSL_SESSION_get_id(session, &ulen); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewByteArrayObj(session_id, (int) ulen)); /* Session ticket */ SSL_SESSION_get0_ticket(session, &ticket, &len2); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewByteArrayObj(ticket, (int) len2)); /* Lifetime - number of seconds */ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewLongObj((long) SSL_SESSION_get_ticket_lifetime_hint(session))); /* Eval callback command */ Tcl_IncrRefCount(cmdPtr); |
︙ | ︙ | |||
900 901 902 903 904 905 906 | servername = (const char *)p; /* Create command to eval */ cmdPtr = Tcl_DuplicateObj(statePtr->vcmd); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("hello", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); | | | 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 | servername = (const char *)p; /* Create command to eval */ cmdPtr = Tcl_DuplicateObj(statePtr->vcmd); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("hello", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(servername, (int) len)); /* Eval callback command */ Tcl_IncrRefCount(cmdPtr); if ((code = EvalCallback(interp, statePtr, cmdPtr)) > 1) { res = SSL_CLIENT_HELLO_RETRY; *alert = SSL_R_TLSV1_ALERT_USER_CANCELLED; } else if (code == 1) { |
︙ | ︙ | |||
1169 1170 1171 1172 1173 1174 1175 | if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); return(TCL_ERROR); } ERR_clear_error(); | | | 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 | if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); return(TCL_ERROR); } ERR_clear_error(); chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); if (chan == (Tcl_Channel) NULL) { return(TCL_ERROR); } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { |
︙ | ︙ | |||
1247 1248 1249 1250 1251 1252 1253 | Tcl_Channel chan; /* The channel to set a mode on. */ State *statePtr; /* client state for ssl socket */ SSL_CTX *ctx = NULL; Tcl_Obj *script = NULL; Tcl_Obj *password = NULL; Tcl_Obj *vcmd = NULL; Tcl_DString upperChannelTranslation, upperChannelBlocking, upperChannelEncoding, upperChannelEOFChar; | | < | | | 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 | Tcl_Channel chan; /* The channel to set a mode on. */ State *statePtr; /* client state for ssl socket */ SSL_CTX *ctx = NULL; Tcl_Obj *script = NULL; Tcl_Obj *password = NULL; Tcl_Obj *vcmd = NULL; Tcl_DString upperChannelTranslation, upperChannelBlocking, upperChannelEncoding, upperChannelEOFChar; int idx, len; int flags = TLS_TCL_INIT; int server = 0; /* is connection incoming or outgoing? */ char *keyfile = NULL; char *certfile = NULL; unsigned char *key = NULL; int key_len = 0; unsigned char *cert = NULL; int cert_len = 0; char *ciphers = NULL; char *ciphersuites = NULL; char *CAfile = NULL; char *CAdir = NULL; char *DHparams = NULL; char *model = NULL; char *servername = NULL; /* hostname for Server Name Indication */ |
︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 | if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel ?options?"); return TCL_ERROR; } ERR_clear_error(); | | | | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 | if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel ?options?"); return TCL_ERROR; } ERR_clear_error(); chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); for (idx = 2; idx < objc; idx++) { char *opt = Tcl_GetStringFromObj(objv[idx], NULL); if (opt[0] != '-') break; OPTOBJ("-alpn", alpn); OPTSTR("-cadir", CAdir); OPTSTR("-cafile", CAfile); |
︙ | ︙ | |||
1422 1423 1424 1425 1426 1427 1428 | "\": not a TLS channel", NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "CHANNEL", "INVALID", (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; } ctx = ((State *)Tcl_GetChannelInstanceData(chan))->ctx; } else { | | | | 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 | "\": not a TLS channel", NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "CHANNEL", "INVALID", (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; } ctx = ((State *)Tcl_GetChannelInstanceData(chan))->ctx; } else { if ((ctx = CTX_Init(statePtr, server, proto, keyfile, certfile, key, cert, key_len, cert_len, CAdir, CAfile, ciphers, ciphersuites, level, DHparams)) == NULL) { Tls_Free((char *) statePtr); return TCL_ERROR; } } statePtr->ctx = ctx; |
︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 | /* Enable Application-Layer Protocol Negotiation. Examples are: http/1.0, http/1.1, h2, h3, ftp, imap, pop3, xmpp-client, xmpp-server, mqtt, irc, etc. */ if (alpn) { /* Convert a TCL list into a protocol-list in wire-format */ unsigned char *protos, *p; unsigned int protos_len = 0; | < | | | | | | | 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 | /* Enable Application-Layer Protocol Negotiation. Examples are: http/1.0, http/1.1, h2, h3, ftp, imap, pop3, xmpp-client, xmpp-server, mqtt, irc, etc. */ if (alpn) { /* Convert a TCL list into a protocol-list in wire-format */ unsigned char *protos, *p; unsigned int protos_len = 0; int i, len, cnt; Tcl_Obj **list; if (Tcl_ListObjGetElements(interp, alpn, &cnt, &list) != TCL_OK) { Tls_Free((char *) statePtr); return TCL_ERROR; } /* Determine the memory required for the protocol-list */ for (i = 0; i < cnt; i++) { Tcl_GetStringFromObj(list[i], &len); if (len > 255) { Tcl_AppendResult(interp, "ALPN protocol name too long", (char *) NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "ALPN", "FAILED", (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; } protos_len += 1 + len; } /* Build the complete protocol-list */ protos = ckalloc(protos_len); /* protocol-lists consist of 8-bit length-prefixed, byte strings */ for (i = 0, p = protos; i < cnt; i++) { char *str = Tcl_GetStringFromObj(list[i], &len); *p++ = len; memcpy(p, str, len); p += len; } /* SSL_set_alpn_protos makes a copy of the protocol-list */ /* Note: This functions reverses the return value convention */ if (SSL_set_alpn_protos(statePtr->ssl, protos, protos_len)) { Tcl_AppendResult(interp, "failed to set ALPN protocols", (char *) NULL); |
︙ | ︙ | |||
1718 1719 1720 1721 1722 1723 1724 | int off = 0; int load_private_key; const SSL_METHOD *method; dprintf("Called"); if (!proto) { | | | | | | | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 | int off = 0; int load_private_key; const SSL_METHOD *method; dprintf("Called"); if (!proto) { Tcl_AppendResult(interp, "no valid protocol selected", NULL); return NULL; } /* create SSL context */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(NO_SSL2) || defined(OPENSSL_NO_SSL2) if (ENABLED(proto, TLS_PROTO_SSL2)) { Tcl_AppendResult(interp, "SSL2 protocol not supported", NULL); return NULL; } #endif #if defined(NO_SSL3) || defined(OPENSSL_NO_SSL3) if (ENABLED(proto, TLS_PROTO_SSL3)) { Tcl_AppendResult(interp, "SSL3 protocol not supported", NULL); return NULL; } #endif #if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) if (ENABLED(proto, TLS_PROTO_TLS1)) { Tcl_AppendResult(interp, "TLS 1.0 protocol not supported", NULL); return NULL; } #endif #if defined(NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1) if (ENABLED(proto, TLS_PROTO_TLS1_1)) { Tcl_AppendResult(interp, "TLS 1.1 protocol not supported", NULL); return NULL; } #endif #if defined(NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2) if (ENABLED(proto, TLS_PROTO_TLS1_2)) { Tcl_AppendResult(interp, "TLS 1.2 protocol not supported", NULL); return NULL; } #endif #if defined(NO_TLS1_3) || defined(OPENSSL_NO_TLS1_3) if (ENABLED(proto, TLS_PROTO_TLS1_3)) { Tcl_AppendResult(interp, "TLS 1.3 protocol not supported", NULL); return NULL; } #endif if (proto == 0) { /* Use full range */ SSL_CTX_set_min_proto_version(ctx, 0); SSL_CTX_set_max_proto_version(ctx, 0); |
︙ | ︙ | |||
2060 2061 2062 2063 2064 2065 2066 | if (objc < 2 || objc > 3 || (objc == 3 && !strcmp(Tcl_GetString(objv[1]), "-local"))) { Tcl_WrongNumArgs(interp, 1, objv, "?-local? channel"); return TCL_ERROR; } /* Get channel Id */ | | | 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 | if (objc < 2 || objc > 3 || (objc == 3 && !strcmp(Tcl_GetString(objv[1]), "-local"))) { Tcl_WrongNumArgs(interp, 1, objv, "?-local? channel"); return TCL_ERROR; } /* Get channel Id */ channelName = Tcl_GetStringFromObj(objv[(objc == 2 ? 1 : 2)], NULL); chan = Tcl_GetChannel(interp, channelName, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); |
︙ | ︙ | |||
2130 2131 2132 2133 2134 2135 2136 | } /* Verify mode depth */ LAPPEND_INT(interp, objPtr, "verifyDepth", SSL_get_verify_depth(statePtr->ssl)); /* Report the selected protocol as a result of the negotiation */ SSL_get0_alpn_selected(statePtr->ssl, &proto, &len); | | | 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 | } /* Verify mode depth */ LAPPEND_INT(interp, objPtr, "verifyDepth", SSL_get_verify_depth(statePtr->ssl)); /* Report the selected protocol as a result of the negotiation */ SSL_get0_alpn_selected(statePtr->ssl, &proto, &len); LAPPEND_STR(interp, objPtr, "alpn", (char *)proto, (int) len); LAPPEND_STR(interp, objPtr, "protocol", SSL_get_version(statePtr->ssl), -1); /* Valid for non-RSA signature and TLS 1.3 */ if (objc == 2) { res = SSL_get_peer_signature_nid(statePtr->ssl, &nid); } else { res = SSL_get_signature_nid(statePtr->ssl, &nid); |
︙ | ︙ | |||
2180 2181 2182 2183 2184 2185 2186 | const EVP_MD *md; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); return(TCL_ERROR); } | | | 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 | const EVP_MD *md; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); return(TCL_ERROR); } chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); if (chan == (Tcl_Channel) NULL) { return(TCL_ERROR); } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { |
︙ | ︙ | |||
2287 2288 2289 2290 2291 2292 2293 | size_t len2; unsigned int ulen; const unsigned char *session_id, *proto; char buffer[SSL_MAX_MASTER_KEY_LENGTH]; /* Report the selected protocol as a result of the ALPN negotiation */ SSL_SESSION_get0_alpn_selected(session, &proto, &len2); | | | | | | | | | 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 | size_t len2; unsigned int ulen; const unsigned char *session_id, *proto; char buffer[SSL_MAX_MASTER_KEY_LENGTH]; /* Report the selected protocol as a result of the ALPN negotiation */ SSL_SESSION_get0_alpn_selected(session, &proto, &len2); LAPPEND_STR(interp, objPtr, "alpn", (char *) proto, (int) len2); /* Report the selected protocol as a result of the NPN negotiation */ #ifdef USE_NPN SSL_get0_next_proto_negotiated(ssl, &proto, &ulen); LAPPEND_STR(interp, objPtr, "npn", (char *) proto, (int) ulen); #endif /* Resumable session */ LAPPEND_BOOL(interp, objPtr, "resumable", SSL_SESSION_is_resumable(session)); /* Session start time (seconds since epoch) */ LAPPEND_LONG(interp, objPtr, "start_time", SSL_SESSION_get_time(session)); /* Timeout value - SSL_CTX_get_timeout (in seconds) */ LAPPEND_LONG(interp, objPtr, "timeout", SSL_SESSION_get_timeout(session)); /* Session id - TLSv1.2 and below only */ session_id = SSL_SESSION_get_id(session, &ulen); LAPPEND_BARRAY(interp, objPtr, "session_id", session_id, (int) ulen); /* Session context */ session_id = SSL_SESSION_get0_id_context(session, &ulen); LAPPEND_BARRAY(interp, objPtr, "session_context", session_id, (int) ulen); /* Session ticket - client only */ SSL_SESSION_get0_ticket(session, &ticket, &len2); LAPPEND_BARRAY(interp, objPtr, "session_ticket", ticket, (int) len2); /* Session ticket lifetime hint (in seconds) */ LAPPEND_LONG(interp, objPtr, "lifetime", SSL_SESSION_get_ticket_lifetime_hint(session)); /* Ticket app data */ SSL_SESSION_get0_ticket_appdata(session, &ticket, &len2); LAPPEND_BARRAY(interp, objPtr, "ticket_app_data", ticket, (int) len2); /* Get master key */ len2 = SSL_SESSION_get_master_key(session, buffer, SSL_MAX_MASTER_KEY_LENGTH); LAPPEND_BARRAY(interp, objPtr, "master_key", buffer, (int) len2); /* Compression id */ unsigned int id = SSL_SESSION_get_compress_id(session); LAPPEND_STR(interp, objPtr, "compression_id", id == 1 ? "zlib" : "none", -1); } /* Compression info */ |
︙ | ︙ | |||
2433 2434 2435 2436 2437 2438 2439 | * *------------------------------------------------------------------- */ static int MiscObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *commands [] = { "req", "strreq", NULL }; enum command { C_REQ, C_STRREQ, C_DUMMY }; | < | | 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 | * *------------------------------------------------------------------- */ static int MiscObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *commands [] = { "req", "strreq", NULL }; enum command { C_REQ, C_STRREQ, C_DUMMY }; int cmd, isStr; char buffer[16384]; dprintf("Called"); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); return TCL_ERROR; |
︙ | ︙ | |||
2457 2458 2459 2460 2461 2462 2463 | switch ((enum command) cmd) { case C_REQ: case C_STRREQ: { EVP_PKEY *pkey=NULL; X509 *cert=NULL; X509_NAME *name=NULL; Tcl_Obj **listv; | | < | 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 | switch ((enum command) cmd) { case C_REQ: case C_STRREQ: { EVP_PKEY *pkey=NULL; X509 *cert=NULL; X509_NAME *name=NULL; Tcl_Obj **listv; int listc,i; BIO *out=NULL; char *k_C="",*k_ST="",*k_L="",*k_O="",*k_OU="",*k_CN="",*k_Email=""; char *keyout,*pemout,*str; int keysize,serial=0,days=365; |
︙ | ︙ | |||
2489 2490 2491 2492 2493 2494 2495 | pemout=Tcl_GetString(objv[4]); if (isStr) { Tcl_SetVar(interp,keyout,"",0); Tcl_SetVar(interp,pemout,"",0); } if (objc>=6) { | | > | 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 | pemout=Tcl_GetString(objv[4]); if (isStr) { Tcl_SetVar(interp,keyout,"",0); Tcl_SetVar(interp,pemout,"",0); } if (objc>=6) { if (Tcl_ListObjGetElements(interp, objv[5], &listc, &listv) != TCL_OK) { return TCL_ERROR; } if ((listc%2) != 0) { Tcl_SetResult(interp,"Information list must have even number of arguments",NULL); return TCL_ERROR; } |
︙ | ︙ | |||
2769 2770 2771 2772 2773 2774 2775 | #endif if (Tcl_PkgRequire(interp, "Tcl", "8.5-", 0) == NULL) { return TCL_ERROR; } #endif if (TlsLibInit(0) != TCL_OK) { | | | 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 | #endif if (Tcl_PkgRequire(interp, "Tcl", "8.5-", 0) == NULL) { return TCL_ERROR; } #endif if (TlsLibInit(0) != TCL_OK) { Tcl_AppendResult(interp, "could not initialize SSL library", NULL); return TCL_ERROR; } Tcl_CreateObjCommand(interp, "tls::ciphers", CiphersObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "tls::connection", ConnectionInfoObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "tls::handshake", HandshakeObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "tls::import", ImportObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); |
︙ | ︙ |
Modified generic/tlsBIO.c from [904acc3cbd] to [3977ec0a04].
1 2 3 4 5 6 7 8 9 10 | /* * Copyright (C) 1997-2000 Matt Newman <[email protected]> * * Provides BIO layer to interface openssl to Tcl. */ #include "tlsInt.h" static int BioWrite(BIO *bio, const char *buf, int bufLen) { Tcl_Channel chan; | | | < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /* * Copyright (C) 1997-2000 Matt Newman <[email protected]> * * Provides BIO layer to interface openssl to Tcl. */ #include "tlsInt.h" static int BioWrite(BIO *bio, const char *buf, int bufLen) { Tcl_Channel chan; int ret; int tclEofChan, tclErrno; chan = Tls_GetParent((State *) BIO_get_data(bio), 0); dprintf("[chan=%p] BioWrite(%p, <buf>, %d)", (void *)chan, (void *) bio, bufLen); ret = (int) Tcl_WriteRaw(chan, buf, bufLen); tclEofChan = Tcl_Eof(chan); tclErrno = Tcl_GetErrno(); dprintf("[chan=%p] BioWrite(%d) -> %d [tclEof=%d; tclErrno=%d]", (void *) chan, bufLen, ret, tclEofChan, Tcl_GetErrno()); BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY); if (tclEofChan && ret <= 0) { dprintf("Got EOF while reading, returning a Connection Reset error which maps to Soft EOF"); Tcl_SetErrno(ECONNRESET); ret = 0; |
︙ | ︙ | |||
51 52 53 54 55 56 57 | if (ret != -1 || (ret == -1 && tclErrno == EAGAIN)) { if (BIO_should_read(bio)) { dprintf("Setting should retry read flag"); BIO_set_retry_read(bio); } } | | | < | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | if (ret != -1 || (ret == -1 && tclErrno == EAGAIN)) { if (BIO_should_read(bio)) { dprintf("Setting should retry read flag"); BIO_set_retry_read(bio); } } return(ret); } static int BioRead(BIO *bio, char *buf, int bufLen) { Tcl_Channel chan; Tcl_Size ret = 0; int tclEofChan, tclErrno; chan = Tls_GetParent((State *) BIO_get_data(bio), 0); dprintf("[chan=%p] BioRead(%p, <buf>, %d)", (void *) chan, (void *) bio, bufLen); if (buf == NULL) { return 0; } ret = Tcl_ReadRaw(chan, buf, bufLen); tclEofChan = Tcl_Eof(chan); tclErrno = Tcl_GetErrno(); dprintf("[chan=%p] BioRead(%d) -> %d [tclEof=%d; tclErrno=%d]", (void *) chan, bufLen, ret, tclEofChan, tclErrno); BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY); if (tclEofChan && ret <= 0) { dprintf("Got EOF while reading, returning a Connection Reset error which maps to Soft EOF"); Tcl_SetErrno(ECONNRESET); ret = 0; |
︙ | ︙ | |||
108 109 110 111 112 113 114 | if (BIO_should_write(bio)) { dprintf("Setting should retry write flag"); BIO_set_retry_write(bio); } } | | < | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | if (BIO_should_write(bio)) { dprintf("Setting should retry write flag"); BIO_set_retry_write(bio); } } dprintf("BioRead(%p, <buf>, %d) [%p] returning %i", (void *) bio, bufLen, (void *) chan, ret); return(ret); } static int BioPuts(BIO *bio, const char *str) { dprintf("BioPuts(%p, <string:%p>) called", bio, str); return BioWrite(bio, str, (int) strlen(str)); } |
︙ | ︙ |
Modified generic/tlsInt.h from [0103fefac9] to [ba5e9003ea].
︙ | ︙ | |||
38 39 40 41 42 43 44 | # endif #endif /* * Backwards compatibility for size type change */ #if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7 | | < < < < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # endif #endif /* * Backwards compatibility for size type change */ #if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7 # define Tcl_Size int #endif #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/rand.h> #include <openssl/opensslv.h> |
︙ | ︙ |
Modified generic/tlsX509.c from [a931d05109] to [c99299d264].
︙ | ︙ | |||
78 79 80 81 82 83 84 | int len = 0; char buffer[1024]; if (astring != NULL) { len = String_to_Hex((char *)ASN1_STRING_get0_data(astring), ASN1_STRING_length(astring), buffer, 1024); } | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | int len = 0; char buffer[1024]; if (astring != NULL) { len = String_to_Hex((char *)ASN1_STRING_get0_data(astring), ASN1_STRING_length(astring), buffer, 1024); } resultPtr = Tcl_NewStringObj(buffer, len); return resultPtr; } /* * Get Key Usage */ Tcl_Obj *Tls_x509KeyUsage(Tcl_Interp *interp, X509 *cert, uint32_t xflags) { |
︙ | ︙ | |||
200 201 202 203 204 205 206 | } if (names = X509_get_ext_d2i(cert, nid, NULL, NULL)) { for (int i=0; i < sk_GENERAL_NAME_num(names); i++) { const GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i); len = BIO_to_Buffer(name && GENERAL_NAME_print(bio, name), bio, buffer, 1024); | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | } if (names = X509_get_ext_d2i(cert, nid, NULL, NULL)) { for (int i=0; i < sk_GENERAL_NAME_num(names); i++) { const GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i); len = BIO_to_Buffer(name && GENERAL_NAME_print(bio, name), bio, buffer, 1024); LAPPEND_STR(interp, listPtr, NULL, buffer, len); } sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } return listPtr; } /* |
︙ | ︙ | |||
277 278 279 280 281 282 283 | if (distpoint->type == 0) { /* full-name GENERALIZEDNAME */ for (int j = 0; j < sk_GENERAL_NAME_num(distpoint->name.fullname); j++) { GENERAL_NAME *gen = sk_GENERAL_NAME_value(distpoint->name.fullname, j); int type; ASN1_STRING *uri = GENERAL_NAME_get0_value(gen, &type); if (type == GEN_URI) { | | | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | if (distpoint->type == 0) { /* full-name GENERALIZEDNAME */ for (int j = 0; j < sk_GENERAL_NAME_num(distpoint->name.fullname); j++) { GENERAL_NAME *gen = sk_GENERAL_NAME_value(distpoint->name.fullname, j); int type; ASN1_STRING *uri = GENERAL_NAME_get0_value(gen, &type); if (type == GEN_URI) { LAPPEND_STR(interp, listPtr, NULL, ASN1_STRING_get0_data(uri), ASN1_STRING_length(uri)); } } } else if (distpoint->type == 1) { /* relative-name X509NAME */ STACK_OF(X509_NAME_ENTRY) *sk_relname = distpoint->name.relativename; for (int j = 0; j < sk_X509_NAME_ENTRY_num(sk_relname); j++) { X509_NAME_ENTRY *e = sk_X509_NAME_ENTRY_value(sk_relname, j); ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); LAPPEND_STR(interp, listPtr, NULL, ASN1_STRING_data(d), ASN1_STRING_length(d)); } } } CRL_DIST_POINTS_free(crl); } return listPtr; } |
︙ | ︙ | |||
331 332 333 334 335 336 337 | if (ads = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL)) { for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(ads); i++) { ad = sk_ACCESS_DESCRIPTION_value(ads, i); if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers && ad->location) { if (ad->location->type == GEN_URI) { len = ASN1_STRING_to_UTF8(&buf, ad->location->d.uniformResourceIdentifier); | | | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | if (ads = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL)) { for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(ads); i++) { ad = sk_ACCESS_DESCRIPTION_value(ads, i); if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers && ad->location) { if (ad->location->type == GEN_URI) { len = ASN1_STRING_to_UTF8(&buf, ad->location->d.uniformResourceIdentifier); Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(buf, len)); OPENSSL_free(buf); break; } } } /* sk_ACCESS_DESCRIPTION_pop_free(ads, ACCESS_DESCRIPTION_free); */ AUTHORITY_INFO_ACCESS_free(ads); |
︙ | ︙ | |||
391 392 393 394 395 396 397 | int sig_nid; X509_get0_signature(&sig, &sig_alg, cert); /* sig_nid = X509_get_signature_nid(cert) */ sig_nid = OBJ_obj2nid(sig_alg->algorithm); LAPPEND_STR(interp, certPtr, "signatureAlgorithm", OBJ_nid2ln(sig_nid), -1); len = (sig_nid != NID_undef) ? String_to_Hex(sig->data, sig->length, buffer, BUFSIZ) : 0; | | | | | | | | | | | | | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | int sig_nid; X509_get0_signature(&sig, &sig_alg, cert); /* sig_nid = X509_get_signature_nid(cert) */ sig_nid = OBJ_obj2nid(sig_alg->algorithm); LAPPEND_STR(interp, certPtr, "signatureAlgorithm", OBJ_nid2ln(sig_nid), -1); len = (sig_nid != NID_undef) ? String_to_Hex(sig->data, sig->length, buffer, BUFSIZ) : 0; LAPPEND_STR(interp, certPtr, "signatureValue", buffer, len); } /* Version of the encoded certificate - RFC 5280 section 4.1.2.1 */ LAPPEND_LONG(interp, certPtr, "version", X509_get_version(cert)+1); /* Unique number assigned by CA to certificate - RFC 5280 section 4.1.2.2 */ len = BIO_to_Buffer(i2a_ASN1_INTEGER(bio, X509_get0_serialNumber(cert)), bio, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "serialNumber", buffer, len); /* Signature algorithm used by the CA to sign the certificate. Must match signatureAlgorithm. RFC 5280 section 4.1.2.3 */ LAPPEND_STR(interp, certPtr, "signature", OBJ_nid2ln(X509_get_signature_nid(cert)), -1); /* Issuer identifies the entity that signed and issued the cert. RFC 5280 section 4.1.2.4 */ len = BIO_to_Buffer(X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, flags), bio, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "issuer", buffer, len); /* Certificate validity period is the interval the CA warrants that it will maintain info on the status of the certificate. RFC 5280 section 4.1.2.5 */ /* Get Validity - Not Before */ len = BIO_to_Buffer(ASN1_TIME_print(bio, X509_get0_notBefore(cert)), bio, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "notBefore", buffer, len); /* Get Validity - Not After */ len = BIO_to_Buffer(ASN1_TIME_print(bio, X509_get0_notAfter(cert)), bio, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "notAfter", buffer, len); /* Subject identifies the entity associated with the public key stored in the subject public key field. RFC 5280 section 4.1.2.6 */ len = BIO_to_Buffer(X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, flags), bio, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "subject", buffer, len); /* SHA1 Digest (Fingerprint) of cert - DER representation */ if (X509_digest(cert, EVP_sha1(), md, &len)) { len = String_to_Hex(md, len, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "sha1_hash", buffer, len); } /* SHA256 Digest (Fingerprint) of cert - DER representation */ if (X509_digest(cert, EVP_sha256(), md, &len)) { len = String_to_Hex(md, len, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "sha256_hash", buffer, len); } /* Subject Public Key Info specifies the public key and identifies the algorithm with which the key is used. RFC 5280 section 4.1.2.7 */ if (X509_get_signature_info(cert, &mdnid, &pknid, &bits, &xflags)) { ASN1_BIT_STRING *key; unsigned int n; LAPPEND_STR(interp, certPtr, "signingDigest", OBJ_nid2ln(mdnid), -1); LAPPEND_STR(interp, certPtr, "publicKeyAlgorithm", OBJ_nid2ln(pknid), -1); LAPPEND_INT(interp, certPtr, "bits", bits); /* Effective security bits */ key = X509_get0_pubkey_bitstr(cert); len = String_to_Hex(key->data, key->length, buffer, BUFSIZ); LAPPEND_STR(interp, certPtr, "publicKey", buffer, len); len = 0; if (X509_pubkey_digest(cert, EVP_get_digestbynid(pknid), md, &n)) { len = String_to_Hex(md, (int)n, buffer, BUFSIZ); } LAPPEND_STR(interp, certPtr, "publicKeyHash", buffer, len); /* digest of the DER representation of the certificate */ len = 0; if (X509_digest(cert, EVP_get_digestbynid(mdnid), md, &n)) { len = String_to_Hex(md, (int)n, buffer, BUFSIZ); } LAPPEND_STR(interp, certPtr, "signatureHash", buffer, len); } /* Certificate Purpose. Call before checking for extensions. */ LAPPEND_STR(interp, certPtr, "purpose", Tls_x509Purpose(cert), -1); LAPPEND_OBJ(interp, certPtr, "certificatePurpose", Tls_x509Purposes(interp, cert)); /* Get extensions flags */ |
︙ | ︙ | |||
487 488 489 490 491 492 493 | and/or issuer names over time. RFC 5280 section 4.1.2.8 */ { const ASN1_BIT_STRING *iuid, *suid; X509_get0_uids(cert, &iuid, &suid); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("issuerUniqueId", -1)); if (iuid != NULL) { | | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | and/or issuer names over time. RFC 5280 section 4.1.2.8 */ { const ASN1_BIT_STRING *iuid, *suid; X509_get0_uids(cert, &iuid, &suid); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("issuerUniqueId", -1)); if (iuid != NULL) { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewByteArrayObj((char *)iuid->data, iuid->length)); } else { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("", -1)); } Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("subjectUniqueId", -1)); if (suid != NULL) { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewByteArrayObj((char *)suid->data, suid->length)); } else { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("", -1)); } } /* X509 v3 Extensions - RFC 5280 section 4.1.2.9 */ LAPPEND_INT(interp, certPtr, "extCount", X509_get_ext_count(cert)); |
︙ | ︙ | |||
581 582 583 584 585 586 587 | /* Subject Information Access - RFC 5280 section 4.2.2.2, NID_sinfo_access */ /* Certificate Alias. If uses a PKCS#12 structure, alias will reflect the friendlyName attribute (RFC 2985). */ { len = 0; char *string = X509_alias_get0(cert, &len); | | | | | 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | /* Subject Information Access - RFC 5280 section 4.2.2.2, NID_sinfo_access */ /* Certificate Alias. If uses a PKCS#12 structure, alias will reflect the friendlyName attribute (RFC 2985). */ { len = 0; char *string = X509_alias_get0(cert, &len); LAPPEND_STR(interp, certPtr, "alias", string, len); } /* Certificate and dump all data */ { char certStr[CERT_STR_SIZE]; /* Get certificate */ len = BIO_to_Buffer(PEM_write_bio_X509(bio, cert), bio, certStr, CERT_STR_SIZE); LAPPEND_STR(interp, certPtr, "certificate", certStr, len); /* Get all cert info */ len = BIO_to_Buffer(X509_print_ex(bio, cert, flags, 0), bio, certStr, CERT_STR_SIZE); LAPPEND_STR(interp, certPtr, "all", certStr, len); } BIO_free(bio); return certPtr; } |