Check-in [49278969f2]
Bounty program for improvements to Tcl and certain Tcl packages.
Overview
Comment:Add support for ASN1 blobs for certificates and keys
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mjanssen-asn1-certs
Files: files | file ages | folders
SHA3-256: 49278969f25b2e653fa8e1a266650d2276761f8bada32a273565c7953102a221
User & Date: mjanssen on 2019-06-17 12:05:26
Other Links: branch diff | manifest | tags
Context
2019-06-17
14:27
Do not expose implementation details in user interface check-in: ef0be0d731 user: mjanssen tags: mjanssen-asn1-certs
12:05
Add support for ASN1 blobs for certificates and keys check-in: 49278969f2 user: mjanssen tags: mjanssen-asn1-certs
2019-04-12
16:58
Better handling of shared/static naming issues check-in: 2c8d3629bc user: rkeene tags: trunk
Changes

Modified tclOpts.h from [aff9aa3b9c] to [1a6cf1121d].

    40     40   #define OPTBOOL(option, var)			\
    41     41       OPT_PROLOG(option)				\
    42     42       if (Tcl_GetBooleanFromObj(interp, objv[idx],\
    43     43   	    &(var)) != TCL_OK) {		\
    44     44   	    return TCL_ERROR;			\
    45     45       }						\
    46     46       OPT_POSTLOG()
           47  +
           48  +#define OPTBYTE(option, var, lvar)			\
           49  +    OPT_PROLOG(option)				\
           50  +    var = Tcl_GetByteArrayFromObj(objv[idx], &(lvar));\
           51  +    OPT_POSTLOG()
    47     52   
    48     53   #define OPTBAD(type, list)			\
    49     54       Tcl_AppendResult(interp, "bad ", (type),	\
    50     55   		" \"", opt, "\": must be ",	\
    51     56   		(list), (char *) NULL)
    52     57   
    53     58   #endif /* _TCL_OPTS_H */

