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:
parent
b25079c4b4
commit
983edafdb4
18 changed files with 835 additions and 39 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
476
lib/tls/mbedtls/mbedtls-extensions.c
Normal file
476
lib/tls/mbedtls/mbedtls-extensions.c
Normal 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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue