1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

mbedtls: add AKID and SKID support

This commit is contained in:
Andy Green 2021-06-16 07:08:50 +01:00
parent b25079c4b4
commit 983edafdb4
18 changed files with 835 additions and 39 deletions

View file

@ -47,6 +47,14 @@ enum lws_tls_cert_info {
* -1 is returned and the size will be returned in buf->ns.len.
* If the certificate cannot be found -1 is returned and 0 in
* buf->ns.len. */
LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
/**< If the cert has one, the key ID responsible for the signature */
LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER,
/**< If the cert has one, the issuer responsible for the signature */
LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL,
/**< If the cert has one, serial number responsible for the signature */
LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
/**< If the cert has one, the cert's subject key ID */
};
union lws_tls_cert_info_results {

View file

@ -121,6 +121,7 @@ if (LWS_WITH_SSL)
if (LWS_WITH_MBEDTLS)
list(APPEND SOURCES
tls/mbedtls/mbedtls-tls.c
tls/mbedtls/mbedtls-extensions.c
tls/mbedtls/mbedtls-x509.c)
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
@ -335,6 +336,7 @@ if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS)
# what's in an openssl also installed on the build host
CHECK_C_SOURCE_COMPILES("#include <openssl/ssl.h>\nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
CHECK_C_SOURCE_COMPILES("#include <openssl/ssl.h>\nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free)
CHECK_C_SOURCE_COMPILES("#include <openssl/ssl.h>\nint main(void) { OPENSSL_STACK *x = NULL; return !x; } \n" LWS_HAVE_OPENSSL_STACK)
set(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS ${LWS_HAVE_SSL_EXTRA_CHAIN_CERTS} PARENT_SCOPE)
set(LWS_HAVE_EVP_MD_CTX_free ${LWS_HAVE_EVP_MD_CTX_free} PARENT_SCOPE)
CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0 PARENT_SCOPE)
@ -352,6 +354,8 @@ if (LWS_WITH_MBEDTLS)
set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1 PARENT_SCOPE)
endif()
CHECK_C_SOURCE_COMPILES("#include <mbedtls/x509_crt.h>\nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID)
CHECK_C_SOURCE_COMPILES("#include <mbedtls/ssl.h>\nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify)
CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE)
CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE)
CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE)

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -25,12 +25,6 @@
#include "private-lib-core.h"
#include "private-lib-tls-mbedtls.h"
static int
OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
return 0;
}
int
lws_ssl_client_bio_create(struct lws *wsi)
{
@ -87,8 +81,10 @@ lws_ssl_client_bio_create(struct lws *wsi)
alpn_comma = wsi->a.vhost->tls.alpn;
if (wsi->stash) {
lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname));
alpn_comma = wsi->stash->cis[CIS_ALPN];
lws_strncpy(hostname, wsi->stash->cis[CIS_HOST],
sizeof(hostname));
if (wsi->stash->cis[CIS_ALPN])
alpn_comma = wsi->stash->cis[CIS_ALPN];
} else {
if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
_WSI_TOKEN_CLIENT_ALPN) > 0)
@ -108,8 +104,6 @@ lws_ssl_client_bio_create(struct lws *wsi)
* use server name indication (SNI), if supported,
* when establishing connection
*/
SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
OpenSSL_client_verify_callback);
SSL_set_fd(wsi->tls.ssl, (int)wsi->desc.sockfd);
@ -195,16 +189,13 @@ enum lws_ssl_capable_status
lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
{
int m, n = SSL_connect(wsi->tls.ssl), en;
const unsigned char *prot;
unsigned int len;
if (n == 1) {
SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len);
lws_role_call_alpn_negotiated(wsi, (const char *)prot);
lws_tls_server_conn_alpn(wsi);
#if defined(LWS_WITH_TLS_SESSIONS)
lws_tls_session_new_mbedtls(wsi);
#endif
lwsl_info("client connect OK\n");
lwsl_info("%s: client connect OK\n", __func__);
return LWS_SSL_CAPABLE_DONE;
}

View file