Modified tls.c from [c565bf20f1] to [8332b7761d].

    58     58   static int	MiscObjCmd(ClientData clientData,
    59     59   			Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
    60     60   
    61     61   static int	UnimportObjCmd(ClientData clientData,
    62     62   			Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
    63     63   
    64     64   static SSL_CTX *CTX_Init(State *statePtr, int isServer, int proto, char *key,
    65         -			char *cert, char *CAdir, char *CAfile, char *ciphers,
    66         -			char *DHparams);
           65  +			char *cert, unsigned char *key_asn1, unsigned char *cert_asn1,
           66  +			int key_asn1_len, int cert_asn1_len, char *CAdir, char *CAfile,
           67  +      char *ciphers, char *DHparams);
    67     68   
    68     69   static int	TlsLibInit(int uninitialize);
    69     70   
    70     71   #define TLS_PROTO_SSL2		0x01
    71     72   #define TLS_PROTO_SSL3		0x02
    72     73   #define TLS_PROTO_TLS1		0x04
    73     74   #define TLS_PROTO_TLS1_1	0x08
................................................................................
   725    726       ClientData clientData;	/* Not used. */
   726    727       Tcl_Interp *interp;
   727    728       int objc;
   728    729       Tcl_Obj *CONST objv[];
   729    730   {
   730    731       Tcl_Channel chan;		/* The channel to set a mode on. */
   731    732       State *statePtr;		/* client state for ssl socket */
   732         -    SSL_CTX *ctx	= NULL;
   733         -    Tcl_Obj *script	= NULL;
   734         -    Tcl_Obj *password	= NULL;
          733  +    SSL_CTX *ctx	        = NULL;
          734  +    Tcl_Obj *script	        = NULL;
          735  +    Tcl_Obj *password	        = NULL;
   735    736       Tcl_DString upperChannelTranslation, upperChannelBlocking, upperChannelEncoding, upperChannelEOFChar;
   736    737       int idx, len;
   737         -    int flags		= TLS_TCL_INIT;
   738         -    int server		= 0;	/* is connection incoming or outgoing? */
   739         -    char *key		= NULL;
   740         -    char *cert		= NULL;
   741         -    char *ciphers	= NULL;
   742         -    char *CAfile	= NULL;
   743         -    char *CAdir		= NULL;
   744         -    char *DHparams	= NULL;
   745         -    char *model		= NULL;
          738  +    int flags		        = TLS_TCL_INIT;
          739  +    int server		        = 0;	/* is connection incoming or outgoing? */
          740  +    char *key		        = NULL;
          741  +    char *cert		        = NULL;
          742  +    unsigned char *key_asn1	= NULL;
          743  +    int key_asn1_len            = 0;
          744  +    unsigned char *cert_asn1	= NULL;
          745  +    int cert_asn1_len           = 0;
          746  +    char *ciphers	        = NULL;
          747  +    char *CAfile	        = NULL;
          748  +    char *CAdir		        = NULL;
          749  +    char *DHparams	        = NULL;
          750  +    char *model		        = NULL;
   746    751   #ifndef OPENSSL_NO_TLSEXT
   747         -    char *servername	= NULL;	/* hostname for Server Name Indication */
          752  +    char *servername	        = NULL;	/* hostname for Server Name Indication */
   748    753   #endif
   749    754       int ssl2 = 0, ssl3 = 0;
   750    755       int tls1 = 1, tls1_1 = 1, tls1_2 = 1, tls1_3 = 1;
   751    756       int proto = 0;
   752    757       int verify = 0, require = 0, request = 1;
   753    758   
   754    759       dprintf("Called");
................................................................................
   812    817   	OPTBOOL( "-ssl2", ssl2);
   813    818   	OPTBOOL( "-ssl3", ssl3);
   814    819   	OPTBOOL( "-tls1", tls1);
   815    820   	OPTBOOL( "-tls1.1", tls1_1);
   816    821   	OPTBOOL( "-tls1.2", tls1_2);
   817    822   	OPTBOOL( "-tls1.3", tls1_3);
   818    823   
   819         -	OPTBAD( "option", "-cadir, -cafile, -certfile, -cipher, -command, -dhparams, -keyfile, -model, -password, -require, -request, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or tls1.3");
          824  +  OPTBYTE("-certasn1", cert_asn1, cert_asn1_len);
          825  +  OPTBYTE("-keyasn1", key_asn1, key_asn1_len);
          826  +
          827  +	OPTBAD( "option", "-cadir, -cafile, -certasn1, -certfile, -cipher, -command, -dhparams, -keyasn1, -keyfile, -model, -password, -require, -request, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or tls1.3");
   820    828   
   821    829   	return TCL_ERROR;
   822    830       }
   823    831       if (request)	    verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER;
   824    832       if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
   825    833       if (verify == 0)	verify = SSL_VERIFY_NONE;
   826    834   
................................................................................
   828    836       proto |= (ssl3 ? TLS_PROTO_SSL3 : 0);
   829    837       proto |= (tls1 ? TLS_PROTO_TLS1 : 0);
   830    838       proto |= (tls1_1 ? TLS_PROTO_TLS1_1 : 0);
   831    839       proto |= (tls1_2 ? TLS_PROTO_TLS1_2 : 0);
   832    840       proto |= (tls1_3 ? TLS_PROTO_TLS1_3 : 0);
   833    841   
   834    842       /* reset to NULL if blank string provided */
   835         -    if (cert && !*cert)		cert	 = NULL;
   836         -    if (key && !*key)		key	 = NULL;
   837         -    if (ciphers && !*ciphers)	ciphers	 = NULL;
   838         -    if (CAfile && !*CAfile)	CAfile	 = NULL;
   839         -    if (CAdir && !*CAdir)	CAdir	 = NULL;
   840         -    if (DHparams && !*DHparams)	DHparams = NULL;
          843  +    if (cert && !*cert)		        cert	        = NULL;
          844  +    if (key && !*key)		        key	        = NULL;
          845  +    if (cert_asn1 && !*cert_asn1)	cert_asn1	= NULL;
          846  +    if (key_asn1 && !*key_asn1)		key_asn1	= NULL;
          847  +    if (ciphers && !*ciphers)	        ciphers	        = NULL;
          848  +    if (CAfile && !*CAfile)	        CAfile	        = NULL;
          849  +    if (CAdir && !*CAdir)	        CAdir	        = NULL;
          850  +    if (DHparams && !*DHparams)	        DHparams        = NULL;
   841    851   
   842    852       /* new SSL state */
   843    853       statePtr		= (State *) ckalloc((unsigned) sizeof(State));
   844    854       memset(statePtr, 0, sizeof(State));
   845    855   
   846    856       statePtr->flags	= flags;
   847    857       statePtr->interp	= interp;
................................................................................
   883    893   	    Tcl_AppendResult(interp, "bad channel \"",
   884    894   		    Tcl_GetChannelName(chan), "\": not a TLS channel", NULL);
   885    895   	    Tls_Free((char *) statePtr);
   886    896   	    return TCL_ERROR;
   887    897   	}
   888    898   	ctx = ((State *)Tcl_GetChannelInstanceData(chan))->ctx;
   889    899       } else {
   890         -	if ((ctx = CTX_Init(statePtr, server, proto, key, cert, CAdir, CAfile, ciphers,
   891         -		DHparams)) == (SSL_CTX*)0) {
          900  +	if ((ctx = CTX_Init(statePtr, server, proto, key, cert, key_asn1,
          901  +    cert_asn1, key_asn1_len, cert_asn1_len, CAdir, CAfile, ciphers,
          902  +    DHparams)) == (SSL_CTX*)0) {
   892    903   	    Tls_Free((char *) statePtr);
   893    904   	    return TCL_ERROR;
   894    905   	}
   895    906       }
   896    907   
   897    908       statePtr->ctx = ctx;
   898    909   
................................................................................
  1052   1063    * Side effects:
  1053   1064    *	constructs SSL context (CTX)
  1054   1065    *
  1055   1066    *-------------------------------------------------------------------
  1056   1067    */
  1057   1068   
  1058   1069   static SSL_CTX *
  1059         -CTX_Init(statePtr, isServer, proto, key, cert, CAdir, CAfile, ciphers, DHparams)
         1070  +CTX_Init(statePtr, isServer, proto, key, cert, key_asn1, cert_asn1,
         1071  +         key_asn1_len, cert_asn1_len, CAdir, CAfile, ciphers, DHparams)
  1060   1072       State *statePtr;
  1061   1073       int isServer;
  1062   1074       int proto;
  1063   1075       char *key;
  1064   1076       char *cert;
         1077  +    unsigned char *key_asn1;
         1078  +    unsigned char *cert_asn1;
         1079  +    int key_asn1_len;
         1080  +    int cert_asn1_len;
  1065   1081       char *CAdir;
  1066   1082       char *CAfile;
  1067   1083       char *ciphers;
  1068   1084       char *DHparams;
  1069   1085   {
  1070   1086       Tcl_Interp *interp = statePtr->interp;
  1071   1087       SSL_CTX *ctx = NULL;
................................................................................
  1283   1299   	 * the SSL context */
  1284   1300   	if (!SSL_CTX_check_private_key(ctx)) {
  1285   1301   	    Tcl_AppendResult(interp,
  1286   1302   			     "private key does not match the certificate public key",
  1287   1303   			     (char *) NULL);
  1288   1304   	    SSL_CTX_free(ctx);
  1289   1305   	    return (SSL_CTX *)0;
         1306  +	}
         1307  +    } else if (cert_asn1 != NULL) {
         1308  +	if (SSL_CTX_use_certificate_ASN1(ctx, cert_asn1_len, cert_asn1) <= 0) {
         1309  +	    Tcl_DStringFree(&ds);
         1310  +	    Tcl_AppendResult(interp,
         1311  +			     "unable to set certificate from ASN1: ",
         1312  +			     REASON(), (char *) NULL);
         1313  +	    SSL_CTX_free(ctx);
         1314  +	    return (SSL_CTX *)0;
         1315  +	}
         1316  +	if (key_asn1 == NULL) {
         1317  +    key_asn1=cert_asn1;
         1318  +    key_asn1_len = cert_asn1_len;
         1319  +  }
         1320  +	if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, ctx, key_asn1,key_asn1_len) <= 0) {
         1321  +	    Tcl_DStringFree(&ds);
         1322  +	    /* flush the passphrase which might be left in the result */
         1323  +	    Tcl_SetResult(interp, NULL, TCL_STATIC);
         1324  +	    Tcl_AppendResult(interp,
         1325  +			     "unable to set public key from ASN1: ",
         1326  +			     REASON(), (char *) NULL);
         1327  +	    SSL_CTX_free(ctx);
         1328  +	    return (SSL_CTX *)0;
  1290   1329   	}
  1291   1330       } else {
  1292   1331   	cert = (char*)X509_get_default_cert_file();
  1293   1332   
  1294   1333   	if (SSL_CTX_use_certificate_file(ctx, cert,
  1295   1334   					SSL_FILETYPE_PEM) <= 0) {
  1296   1335   #if 0

Modified tls.tcl from [75c0c2a68a] to [bc6c1405ca].

    30     30       variable socketOptionRules {
    31     31           {0 -async sopts 0}
    32     32           {* -myaddr sopts 1}
    33     33           {0 -myport sopts 1}
    34     34           {* -type sopts 1}
    35     35           {* -cadir iopts 1}
    36     36           {* -cafile iopts 1}
           37  +        {* -certasn1 iopts 1}
    37     38           {* -certfile iopts 1}
    38     39           {* -cipher iopts 1}
    39     40           {* -command iopts 1}
    40     41           {* -dhparams iopts 1}
           42  +        {* -keyasn1 iopts 1}
    41     43           {* -keyfile iopts 1}
    42     44           {* -password iopts 1}
    43     45           {* -request iopts 1}
    44     46           {* -require iopts 1}
    45     47           {* -autoservername discardOpts 1}
    46     48           {* -servername iopts 1}
    47     49           {* -ssl2 iopts 1}