Changes On Branch 87010ba1d9d1dba0

Changes In Branch status_x509 Through [87010ba1d9] Excluding Merge-Ins

This is equivalent to a diff from dbe759a0f2 to 87010ba1d9

2023-09-01
21:57
Merged status and X509 updates branch into master check-in: 3432ab03a3 user: bohagan tags: trunk
2023-08-01
22:42
Added Certificate purposes to X509 status output. Corrected certificate alias get text bug. Refactored code to reduce number of variables and use common buffers for SHA fingerprints. check-in: e94d9cae93 user: bohagan tags: status_x509
2023-07-31
02:17
Added verify depth and mode status to connection status, renamed signatureType and signatureType check-in: 87010ba1d9 user: bohagan tags: status_x509
2023-07-30
22:25
Replaced custom X509 ASN1_UTCTIME_tostr function with OpenSSL function ASN1_TIME_print. Added catch errors returned from get certificate functions. check-in: b50520df51 user: bohagan tags: status_x509
03:39
Merged master into branch check-in: 739742d3d4 user: bohagan tags: status_x509
03:21
Merged errors_and_callbacks branch into master check-in: dbe759a0f2 user: bohagan tags: trunk
02:53
Updated default callbacks in tls.tcl file Leaf check-in: cdb51c799e user: bohagan tags: errors_and_callbacks
2023-07-16
15:05
Merge status and X509 updates branch check-in: 1924dcd361 user: bohagan tags: trunk

Modified doc/tls.html from [3c88bc4018] to [9494c1c42e].

252
253
254
255
256
257
258
259

260





261

262
263
264
265
266
267
268
252
253
254
255
256
257
258

259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+

+
+
+
+
+
-
+







	<dt><strong>protocol</strong> <em>version</em></dt>
	<dd>The protocol version used for the connection:
	    SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown.</dd>
	<dt><strong>sbits</strong> <em>n</em></dt>
	<dd>The number of bits used for the session key.</dd>
	<dt><strong>signatureHashAlgorithm</strong> <em>algorithm</em></dt>
	<dd>The signature hash algorithm.</dd>
	<dt><strong>signature_type</strong> <em>type</em></dt>
	<dt><strong>signatureType</strong> <em>type</em></dt>
	<dd>The signature type value.</dd>
	<dt><strong>verifyDepth</strong> <em>n</em></dt>
	<dd>Maximum depth for the certificate chain verification.
	    Default is -1, to check all.</dd>
	<dt><strong>verifyMode</strong> <em>list</em></dt>
	<dd>List of certificate verification modes.</dd>
	<dt><strong>verification</strong> <em>result</em></dt>
	<dt><strong>verifyResult</strong> <em>result</em></dt>
	<dd>Certificate verification result.</dd>
	<dt><strong>ca_names</strong> <em>list</em></dt>
	<dd>List of the Certificate Authorities used to create the certificate.</dd>
    </dl>
</blockquote>
<blockquote>
	<b>Certificate Status</b>

Modified generic/tls.c from [b314eff29c] to [876a0b1ced].

2098
2099
2100
2101
2102
2103
2104
2105

2106
2107
2108




























2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158







-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







    ciphers = (char*)SSL_get_cipher(statePtr->ssl);
    if ((ciphers != NULL) && (strcmp(ciphers, "(NONE)") != 0)) {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("cipher", -1));
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(ciphers, -1));
    }

    /* Verify the X509 certificate presented by the peer */
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("verification", -1));
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("verifyResult", -1));
    Tcl_ListObjAppendElement(interp, objPtr,
	Tcl_NewStringObj(X509_verify_cert_error_string(SSL_get_verify_result(statePtr->ssl)), -1));

    /* Verify mode */
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("verifyMode", -1));
    /* SSL_CTX_get_verify_mode(ctx) */
    mode = SSL_get_verify_mode(statePtr->ssl);
    if (mode && SSL_VERIFY_NONE) {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("none", -1));
    } else {
	Tcl_Obj *listObjPtr = Tcl_NewListObj(0, NULL);
	if (mode && SSL_VERIFY_PEER) {
	    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("peer", -1));
	}
	if (mode && SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
	    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("fail if no peer cert", -1));
	}
	if (mode && SSL_VERIFY_CLIENT_ONCE) {
	    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("client once", -1));
	}
	if (mode && SSL_VERIFY_POST_HANDSHAKE) {
	    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("post handshake", -1));
	}
	Tcl_ListObjAppendElement(interp, objPtr, listObjPtr);
    }

    /* Verify mode depth */
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("verifyDepth", -1));
    /* SSL_CTX_get_verify_depth(ctx) */
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(SSL_get_verify_depth(statePtr->ssl)));

    /* Report the selected protocol as a result of the negotiation */
    SSL_get0_alpn_selected(statePtr->ssl, &proto, &len);
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("alpn", -1));
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj((char *)proto, (int) len));
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("protocol", -1));
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(SSL_get_version(statePtr->ssl), -1));

    /* Valid for non-RSA signature and TLS 1.3 */
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("signatureHashAlgorithm", -1));
    if (objc == 2 ? SSL_get_peer_signature_nid(statePtr->ssl, &nid) : SSL_get_signature_nid(statePtr->ssl, &nid)) {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(OBJ_nid2ln(nid), -1));
    } else {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("", -1));
    }
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("signature_type", -1));
    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("signatureType", -1));
    if (objc == 2 ? SSL_get_peer_signature_type_nid(statePtr->ssl, &nid) : SSL_get_signature_type_nid(statePtr->ssl, &nid)) {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(OBJ_nid2ln(nid), -1));
    } else {
	Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("", -1));
    }

    Tcl_SetObjResult(interp, objPtr);

Modified generic/tlsX509.c from [4adcfb41ce] to [b50e8f8920].

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
29
30
31
32
33
34
35





































36
37
38
39
40
41
42







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

static int max(int a, int b)
{
    return (a > b) ? a : b;
}

/*
 * ASN1_UTCTIME_tostr --
 */
static char *
ASN1_UTCTIME_tostr(ASN1_UTCTIME *tm)
{
    static char bp[128];
    char *v;
    int gmt=0;
    static char *mon[12]={
        "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"};
    int i;
    int y=0,M=0,d=0,h=0,m=0,s=0;

    i=tm->length;
    v=(char *)tm->data;

    if (i < 10) goto err;
    if (v[i-1] == 'Z') gmt=1;
    for (i=0; i<10; i++)
        if ((v[i] > '9') || (v[i] < '0')) goto err;
    y= (v[0]-'0')*10+(v[1]-'0');
    if (y < 70) y+=100;
    M= (v[2]-'0')*10+(v[3]-'0');
    if ((M > 12) || (M < 1)) goto err;
    d= (v[4]-'0')*10+(v[5]-'0');
    h= (v[6]-'0')*10+(v[7]-'0');
    m=  (v[8]-'0')*10+(v[9]-'0');
    if ((v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
        s=  (v[10]-'0')*10+(v[11]-'0');

    sprintf(bp,"%s %2d %02d:%02d:%02d %d%s", mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"");
    return bp;
 err:
    return "Bad time value";
}

/*
 * Binary string to hex string
 */
int String_to_Hex(char* input, int len, char *output, int max) {
    int count = 0;

    for (int i = 0; i < len && count < max - 1; i++, count += 2) {
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







 *
 *	Tls_NewX509Obj --
 *
 *	------------------------------------------------*
 *	Converts a X509 certificate into a Tcl_Obj
 *	------------------------------------------------*
 *
 *	Sideeffects:
 *	Side effects:
 *		None
 *
 *	Result:
 *		A Tcl List Object representing the provided
 *		X509 certificate.
 *
 *------------------------------------------------------*
120
121
122
123
124
125
126
127

128
129
130
131
132






133
134
135

136
137


138
139
140
141
142
143
144








145
146
147
148
149
150







151
152


153
154
155
156
157
158
159
83
84
85
86
87
88
89

90





91
92
93
94
95
96
97
98
99
100


101
102







103
104
105
106
107
108
109
110






111
112
113
114
115
116
117


118
119
120
121
122
123
124
125
126







-
+
-
-
-
-
-
+
+
+
+
+
+



+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+







    int certStr_len, toRead;
    unsigned char sha1_hash_binary[SHA_DIGEST_LENGTH];
    unsigned char sha256_hash_binary[SHA256_DIGEST_LENGTH];
    int nid, pknid, bits, num_of_exts, len;
    uint32_t xflags;
    STACK_OF(GENERAL_NAME) *san;

    certStr[0] = 0;
    certStr[0]   = 0;
    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
	subject[0] = 0;
	issuer[0]  = 0;
	serial[0]  = 0;
    } else {
    subject[0]   = 0;
    issuer[0]    = 0;
    serial[0]    = 0;
    notBefore[0] = 0;
    notAfter[0]  = 0;
    if ((bio = BIO_new(BIO_s_mem())) != NULL) {
	flags = XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT;
	flags &= ~ASN1_STRFLGS_ESC_MSB;

	/* Get subject name */
	X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, flags);
	n = BIO_read(bio, subject, min(BIO_pending(bio), BUFSIZ - 1));
	if (X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, flags) > 0) {
	    n = BIO_read(bio, subject, min(BIO_pending(bio), BUFSIZ - 1));
	n = max(n, 0);
	subject[n] = 0;
	(void)BIO_flush(bio);

	X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, flags);
	n = BIO_read(bio, issuer, min(BIO_pending(bio), BUFSIZ - 1));
	n = max(n, 0);
	    subject[max(n, 0)] = 0;
	    (void)BIO_flush(bio);
	}

	/* Get issuer name */
	if (X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, flags) > 0) {
	    n = BIO_read(bio, issuer, min(BIO_pending(bio), BUFSIZ - 1));
	    issuer[max(n, 0)] = 0;
	issuer[n] = 0;
	(void)BIO_flush(bio);

	i2a_ASN1_INTEGER(bio, X509_get0_serialNumber(cert));
	n = BIO_read(bio, serial, min(BIO_pending(bio), BUFSIZ - 1));
	n = max(n, 0);
	    (void)BIO_flush(bio);
	}

	/* Get serial number */
	if (i2a_ASN1_INTEGER(bio, X509_get0_serialNumber(cert)) > 0) {
	    n = BIO_read(bio, serial, min(BIO_pending(bio), BUFSIZ - 1));
	    serial[max(n, 0)] = 0;
	serial[n] = 0;
	(void)BIO_flush(bio);
	    (void)BIO_flush(bio);
	}

        /* Get certificate */
        if (PEM_write_bio_X509(bio, cert)) {
            certStr_p = certStr;
            certStr_len = 0;
            while (1) {
                toRead = min(BIO_pending(bio), CERT_STR_SIZE - certStr_len - 1);
169
170
171
172
173
174
175
176

177
178
179
180

181
182
183
184
185














186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
136
137
138
139
140
141
142

143
144
145
146

147

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169



170
171
172
173
174
175
176

177
178
179
180
181
182
183
184







-
+



-
+
-




+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-







-
+







                certStr_len += n;
                certStr_p   += n;
            }
            *certStr_p = '\0';
            (void)BIO_flush(bio);
        }

	/* All */
	/* Get all cert info */
	if (X509_print_ex(bio, cert, flags, 0)) {
	    char all[65536];
	    n = BIO_read(bio, all, min(BIO_pending(bio), 65535));
	    n = max(n, 0);
	    all[max(n, 0)] = 0;
	    all[n] = 0;
	    (void)BIO_flush(bio);
	    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("all", -1));
	    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(all, n));
	}

	/* Get Validity - Not Before */
	if (ASN1_TIME_print(bio, X509_get_notBefore(cert))) {
	    n = BIO_read(bio, notBefore, min(BIO_pending(bio), BUFSIZ - 1));
	    notBefore[max(n, 0)] = 0;
	    (void)BIO_flush(bio);
	}

	/* Get Validity - Not After */
	if (ASN1_TIME_print(bio, X509_get_notAfter(cert))) {
	    n = BIO_read(bio, notAfter, min(BIO_pending(bio), BUFSIZ - 1));
	    notAfter[max(n, 0)] = 0;
	    (void)BIO_flush(bio);
	}

	BIO_free(bio);
    }

    strcpy(notBefore, ASN1_UTCTIME_tostr(X509_get0_notBefore(cert)));
    strcpy(notAfter, ASN1_UTCTIME_tostr(X509_get0_notAfter(cert)));

    /* Version */
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("version", -1));
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewLongObj(X509_get_version(cert)+1));

    /* Signature algorithm */
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("signature", -1));
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(OBJ_nid2ln(X509_get_signature_nid(cert)),-1));
 

    /* SHA1 Fingerprint of cert - DER representation */
    X509_digest(cert, EVP_sha1(), sha1_hash_binary, &len);
    len = String_to_Hex(sha1_hash_binary, len, buffer, BUFSIZ);
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("sha1_hash", -1));
    Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len));

    /* SHA256 Fingerprint of cert - DER representation */
240
241
242
243
244
245
246
247

248
249
250
251
252
253

254
255
256
257
258
259
260
217
218
219
220
221
222
223

224
225
226
227
228
229

230
231
232
233
234
235
236
237







-
+





-
+







	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(OBJ_nid2ln(nid),-1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("publicKeyAlgorithm", -1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(OBJ_nid2ln(pknid),-1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("bits", -1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewIntObj(bits));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("extension_flags", -1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewIntObj(xflags));
	

	/* Public key - X509_get0_pubkey */
	key = X509_get0_pubkey_bitstr(cert);
	len = String_to_Hex(key->data, key->length, buffer, BUFSIZ);
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("publicKey", -1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len));
	

	/* Check if cert was issued by CA cert issuer or self signed */
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("self_signed", -1));
	Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewBooleanObj(X509_check_issued(cert, cert) == X509_V_OK));
    }

    /* Unique Ids */
    {