@ -0,0 +1,476 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* These are additional apis that belong in mbedtls but do not yet exist there.
* Alternaives are provided for lws to use that understand additional standard
* v3 tls extensions. Error results are simplified to lws style.
*
* This file includes code taken from mbedtls and modified, and from an as of
* 2021-06-11 unaccepted-upstream patch for mbedtls contributed by Gábor Tóth
* <toth92g@gmail.com>. Gabor has graciously allowed use of his patch with more
* liberal terms but to not complicate matters I provide it here under the same
* Apache 2.0 terms as the mbedtls pieces.
*
* Those original pieces are licensed Apache-2.0 as follows
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "private-lib-core.h"
#include "private-lib-tls-mbedtls.h"
#include <mbedtls/oid.h>
#include <mbedtls/x509.h>
/*
* This section from mbedtls oid.c
*/
typedef struct {
mbedtls_oid_descriptor_t descriptor;
int ext_type;
} oid_x509_ext_t;
#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s)
#define LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */
#define LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */
#define LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
#define LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
#define LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER
#define LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER
#define LWS_MBEDTLS_X509_SAN_OTHER_NAME 0
#define LWS_MBEDTLS_X509_SAN_RFC822_NAME 1
#define LWS_MBEDTLS_X509_SAN_DNS_NAME 2
#define LWS_MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0
#define LWS_MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F
static const oid_x509_ext_t oid_x509_ext[] = {
{ {ADD_LEN( LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
"id-ce-subjectKeyIdentifier",
"Subject Key Identifier" },
LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
},
{ {ADD_LEN( LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
"id-ce-authorityKeyIdentifier",
"Authority Key Identifier" },
LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
},
{ { NULL, 0 }, 0 },
};
#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \
static const TYPE_T * oid_ ## NAME ## _from_asn1( \
const mbedtls_asn1_buf *oid ) \
{ \
const TYPE_T *p = (LIST); \
const mbedtls_oid_descriptor_t *cur = \
(const mbedtls_oid_descriptor_t *) p; \
if( p == NULL || oid == NULL ) return( NULL ); \
while( cur->asn1 != NULL ) { \
if( cur->asn1_len == oid->len && \
memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \
return( p ); \
} \
p++; \
cur = (const mbedtls_oid_descriptor_t *) p; \
} \
return( NULL ); \
}
#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
{ \
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
if (!data) return 1; \
*ATTR1 = data->ATTR1; \
return 0; \
}
FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
FN_OID_GET_ATTR1(lws_mbedtls_oid_get_x509_ext_type,
oid_x509_ext_t, x509_ext, int, ext_type)
typedef struct lws_mbedtls_x509_san_other_name
{
/**
* The type_id is an OID as deifned in RFC 5280.
* To check the value of the type id, you should use
* \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
*/
mbedtls_x509_buf type_id; /**< The type id. */
union
{
/**
* From RFC 4108 section 5:
* HardwareModuleName ::= SEQUENCE {
* hwType OBJECT IDENTIFIER,
* hwSerialNum OCTET STRING }
*/
struct
{
mbedtls_x509_buf oid; /**< The object identifier. */
mbedtls_x509_buf val; /**< The named value. */
}
hardware_module_name;
}
value;
}
lws_mbedtls_x509_san_other_name;
typedef struct lws_mbedtls_x509_subject_alternative_name
{
int type; /**< The SAN type, value of LWS_MBEDTLS_X509_SAN_XXX. */
union {
lws_mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
}
san; /**< A union of the supported SAN types */
}
lws_mbedtls_x509_subject_alternative_name;
static int
x509_get_skid(uint8_t **p, const uint8_t *end, mbedtls_x509_buf *skid)
{
int ret = 1;
size_t len = 0u;
ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (ret)
return ret;
skid->len = len;
skid->tag = MBEDTLS_ASN1_OCTET_STRING;
skid->p = *p;
*p += len;
return *p != end;
}
static int
lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf,
lws_mbedtls_x509_subject_alternative_name *name)
{
// mbedtls_x509_name_other_name other_name;
uint8_t *bufferPointer, **p, *end;
mbedtls_x509_name rfc822Name;
int ret;
switch (name_buf->tag & (LWS_MBEDTLS_ASN1_TAG_CLASS_MASK |
LWS_MBEDTLS_ASN1_TAG_VALUE_MASK)) {
#if 0
case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_OTHER_NAME:
ret = x509_get_other_name( name_buf, &other_name );
if (ret)
return ret;
memset(name, 0, sizeof(*name));
name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME;
memcpy(&name->name.other_name, &other_name, sizeof(other_name));
return 0;
#endif
case MBEDTLS_ASN1_SEQUENCE | LWS_MBEDTLS_X509_SAN_RFC822_NAME:
bufferPointer = name_buf->p;
p = &bufferPointer;
end = name_buf->p + name_buf->len;
/* The leading ASN1 tag and length has been processed.
* Stepping back with 2 bytes, because mbedtls_x509_get_name
* expects the beginning of the SET tag */
*p = *p - 2;
ret = mbedtls_x509_get_name( p, end, &rfc822Name );
if (ret)
return ret;
memset(name, 0, sizeof(*name));
name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME;
memcpy(&name->san.unstructured_name,
&rfc822Name, sizeof(rfc822Name));
return 0;
case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_DNS_NAME:
memset(name, 0, sizeof(*name));
name->type = LWS_MBEDTLS_X509_SAN_DNS_NAME;
memcpy(&name->san.unstructured_name,
name_buf, sizeof(*name_buf) );
return 0;
default:
return 1;
}
return 1;
}
static int
lws_x509_get_general_names(uint8_t **p, const uint8_t *end,
mbedtls_x509_sequence *name )
{
mbedtls_asn1_sequence *cur = name;
mbedtls_asn1_buf *buf;
size_t len, tag_len;
unsigned char tag;
int r;
/* Get main sequence tag */
r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (r)
return r;
if (*p + len != end)
return 1;
while (*p < end) {
lws_mbedtls_x509_subject_alternative_name dnb;
memset(&dnb, 0, sizeof(dnb));
tag = **p;
(*p)++;
r = mbedtls_asn1_get_len(p, end, &tag_len);
if (r)
return r;
/* Tag shall be CONTEXT_SPECIFIC or SET */
if ((tag & LWS_MBEDTLS_ASN1_TAG_CLASS_MASK) !=
MBEDTLS_ASN1_CONTEXT_SPECIFIC &&
(tag & (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE))
return 1;
/*
* Check that the name is structured correctly.
*/
r = lws_mbedtls_x509_parse_general_name(&cur->buf, &dnb);
/*
* In case the extension is malformed, return an error,
* and clear the allocated sequences.
*/
if (r && r != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
mbedtls_x509_sequence *seq_cur = name->next;
mbedtls_x509_sequence *seq_prv;
while( seq_cur != NULL ) {
seq_prv = seq_cur;
seq_cur = seq_cur->next;
lws_explicit_bzero(seq_prv, sizeof(*seq_cur));
lws_free(seq_prv);
}
name->next = NULL;
return r;
}
/* Allocate and assign next pointer */
if (cur->buf.p) {
if (cur->next)
return 1;
cur->next = lws_zalloc(sizeof(*cur), __func__);
if (!cur->next)
return 1;
cur = cur->next;
}
buf = &(cur->buf);
buf->tag = tag;
buf->p = *p;
buf->len = tag_len;
*p += buf->len;
}
/* Set final sequence entry's next pointer to NULL */
cur->next = NULL;
return *p != end;
}
static int
x509_get_akid(uint8_t **p, uint8_t *end, lws_mbedtls_x509_authority *akid)
{
size_t len = 0u;
int r;
r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (r)
return r;
r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (!r) {
akid->keyIdentifier.len = len;
akid->keyIdentifier.p = *p;
akid->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;
*p += len;
}
if (*p < end) {
/* Getting authorityCertIssuer using the required specific
* class tag [1] */
r = mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 1 );
if (!r) {
/* Getting directoryName using the required specific
* class tag [4] */
r = mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 4);
if (r)
return(r);
/* "end" also includes the CertSerialNumber field
* so "len" shall be used */
r = lws_x509_get_general_names(p, (*p + len),
&akid->authorityCertIssuer);
}
}
if (*p < end) {
r = mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_INTEGER );
if (r)
return r;
akid->authorityCertSerialNumber.len = len;
akid->authorityCertSerialNumber.p = *p;
akid->authorityCertSerialNumber.tag = MBEDTLS_ASN1_OCTET_STRING;
*p += len;
}
return *p != end;
}
/*
* Work around lack of this in mbedtls... we don't need to do sanity checks
* sanity checks because they will be done at x509 validation time
*/
int
lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid,
lws_mbedtls_x509_authority *akid)
{
uint8_t *p = crt->v3_ext.p, *end_ext_data, *end_ext_octet;
const uint8_t *end = p + crt->v3_ext.len;
size_t len;
int r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (r)
return r;
while (p < end) {
mbedtls_x509_buf extn_oid = { 0, 0, NULL };
int is_critical = 0; /* DEFAULT FALSE */
int ext_type = 0;
r = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (r)
return r;
end_ext_data = p + len;
/* Get extension ID */
r = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.len,
MBEDTLS_ASN1_OID);
if (r)
return r;
extn_oid.tag = MBEDTLS_ASN1_OID;
extn_oid.p = p;
p += extn_oid.len;
/* Get optional critical */
r = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
return r;
/* Data should be octet string type */
r = mbedtls_asn1_get_tag(&p, end_ext_data, &len,
MBEDTLS_ASN1_OCTET_STRING);
if (r)
return r;
end_ext_octet = p + len;
if (end_ext_octet != end_ext_data)
return 1;
r = lws_mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
if (r) {
p = end_ext_octet;
continue;
}
switch (ext_type) {
case LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
/* Parse subject key identifier */
r = x509_get_skid(&p, end_ext_data, skid);
if (r)
return r;
break;
case LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
/* Parse authority key identifier */
r = x509_get_akid(&p, end_ext_octet, akid);
if (r)
return r;
break;
default:
p = end_ext_octet;
}
}
return 0;
}

