Open igrr opened 7 years ago
For me situation is very simple. In my app I plan to only have two server cert to trust. Initially slot1==slot2==server. If server cert changes I plan to change slot2 to the new cert, then both old and new cert will work for a while until I have confirmation from all devices...
Using the openssl
command I found that not all of the certs in ca-bundle.crt
created by mk-ca-bundle.pl have the authority key identifier extension so I wrote a quick hack to process the file and print out one line with each identifier. Only 37 of the 143 entries have the extension.
15:47:18 certmaker chris.l$ ./Debug/certmaker <ca-bundle.crt | wc -l
37
15:47:30 certmaker chris.l$ grep BEGIN ca-bundle.crt | wc -l
143
Hack:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
int main(void) {
FILE *arq = stdin; // fopen("<path to your certificate in PEM format>","rw");
while(!feof(stdin))
{
int next;
X509 *cert;
cert = PEM_read_X509(arq,NULL,NULL, NULL);
if (!cert)
{
break;
}
X509_EXTENSION *ext;
next = X509_get_ext_count(cert);
for (int i=0;i<next;i++)
{
ext = X509_get_ext(cert, i);
int nid = OBJ_obj2nid(ext->object);
if(nid == NID_authority_key_identifier)
{
AUTHORITY_KEYID *authKeyId = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
//converting to hex
char *hex_data = malloc(authKeyId->keyid->length*2 +1);
int j = 0;
for(int i = 0; i < authKeyId->keyid->length; i++)
{
sprintf(&hex_data[j], "%02X", authKeyId->keyid->data[i]);
j+=2;
}
hex_data[j] = '\0';
printf("id: %s\n", hex_data);
free(hex_data);
}
}
}
}
AFAIK the root certificates do not necessarily have authorityKeyIdentifer. The certificates signed by root certificates, on the other hand, should have the authorityKeyIdentifer. Do you have an example of a certificate which is non-root and doesn't have the authorityKeyIdentifer?
Ahh. I think I misunderstood. I just re-read 4.2.1.1. Authority Key Identifier as well as the next section that describes methods to generate the key identifier. Ok so they list 2 methods but also say that other methods are acceptable... whats the plan to generate the local root cert store? Assume one of the methods? Or empirically by locating certs signed with the root key? Asking because I'll try writing something C or perl that will generate it. (was going to do that based on DN)
Loading a full root certificate store into memory in the way it is currently implemented in axTLS will quickly cause an out-of-memory condition on the ESP8266. Certificates themselves, in DER format, can also occupy significant chunk of program memory. For this reason, in the past we have implemented certificate fingerprint verification. Certificate fingerprint verification suffers from poor UX though, as certificates get renewed and fingerprints change. Recently merged SPKI verification (#31) can potentially help with the renewal issues, but support for displaying SHA-256 hash of SPKI is not present in all major browsers, complicating the process for new users.
Considering the way axTLS performs certificate chain verification, we don't actually need to know the full contents of root certificate. AxTLS only uses the public key to perform verification. In addition to that, DN is used to identify the root certificate to be used, and basic constraint info is checked in the latest version.
The basic constraint info can be checked before creating a root certificate bundle for axTLS, in a way similar to curl's mk-ca-bundle.pl.
Instead of using DN to match root certificate, we can use authority key identifier extension, which "MUST be included in all certificates generated by conforming CAs" according to the RFC. Authority key identifier is basically a SHA-1 hash of the CA's public key.
With this in mind, for each root certificate we need about (RSAkeySize/8 + 30) bytes of storage. SHA-1 hashes of
authorityKeyIdentifier
s can be stored in a heap structure in program memory (PROGMEM
), making RAM overhead essentially zero. Limiting the number of root certificates in the store to ~20 most common ones we can keep the program memory cost small, and provide good out of the box experience for users at the same time.This issue seeks discussion about the overall idea and specific APIs which will be used to expose this new mechanism.
/cc @slaff @ADiea