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