1d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/* 2d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * Hotspot 2.0 OSU client - EST client 36cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt * Copyright (c) 2012-2014, Qualcomm Atheros, Inc. 4d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * 5d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * This software may be distributed under the terms of the BSD license. 6d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * See README for more details. 7d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt */ 8d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 9d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "includes.h" 10d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/err.h> 11d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/evp.h> 12d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/pem.h> 13d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/pkcs7.h> 14d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/rsa.h> 15d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/asn1.h> 16d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/asn1t.h> 17d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/x509.h> 18d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/x509v3.h> 19d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 20d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "common.h" 21d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "utils/base64.h" 22d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "utils/xml-utils.h" 23d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "utils/http-utils.h" 24d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "osu_client.h" 25d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 26d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 27d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7, 28d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t len, char *pem_file, char *der_file) 29d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 30d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt PKCS7 *p7 = NULL; 31d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt const unsigned char *p = pkcs7; 32d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509) *certs; 33d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int i, num, ret = -1; 34d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO *out = NULL; 35d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 36d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt p7 = d2i_PKCS7(NULL, &p, len); 37d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (p7 == NULL) { 38d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s", 39d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ERR_error_string(ERR_get_error(), NULL)); 40d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Could not parse PKCS#7 object from EST"); 41d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 42d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 43d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 44d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt switch (OBJ_obj2nid(p7->type)) { 45d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt case NID_pkcs7_signed: 46d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt certs = p7->d.sign->cert; 47d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt break; 48d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt case NID_pkcs7_signedAndEnveloped: 49d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt certs = p7->d.signed_and_enveloped->cert; 50d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt break; 51d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt default: 52d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt certs = NULL; 53d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt break; 54d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 55d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 56d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!certs || ((num = sk_X509_num(certs)) == 0)) { 57d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object"); 58d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "No certificates found in PKCS#7 object"); 59d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 60d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 61d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 62d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (der_file) { 63d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f = fopen(der_file, "wb"); 64d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f == NULL) 65d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 66d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt i2d_X509_fp(f, sk_X509_value(certs, 0)); 67d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 68d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 69d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 70d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pem_file) { 71d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt out = BIO_new(BIO_s_file()); 72d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (out == NULL || 73d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_write_filename(out, pem_file) <= 0) 74d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 75d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 76d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt for (i = 0; i < num; i++) { 77d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509 *cert = sk_X509_value(certs, i); 78d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_print(out, cert); 79d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt PEM_write_bio_X509(out, cert); 80d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_puts(out, "\n"); 81d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 82d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 83d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 84d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ret = 0; 85d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 86d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtfail: 87d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt PKCS7_free(p7); 88d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (out) 89d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free_all(out); 90d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 91d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return ret; 92d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 93d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 94d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 95d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint est_load_cacerts(struct hs20_osu_client *ctx, const char *url) 96d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 97d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *buf, *resp; 98d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t buflen; 99d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unsigned char *pkcs7; 100d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t pkcs7_len, resp_len; 101d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res; 102d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 103d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buflen = os_strlen(url) + 100; 104d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf = os_malloc(buflen); 105d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (buf == NULL) 106d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 107d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 108d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(buf, buflen, "%s/cacerts", url); 109d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf); 110d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "Download EST cacerts from %s", buf); 1116cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 1; 1126cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 1); 113d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt", 114d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ctx->ca_fname); 1156cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 1166cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); 1176cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 0; 118d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0) { 119d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s", 120d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf); 121d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Failed to download EST cacerts from %s", 122d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf); 123d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(buf); 124d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 125d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 126d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(buf); 127d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 128d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt resp = os_readfile("Cert/est-cacerts.txt", &resp_len); 129d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (resp == NULL) { 130d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt"); 131d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Could not read EST cacerts"); 132d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 133d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 134d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 135d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len); 136d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7 && pkcs7_len < resp_len / 2) { 137d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary", 138d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt (unsigned int) pkcs7_len, (unsigned int) resp_len); 139d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(pkcs7); 140d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7 = NULL; 141d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 142d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7 == NULL) { 143d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7"); 144d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7 = os_malloc(resp_len); 145d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7) { 146d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_memcpy(pkcs7, resp, resp_len); 147d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7_len = resp_len; 148d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 149d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 150d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(resp); 151d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 152d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7 == NULL) { 153d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts"); 154d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Could not fetch EST PKCS#7 cacerts"); 155d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 156d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 157d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 158d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem", 159d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt NULL); 160d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(pkcs7); 161d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0) { 162d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response"); 163d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response"); 164d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 165d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 166d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unlink("Cert/est-cacerts.txt"); 167d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 168d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return 0; 169d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 170d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 171d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 172d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/* 173d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID 174d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * 175d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * AttrOrOID ::= CHOICE { 176d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * oid OBJECT IDENTIFIER, 177d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * attribute Attribute } 178d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * 179d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * Attribute ::= SEQUENCE { 180d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * type OBJECT IDENTIFIER, 181d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * values SET SIZE(1..MAX) OF OBJECT IDENTIFIER } 182d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt */ 183d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 184d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct { 185d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_OBJECT *type; 186d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(ASN1_OBJECT) *values; 187d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} Attribute; 188d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 189d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct { 190d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int type; 191d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt union { 192d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_OBJECT *oid; 193d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt Attribute *attribute; 194d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } d; 195d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} AttrOrOID; 196d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 197d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct { 198d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int type; 199d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(AttrOrOID) *attrs; 200d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} CsrAttrs; 201d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 202d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(Attribute) = { 203d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_SIMPLE(Attribute, type, ASN1_OBJECT), 204d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_SET_OF(Attribute, values, ASN1_OBJECT) 205d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(Attribute); 206d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 207d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_CHOICE(AttrOrOID) = { 208d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT), 209d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute) 210d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_CHOICE_END(AttrOrOID); 211d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 212d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_CHOICE(CsrAttrs) = { 213d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID) 214d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_CHOICE_END(CsrAttrs); 215d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 216d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtIMPLEMENT_ASN1_FUNCTIONS(CsrAttrs); 217d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 218d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 219d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid, 220d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509_EXTENSION) *exts) 221d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 222d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char txt[100]; 223d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res; 224d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 225d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!oid) 226d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 227d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 228d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = OBJ_obj2txt(txt, sizeof(txt), oid, 1); 229d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0 || res >= (int) sizeof(txt)) 230d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 231d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 232d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) { 233d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "TODO: csrattr challengePassword"); 234d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) { 235d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption"); 236d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else { 237d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt); 238d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 239d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 240d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 241d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 242d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_csrattrs_ext_req(struct hs20_osu_client *ctx, 243d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(ASN1_OBJECT) *values, 244d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509_EXTENSION) *exts) 245d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 246d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char txt[100]; 247d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int i, num, res; 248d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 249d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt num = sk_ASN1_OBJECT_num(values); 250d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt for (i = 0; i < num; i++) { 251d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i); 252d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 253d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = OBJ_obj2txt(txt, sizeof(txt), oid, 1); 254d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0 || res >= (int) sizeof(txt)) 255d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt continue; 256d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 257d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) { 258d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "TODO: extReq macAddress"); 259d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) { 260d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "TODO: extReq imei"); 261d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) { 262d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "TODO: extReq meid"); 263d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) { 264d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "TODO: extReq DevId"); 265d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else { 266d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s", 267d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt txt); 268d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 269d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 270d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 271d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 272d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 273d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr, 274d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509_EXTENSION) *exts) 275d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 276d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char txt[100], txt2[100]; 277d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int i, num, res; 278d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 279d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!attr || !attr->type || !attr->values) 280d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 281d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 282d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1); 283d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0 || res >= (int) sizeof(txt)) 284d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 285d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 286d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) { 287d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt add_csrattrs_ext_req(ctx, attr->values, exts); 288d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 289d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 290d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 291d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt num = sk_ASN1_OBJECT_num(attr->values); 292d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt for (i = 0; i < num; i++) { 293d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i); 294d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 295d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1); 296d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0 || res >= (int) sizeof(txt2)) 297d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt continue; 298d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 299d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s", 300d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt txt, txt2); 301d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 302d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 303d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 304d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 305d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs, 306d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509_EXTENSION) *exts) 307d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 308d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int i, num; 309d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 310d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!csrattrs || ! csrattrs->attrs) 311d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return; 312d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 313d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt num = SKM_sk_num(AttrOrOID, csrattrs->attrs); 314d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt for (i = 0; i < num; i++) { 315d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i); 316d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt switch (ao->type) { 317d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt case 0: 318d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt add_csrattrs_oid(ctx, ao->d.oid, exts); 319d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt break; 320d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt case 1: 321d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt add_csrattrs_attr(ctx, ao->d.attribute, exts); 322d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt break; 323d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 324d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 325d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 326d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 327d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 328d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int generate_csr(struct hs20_osu_client *ctx, char *key_pem, 329d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *csr_pem, char *est_req, char *old_cert, 330d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt CsrAttrs *csrattrs) 331d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 332d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt EVP_PKEY_CTX *pctx = NULL; 333d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt EVP_PKEY *pkey = NULL; 334d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt RSA *rsa; 335d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_REQ *req = NULL; 336d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int ret = -1; 337d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unsigned int val; 338d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_NAME *subj = NULL; 339d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char name[100]; 340d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt STACK_OF(X509_EXTENSION) *exts = NULL; 341d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_EXTENSION *ex; 342d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO *out; 343d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 344d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Generate RSA private key"); 345d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "Generate RSA private key"); 346d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); 347d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!pctx) 348d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 349d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 350d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (EVP_PKEY_keygen_init(pctx) <= 0) 351d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 352d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 353d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0) 354d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 355d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 356d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (EVP_PKEY_keygen(pctx, &pkey) <= 0) 357d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 358d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt EVP_PKEY_CTX_free(pctx); 359d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pctx = NULL; 360d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 361d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt rsa = EVP_PKEY_get1_RSA(pkey); 362d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (rsa == NULL) 363d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 364d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 365d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (key_pem) { 366d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f = fopen(key_pem, "wb"); 367d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f == NULL) 368d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 369d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL, 370d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt NULL)) { 371d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not write private key: %s", 372d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ERR_error_string(ERR_get_error(), NULL)); 373d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 374d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 375d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 376d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 377d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 378d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 379d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Generate CSR"); 380d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "Generate CSR"); 381d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt req = X509_REQ_new(); 382d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (req == NULL) 383d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 384d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 385d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (old_cert) { 386d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f; 387d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509 *cert; 388d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res; 389d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 390d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt f = fopen(old_cert, "r"); 391d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f == NULL) 392d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 393d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt cert = PEM_read_X509(f, NULL, NULL, NULL); 394d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 395d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 396d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (cert == NULL) 397d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 398d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = X509_REQ_set_subject_name(req, 399d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_get_subject_name(cert)); 400d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_free(cert); 401d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!res) 402d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 403d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else { 404d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_get_random((u8 *) &val, sizeof(val)); 405d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(name, sizeof(name), "cert-user-%u", val); 406d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt subj = X509_NAME_new(); 407d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (subj == NULL || 408d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt !X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC, 409d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt (unsigned char *) name, 410d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt -1, -1, 0) || 411d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt !X509_REQ_set_subject_name(req, subj)) 412d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 413d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_NAME_free(subj); 414d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt subj = NULL; 415d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 416d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 417d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!X509_REQ_set_pubkey(req, pkey)) 418d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 419d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 420d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt exts = sk_X509_EXTENSION_new_null(); 421d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!exts) 422d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 423d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 424d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, 425d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "CA:FALSE"); 426d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ex == NULL || 427d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt !sk_X509_EXTENSION_push(exts, ex)) 428d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 429d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 430d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, 431d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "nonRepudiation,digitalSignature,keyEncipherment"); 432d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ex == NULL || 433d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt !sk_X509_EXTENSION_push(exts, ex)) 434d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 435d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 436d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, 437d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "1.3.6.1.4.1.40808.1.1.2"); 438d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ex == NULL || 439d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt !sk_X509_EXTENSION_push(exts, ex)) 440d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 441d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 442d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt add_csrattrs(ctx, csrattrs, exts); 443d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 444d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!X509_REQ_add_extensions(req, exts)) 445d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 446d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 447d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt exts = NULL; 448d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 449d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!X509_REQ_sign(req, pkey, EVP_sha256())) 450d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 451d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 452d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt out = BIO_new(BIO_s_mem()); 453d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (out) { 454d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *txt; 455d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t rlen; 456d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 457d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_REQ_print(out, req); 458d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt rlen = BIO_ctrl_pending(out); 459d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt txt = os_malloc(rlen + 1); 460d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (txt) { 461d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res = BIO_read(out, txt, rlen); 462d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res > 0) { 463d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt txt[res] = '\0'; 464d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s", 465d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt txt); 466d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 467d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(txt); 468d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 469d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free(out); 470d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 471d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 472d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (csr_pem) { 473d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f = fopen(csr_pem, "w"); 474d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f == NULL) 475d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 476d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_REQ_print_fp(f, req); 477d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!PEM_write_X509_REQ(f, req)) { 478d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 479d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 480d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 481d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 482d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 483d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 484d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (est_req) { 485d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO *mem = BIO_new(BIO_s_mem()); 486d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BUF_MEM *ptr; 487d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *pos, *end, *buf_end; 488d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f; 489d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 490d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (mem == NULL) 491d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 492d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (!PEM_write_bio_X509_REQ(mem, req)) { 493d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free(mem); 494d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 495d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 496d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 497d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_get_mem_ptr(mem, &ptr); 498d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pos = ptr->data; 499d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf_end = pos + ptr->length; 500d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 501d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt /* Remove START/END lines */ 502d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt while (pos < buf_end && *pos != '\n') 503d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pos++; 504d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pos == buf_end) { 505d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free(mem); 506d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 507d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 508d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pos++; 509d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 510d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt end = pos; 511d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt while (end < buf_end && *end != '-') 512d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt end++; 513d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 514d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt f = fopen(est_req, "w"); 515d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f == NULL) { 516d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free(mem); 517d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt goto fail; 518d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 519d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fwrite(pos, end - pos, 1, f); 520d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 521d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 522d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt BIO_free(mem); 523d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 524d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 525d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ret = 0; 526d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtfail: 527d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (exts) 528d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 529d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (subj) 530d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_NAME_free(subj); 531d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (req) 532d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt X509_REQ_free(req); 533d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkey) 534d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt EVP_PKEY_free(pkey); 535d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pctx) 536d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt EVP_PKEY_CTX_free(pctx); 537d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return ret; 538d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 539d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 540d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 541d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint est_build_csr(struct hs20_osu_client *ctx, const char *url) 542d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 543d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *buf; 544d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t buflen; 545d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res; 546d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char old_cert_buf[200]; 547d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *old_cert = NULL; 548d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt CsrAttrs *csrattrs = NULL; 549d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 550d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buflen = os_strlen(url) + 100; 551d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf = os_malloc(buflen); 552d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (buf == NULL) 553d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 554d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 555d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(buf, buflen, "%s/csrattrs", url); 556d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Download csrattrs from %s", buf); 557d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "Download EST csrattrs from %s", buf); 5586cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 1; 5596cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 1); 560d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt", 561d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ctx->ca_fname); 5626cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 5636cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); 5646cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 0; 565d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(buf); 566d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0) { 567d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed"); 568d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else { 569d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t resp_len; 570d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *resp; 571d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unsigned char *attrs; 572d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt const unsigned char *pos; 573d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t attrs_len; 574d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 575d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt resp = os_readfile("Cert/est-csrattrs.txt", &resp_len); 576d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (resp == NULL) { 577d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not read csrattrs"); 578d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 579d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 580d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 581d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt attrs = base64_decode((unsigned char *) resp, resp_len, 582d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt &attrs_len); 583d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(resp); 584d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 585d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (attrs == NULL) { 586d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not base64 decode csrattrs"); 587d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 588d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 589d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unlink("Cert/est-csrattrs.txt"); 590d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 591d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pos = attrs; 592d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len); 593d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(attrs); 594d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (csrattrs == NULL) { 595d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1"); 596d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt /* Continue assuming no additional requirements */ 597d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 598d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 599d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 600d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ctx->client_cert_present) { 601d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(old_cert_buf, sizeof(old_cert_buf), 602d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "SP/%s/client-cert.pem", ctx->fqdn); 603d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt old_cert = old_cert_buf; 604d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 605d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 606d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem", 607d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "Cert/est-req.b64", old_cert, csrattrs); 608d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (csrattrs) 609d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt CsrAttrs_free(csrattrs); 610d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 611d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return res; 612d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 613d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 614d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 615d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint est_simple_enroll(struct hs20_osu_client *ctx, const char *url, 616d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt const char *user, const char *pw) 617d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 618d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char *buf, *resp, *req, *req2; 619d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt size_t buflen, resp_len, len, pkcs7_len; 620d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt unsigned char *pkcs7; 621d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt FILE *f; 622d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char client_cert_buf[200]; 623d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char client_key_buf[200]; 624d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt const char *client_cert = NULL, *client_key = NULL; 625d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int res; 626d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 627d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt req = os_readfile("Cert/est-req.b64", &len); 628d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (req == NULL) { 629d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Could not read Cert/req.b64"); 630d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 631d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 632d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt req2 = os_realloc(req, len + 1); 633d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (req2 == NULL) { 634d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(req); 635d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 636d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 637d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt req2[len] = '\0'; 638d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt req = req2; 639d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req); 640d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 641d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buflen = os_strlen(url) + 100; 642d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt buf = os_malloc(buflen); 643d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (buf == NULL) { 644d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(req); 645d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 646d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 647d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 648d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ctx->client_cert_present) { 649d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(buf, buflen, "%s/simplereenroll", url); 650d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(client_cert_buf, sizeof(client_cert_buf), 651d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "SP/%s/client-cert.pem", ctx->fqdn); 652d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt client_cert = client_cert_buf; 653d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(client_key_buf, sizeof(client_key_buf), 654d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "SP/%s/client-key.pem", ctx->fqdn); 655d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt client_key = client_key_buf; 656d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } else 657d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_snprintf(buf, buflen, "%s/simpleenroll", url); 658d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf); 659d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "EST simpleenroll URL: %s", buf); 6606cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 1; 6616cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 1); 662d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt resp = http_post(ctx->http, buf, req, "application/pkcs10", 663d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "Content-Transfer-Encoding: base64", 664d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ctx->ca_fname, user, pw, client_cert, client_key, 665d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt &resp_len); 6666cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt http_ocsp_set(ctx->http, 6676cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); 6686cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt ctx->no_osu_cert_validation = 0; 669d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(buf); 670d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (resp == NULL) { 671d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST certificate enrollment failed"); 672d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "EST certificate enrollment failed"); 673d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 674d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 675d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp); 676d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt f = fopen("Cert/est-resp.raw", "w"); 677d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (f) { 678d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fwrite(resp, resp_len, 1, f); 679d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt fclose(f); 680d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 681d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 682d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len); 683d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7 == NULL) { 684d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7"); 685d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7 = os_malloc(resp_len); 686d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7) { 687d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_memcpy(pkcs7, resp, resp_len); 688d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt pkcs7_len = resp_len; 689d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 690d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 691d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(resp); 692d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 693d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (pkcs7 == NULL) { 694d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response"); 695d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "Failed to parse EST simpleenroll base64 response"); 696d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 697d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 698d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 699d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem", 700d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "Cert/est_cert.der"); 701d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_free(pkcs7); 702d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 703d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (res < 0) { 704d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file"); 705d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file"); 706d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 707d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 708d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 709d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "EST simple%senroll completed successfully", 710d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ctx->client_cert_present ? "re" : ""); 711d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt write_summary(ctx, "EST simple%senroll completed successfully", 712d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ctx->client_cert_present ? "re" : ""); 713d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 714d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return 0; 715d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 716