View file

@ -113,7 +113,7 @@ do_err:
* paths to dump what was received as decrypted data from the tls tunnel
*/
lwsl_notice("%s: len %d\n", __func__, n);
lwsl_hexdump_notice(buf, n);
lwsl_hexdump_notice(buf, (size_t)n);
#endif
#if defined(LWS_WITH_SYS_METRICS)

View file

@ -69,32 +69,43 @@ static int
lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
union lws_tls_cert_info_results *buf, size_t len)
{
int r = -1;
buf->ns.len = 0;
while (name) {
if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
/*
if (MBEDTLS_OID_CMP(type, &name->oid)) {
name = name->next;
continue;
}
*/
lws_strnncpy(&buf->ns.name[buf->ns.len],
(const char *)name->val.p,
name->val.len, len - (size_t)buf->ns.len);
buf->ns.len = (int)strlen(buf->ns.name);
if (len - 1 < name->val.len)
return -1;
memcpy(&buf->ns.name[0], name->val.p, name->val.len);
buf->ns.name[name->val.len] = '\0';
buf->ns.len = (int)name->val.len;
return 0;
r = 0;
name = name->next;
}
return -1;
return r;
}
static int
int
lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
union lws_tls_cert_info_results *buf, size_t len)
{
mbedtls_x509_buf skid;
lws_mbedtls_x509_authority akid;
if (!x509)
return -1;
if (!len)
len = sizeof(buf->ns.name);
switch (type) {
case LWS_TLS_CERT_INFO_VALIDITY_FROM:
buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from);
@ -180,6 +191,77 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
memcpy(buf->ns.name, x509->raw.p, x509->raw.len);
break;
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID:
memset(&akid, 0, sizeof(akid));
memset(&skid, 0, sizeof(skid));
lws_x509_get_crt_ext(x509, &skid, &akid);
if (akid.keyIdentifier.tag != MBEDTLS_ASN1_OCTET_STRING)
return 1;
buf->ns.len = (int)akid.keyIdentifier.len;
if (len < (size_t)buf->ns.len)
return -1;
memcpy(buf->ns.name, akid.keyIdentifier.p, (size_t)buf->ns.len);
break;
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: {
mbedtls_x509_sequence * ip;
memset(&akid, 0, sizeof(akid));
memset(&skid, 0, sizeof(skid));
lws_x509_get_crt_ext(x509, &skid, &akid);
ip = &akid.authorityCertIssuer;
buf->ns.len = 0;
if (!ip)
return 1;
while (ip) {
if (akid.keyIdentifier.tag != MBEDTLS_ASN1_OCTET_STRING ||
ip->buf.len < 9 || len < (size_t)ip->buf.len - 9u)
break;
memcpy(buf->ns.name + buf->ns.len, ip->buf.p,
(size_t)ip->buf.len - 9);
buf->ns.len = buf->ns.len + (int)ip->buf.len - 9;
ip = ip->next;
}
break;
}
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL:
memset(&akid, 0, sizeof(akid));
memset(&skid, 0, sizeof(skid));
lws_x509_get_crt_ext(x509, &skid, &akid);
if (akid.authorityCertSerialNumber.tag != MBEDTLS_ASN1_OCTET_STRING)
return 1;
buf->ns.len = (int)akid.authorityCertSerialNumber.len;
if (len < (size_t)buf->ns.len)
return -1;
memcpy(buf->ns.name, akid.authorityCertSerialNumber.p, (size_t)buf->ns.len);
break;
case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID:
memset(&akid, 0, sizeof(akid));
memset(&skid, 0, sizeof(skid));
lws_x509_get_crt_ext(x509, &skid, &akid);
if (skid.tag != MBEDTLS_ASN1_OCTET_STRING)
return 1;;
buf->ns.len = (int)skid.len;
if (len < (size_t)buf->ns.len)
return -1;
memcpy(buf->ns.name, skid.p, (size_t)buf->ns.len);
break;
default:
return -1;
}

View file

@ -31,6 +31,16 @@ struct lws_x509_cert {
mbedtls_x509_crt cert; /* has a .next for linked-list / chain */
};
typedef struct lws_mbedtls_x509_authority
{
mbedtls_x509_buf keyIdentifier;
mbedtls_x509_sequence authorityCertIssuer;
mbedtls_x509_buf authorityCertSerialNumber;
mbedtls_x509_buf raw;
}
lws_mbedtls_x509_authority;
mbedtls_md_type_t
lws_gencrypto_mbedtls_hash_to_MD_TYPE(enum lws_genhash_types hash_type);
@ -39,3 +49,11 @@ lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len);
int
lws_tls_session_new_mbedtls(struct lws *wsi);
int
lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
union lws_tls_cert_info_results *buf, size_t len);
int
lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid,
lws_mbedtls_x509_authority *akid);

View file

@ -31,6 +31,8 @@
#include "ssl_code.h"
#include <mbedtls/x509_crt.h>
typedef void SSL_CIPHER;
typedef void X509_STORE_CTX;
@ -183,7 +185,7 @@ struct ssl_ctx_st
int verify_mode;
int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx);
int (*default_verify_callback) (SSL *, mbedtls_x509_crt *);
long session_timeout;
@ -223,7 +225,7 @@ struct ssl_st
int verify_mode;
int (*verify_callback) (int ok, X509_STORE_CTX *ctx);
int (*verify_callback) (SSL *, mbedtls_x509_crt *);
int rwstate;
int interrupted_remaining_write;

View file

@ -708,7 +708,7 @@ int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
*
* @return none
*/
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *));
/**
* @brief set the SSL verifying of the SSL context
@ -719,7 +719,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509
*
* @return none
*/
void SSL_set_verify(SSL *s, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
void SSL_set_verify(SSL *s, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *));
/**
* @brief set the SSL verify depth of the SSL context
@ -739,7 +739,7 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
*
* @return verifying result
*/
int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx);
int verify_callback(SSL *, mbedtls_x509_crt *);
/**
* @brief set the session timeout time

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_cert.h"
#include "ssl_pkey.h"
#include "ssl_x509.h"

View file

@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_lib.h"
#include "ssl_pkey.h"
#include "ssl_x509.h"
@ -19,8 +22,6 @@
#include "ssl_dbg.h"
#include "ssl_port.h"
#include "private-lib-core.h"
char *
lws_strncpy(char *dest, const char *src, size_t size);
@ -1078,7 +1079,7 @@ void SSL_set_verify_depth(SSL *ssl, int depth)
/**
* @brief set the SSL context verifying of the SSL context
*/
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *))
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *))
{
SSL_ASSERT3(ctx);
@ -1089,7 +1090,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509
/**
* @brief set the SSL verifying of the SSL context
*/
void SSL_set_verify(SSL *ssl, int mode, int (*verify_callback)(int, X509_STORE_CTX *))
void SSL_set_verify(SSL *ssl, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *))
{
SSL_ASSERT3(ssl);

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_methods.h"
#include "ssl_pm.h"

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_pkey.h"
#include "ssl_methods.h"
#include "ssl_dbg.h"

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_stack.h"
#include "ssl_dbg.h"
#include "ssl_port.h"

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_x509.h"
#include "ssl_methods.h"
#include "ssl_dbg.h"

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "private-lib-core.h"
#include "ssl_pm.h"
#include "ssl_port.h"
#include "ssl_dbg.h"
@ -27,9 +29,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
//#include "mbedtls/certs.h"
#include "private-lib-core.h"
#define X509_INFO_STRING_LENGTH 8192
@ -96,6 +96,19 @@ static void ssl_platform_debug(void *ctx, int level,
}
//#endif
#if defined(LWS_HAVE_mbedtls_ssl_set_verify)
static int
lws_mbedtls_f_vrfy(void *opaque, mbedtls_x509_crt *x509, int state, uint32_t *pflags)
{
struct ssl_pm *ssl_pm = (struct ssl_pm *)opaque;
if (ssl_pm->owner->verify_callback)
(ssl_pm->owner->verify_callback)(ssl_pm->owner, x509);
return 0;
}
#endif
/**
* @brief create SSL low-level object
*/
@ -134,6 +147,10 @@ int ssl_pm_new(SSL *ssl)
mbedtls_entropy_init(&ssl_pm->entropy);
mbedtls_ssl_init(&ssl_pm->ssl);
#if defined(LWS_HAVE_mbedtls_ssl_set_verify)
mbedtls_ssl_set_verify(&ssl_pm->ssl, lws_mbedtls_f_vrfy, ssl_pm);
#endif
ret = mbedtls_ctr_drbg_seed(&ssl_pm->ctr_drbg, mbedtls_entropy_func, &ssl_pm->entropy, pers, pers_len);
if (ret) {
lwsl_notice("%s: mbedtls_ctr_drbg_seed() return -0x%x", __func__, -ret);

View file

@ -71,17 +71,33 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
#endif
}
#if defined(USE_WOLFSSL)
#define AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID
#endif
int
lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
union lws_tls_cert_info_results *buf, size_t len)
{
#ifndef USE_WOLFSSL
const unsigned char *dp;
ASN1_OCTET_STRING *val;
AUTHORITY_KEYID *akid;
X509_EXTENSION *ext;
int tag, xclass, r = 1;
long xlen, loc;
#endif
X509_NAME *xn;
#if !defined(LWS_PLAT_OPTEE)
char *p;
#endif
buf->ns.len = 0;
if (!x509)
return -1;
if (!len)
len = sizeof(buf->ns.name);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
#define X509_get_notBefore(x) X509_getm_notBefore(x)
@ -180,6 +196,151 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
return 0;
}
#ifndef USE_WOLFSSL
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID:
loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
if (loc < 0)
return 1;
ext = X509_get_ext(x509, (int)loc);
if (!ext)
return 1;
#ifndef USE_WOLFSSL
akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
#else
akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
#endif
if (!akid || !akid->keyid)
return 1;
val = akid->keyid;
dp = (const unsigned char *)val->data;
xlen = val->length;
buf->ns.len = (int)xlen;
if (len < (size_t)buf->ns.len)
return -1;
memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
AUTHORITY_KEYID_free(akid);
break;
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER:
loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
if (loc < 0)
return 1;
ext = X509_get_ext(x509, (int)loc);
if (!ext)
return 1;
#ifndef USE_WOLFSSL
akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
#else
akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
#endif
if (!akid || !akid->issuer)
return 1;
#if defined(LWS_HAVE_OPENSSL_STACK)
{
const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
STACK_OF(CONF_VALUE) *cv;
int j;
cv = i2v_GENERAL_NAMES((X509V3_EXT_METHOD*)method, akid->issuer, NULL);
if (!cv)
goto bail_ak;
for (j = 0; j < OPENSSL_sk_num((const OPENSSL_STACK *)&cv); j++) {
CONF_VALUE *nval = OPENSSL_sk_value((const OPENSSL_STACK *)&cv, j);
size_t ln = (nval->name ? strlen(nval->name) : 0),
lv = (nval->value ? strlen(nval->value) : 0),
l = ln + lv;
if (len > l) {
if (nval->name)
memcpy(buf->ns.name + buf->ns.len, nval->name, ln);
if (nval->value)
memcpy(buf->ns.name + buf->ns.len + ln, nval->value, lv);
buf->ns.len = (int)((size_t)buf->ns.len + l);
len -= l;
buf->ns.name[buf->ns.len] = '\0';
r = 0;
}
}
}
bail_ak:
#endif
AUTHORITY_KEYID_free(akid);
return r;
case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL:
loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
if (loc < 0)
return 1;
ext = X509_get_ext(x509, (int)loc);
if (!ext)
return 1;
akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
if (!akid || !akid->serial)
return 1;
#if 0
// need to handle blobs, and ASN1_INTEGER_get_uint64 not
// available on older openssl
{
uint64_t res;
if (ASN1_INTEGER_get_uint64(&res, akid->serial) != 1)
break;
buf->ns.len = lws_snprintf(buf->ns.name, len, "%llu",
(unsigned long long)res);
}
#endif
break;
case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID:
loc = X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1);
if (loc < 0)
return 1;
ext = X509_get_ext(x509, (int)loc);
if (!ext)
return 1;
val = X509_EXTENSION_get_data(ext);
if (!val)
return 1;
#if defined(USE_WOLFSSL)
return 1;
#else
dp = (const unsigned char *)val->data;
if (ASN1_get_object(&dp, &xlen,
&tag, &xclass, val->length) & 0x80)
return -1;
if (tag != V_ASN1_OCTET_STRING) {
lwsl_notice("not octet string %d\n", (int)tag);
return 1;
}
#endif
buf->ns.len = (int)xlen;
if (len < (size_t)buf->ns.len)
return -1;
memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
break;
#endif
default:
return -1;
}

View file

@ -78,6 +78,28 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
lwsl_notice(" Peer Cert public key:\n");
lwsl_hexdump_notice(ci->ns.name, (unsigned int)ci->ns.len);
}
if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
ci, 0)) {
lwsl_notice(" AUTHORITY_KEY_ID\n");
lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len);
}
if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER,
ci, 0)) {
lwsl_notice(" AUTHORITY_KEY_ID ISSUER\n");
lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len);
}
if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL,
ci, 0)) {
lwsl_notice(" AUTHORITY_KEY_ID SERIAL\n");
lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len);
}
if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
ci, 0)) {
lwsl_notice(" AUTHORITY_KEY_ID SUBJECT_KEY_ID\n");
lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len);
}
break;
/* chunks of chunked content, with header removed */
@ -207,6 +229,10 @@ int main(int argc, const char **argv)
i.port = 443;
i.address = "warmcat.com";
}
if ((p = lws_cmdline_option(argc, argv, "-s")))
i.address = p;
i.path = "/";
i.host = i.address;
i.origin = i.address;