--- /dev/null
+/*
+ * Copyright (C) 2022 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/ocsp_response.h>
+#include <credentials/certificates/ac.h>
+
+#include <time.h>
+
+/**
+ * RSA private key, so we don't have to generate one
+ */
+static char keydata[] = {
+ 0x30,0x82,0x02,0x5e,0x02,0x01,0x00,0x02,0x81,0x81,0x00,0xb1,0x9b,0xd4,0x51,0x24,
+ 0xfc,0x56,0x1d,0x3d,0xfb,0xa2,0xea,0x37,0x02,0x70,0x72,0x87,0x84,0x2f,0x3b,0x2d,
+ 0x6e,0x22,0xef,0x3f,0x37,0x04,0xb2,0x6f,0xb7,0xe7,0xd8,0x58,0x05,0xde,0x34,0xbf,
+ 0x99,0xe6,0x40,0x7a,0x56,0xa7,0x73,0xf5,0x98,0xcb,0xb0,0x37,0x90,0x5e,0xd1,0x3f,
+ 0xf4,0x73,0x50,0x7f,0x53,0x8e,0xf1,0x04,0x25,0xb4,0x77,0x22,0x4e,0x8a,0x9d,0x27,
+ 0x8f,0x6f,0xaf,0x59,0xbd,0xb0,0x0f,0xf0,0xaa,0x11,0x94,0x66,0x16,0x10,0x58,0xad,
+ 0x77,0xa1,0xac,0x58,0xb4,0xd0,0x0d,0xbc,0x11,0xe0,0xc0,0xe9,0x29,0xdc,0x42,0x63,
+ 0x01,0x23,0x4f,0x28,0x41,0x6d,0x34,0x9e,0x0c,0x4a,0xc8,0x62,0x83,0xb5,0x71,0x71,
+ 0x0b,0x51,0xc0,0x4c,0x37,0xd4,0x68,0x19,0x52,0x9a,0x8b,0x02,0x03,0x01,0x00,0x01,
+ 0x02,0x81,0x81,0x00,0x82,0xca,0x33,0x16,0xb2,0x3a,0xd4,0x1b,0x62,0x9a,0x9c,0xc5,
+ 0x07,0x4f,0x57,0x89,0x2f,0x7c,0x4a,0xdf,0xb4,0x3b,0xc7,0xa4,0x11,0x14,0x2d,0xf4,
+ 0x4c,0xca,0xcc,0x03,0x88,0x06,0x82,0x34,0xab,0xe7,0xe4,0x24,0x15,0x33,0x1c,0xcb,
+ 0x0a,0xcf,0xc3,0x27,0x78,0x33,0x6b,0x6f,0x82,0x3e,0x3c,0x70,0xc9,0xe2,0xb9,0x7f,
+ 0x88,0xc3,0x4f,0x59,0xb5,0x8e,0xa3,0x81,0xd9,0x88,0x1f,0xc0,0x38,0xbc,0xc8,0x93,
+ 0x40,0x0f,0x43,0xd8,0x72,0x12,0xb4,0xcc,0x6d,0x76,0x0a,0x6f,0x01,0x05,0xa8,0x88,
+ 0xf4,0x57,0x44,0xd2,0x05,0xc4,0x77,0xf5,0xfb,0x1b,0xf3,0xb2,0x0d,0x90,0xb8,0xb4,
+ 0x63,0x62,0x70,0x2c,0xe4,0x28,0xd8,0x20,0x10,0x85,0x4a,0x5e,0x63,0xa9,0xb0,0xdd,
+ 0xba,0xd0,0x32,0x49,0x02,0x41,0x00,0xdb,0x77,0xf1,0xdd,0x1a,0x12,0xc5,0xfb,0x2b,
+ 0x5b,0xb2,0xcd,0xb6,0xd0,0x4c,0xc4,0xe5,0x93,0xd6,0xf8,0x88,0xfc,0x18,0x40,0x21,
+ 0x9c,0xf7,0x2d,0x60,0x6f,0x91,0xf5,0x73,0x3c,0xf7,0x7f,0x67,0x1d,0x5b,0xb5,0xee,
+ 0x29,0xc1,0xd4,0xc6,0xdb,0x44,0x4c,0x40,0x05,0x63,0xaa,0x71,0x95,0x18,0x14,0xa7,
+ 0x23,0x9f,0x7a,0xee,0x7f,0xb5,0xc7,0x02,0x41,0x00,0xcf,0x2c,0x24,0x50,0x65,0xf4,
+ 0x94,0x7b,0xe9,0xf3,0x13,0x77,0xea,0x27,0x3c,0x6f,0x03,0x84,0xa7,0x7d,0xa2,0x54,
+ 0x40,0x97,0x82,0x0e,0xd9,0x09,0x9f,0x4a,0xa6,0x75,0xe5,0x66,0xe4,0x9c,0x59,0xd9,
+ 0x3a,0xe6,0xf7,0xd8,0x8b,0x68,0xb0,0x21,0x52,0x31,0xb3,0x4a,0xa0,0x2c,0x41,0xd7,
+ 0x1f,0x7b,0xe2,0x0f,0x15,0xc9,0x6e,0xc0,0xe5,0x1d,0x02,0x41,0x00,0x9c,0x1a,0x61,
+ 0x9f,0x89,0xc7,0x26,0xa9,0x33,0xba,0xe2,0xa0,0x6d,0xd3,0x15,0x77,0xcb,0x6f,0xef,
+ 0xad,0x12,0x0a,0x75,0xd9,0x4f,0xcf,0x4d,0x05,0x2a,0x9d,0xd1,0x2c,0xcb,0xcd,0xe6,
+ 0xa0,0xe9,0x20,0x39,0xb6,0x5a,0xf3,0xba,0x99,0xf4,0xe3,0xcb,0x5d,0x8d,0x00,0x08,
+ 0x57,0x18,0xb9,0x1a,0xca,0xbd,0xe3,0x99,0xb1,0x1f,0xe9,0x18,0xcb,0x02,0x40,0x65,
+ 0x35,0x1b,0x48,0x6b,0x86,0x60,0x43,0x68,0xb6,0xe6,0xfb,0xdd,0xd7,0xed,0x1e,0x0e,
+ 0x89,0xef,0x88,0xe0,0x94,0x68,0x39,0x9b,0xbf,0xc5,0x27,0x7e,0x39,0xe9,0xb8,0x0e,
+ 0xa9,0x85,0x65,0x1c,0x3f,0x93,0x16,0xe2,0x5d,0x57,0x3d,0x7d,0x4d,0xc9,0xe9,0x9d,
+ 0xbd,0x07,0x22,0x97,0xc7,0x90,0x09,0xe5,0x15,0x99,0x7f,0x1e,0x2b,0xfd,0xc1,0x02,
+ 0x41,0x00,0x92,0x78,0xfe,0x04,0xa0,0x53,0xed,0x36,0x97,0xbd,0x16,0xce,0x91,0x9b,
+ 0xbe,0x1f,0x8e,0x40,0x00,0x99,0x0c,0x49,0x15,0xca,0x59,0xd3,0xe3,0xd4,0xeb,0x71,
+ 0xcf,0xda,0xd7,0xc8,0x99,0x74,0xfc,0x6b,0xe8,0xfd,0xe5,0xe0,0x49,0x61,0xcb,0xda,
+ 0xe3,0xe7,0x8b,0x72,0xb5,0x69,0x73,0x2b,0x8b,0x54,0xcb,0xd9,0x48,0x6d,0x61,0x02,
+ 0x49,0xe8,
+};
+
+/**
+ * Issue a certificate with a given serial number
+ */
+static certificate_t* create_cert(chunk_t serial)
+{
+ private_key_t *privkey;
+ public_key_t *pubkey;
+ certificate_t *cert;
+ identification_t *id;
+
+ privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
+ BUILD_END);
+ ck_assert(privkey);
+ pubkey = privkey->get_public_key(privkey);
+ ck_assert(pubkey);
+ id = identification_create_from_string("C=CH, O=strongSwan, CN=test");
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_SIGNING_KEY, privkey,
+ BUILD_PUBLIC_KEY, pubkey,
+ BUILD_SUBJECT, id,
+ BUILD_SERIAL, serial,
+ BUILD_END);
+ ck_assert(cert);
+ id->destroy(id);
+ privkey->destroy(privkey);
+ pubkey->destroy(pubkey);
+
+ return cert;
+}
+
+CALLBACK(filter, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ crl_revoked_t *revoked;
+ crl_reason_t *reason;
+ chunk_t *serial;
+ time_t *date;
+
+ VA_ARGS_VGET(args, serial, date, reason);
+
+ if (orig->enumerate(orig, &revoked))
+ {
+ *serial = revoked->serial;
+ *date = revoked->date;
+ *reason = revoked->reason;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Revoke a certificate with a given serial number
+ */
+static certificate_t* create_crl(chunk_t serial, certificate_t *cert)
+{
+ private_key_t *privkey;
+ certificate_t *crl;
+ linked_list_t *list;
+ enumerator_t *enumerator;
+ crl_revoked_t *revoked;
+ time_t date = time(NULL);
+
+ privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
+ BUILD_END);
+ ck_assert(privkey);
+
+ INIT(revoked,
+ .serial = serial,
+ .reason = CRL_REASON_KEY_COMPROMISE,
+ .date = date
+ );
+ list = linked_list_create();
+ list->insert_last(list, revoked);
+
+ enumerator = enumerator_create_filter(list->create_enumerator(list),
+ filter, NULL, NULL);
+ crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_SIGNING_KEY, privkey,
+ BUILD_NOT_BEFORE_TIME, date,
+ BUILD_NOT_AFTER_TIME, date + 30 * 24 * 3600,
+ BUILD_SIGNING_CERT, cert,
+ BUILD_REVOKED_ENUMERATOR, enumerator,
+ BUILD_SERIAL, serial,
+ BUILD_BASE_CRL, serial,
+ BUILD_END);
+ ck_assert(crl);
+ enumerator->destroy(enumerator);
+ list->destroy(list);
+ free(revoked);
+ privkey->destroy(privkey);
+
+ return crl;
+}
+
+/**
+ * Create an OCSP request for a given serial number
+ */
+static certificate_t* create_ocsp_request(certificate_t *cert)
+{
+ certificate_t *ocsp_req;
+
+ ocsp_req = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
+ BUILD_CA_CERT, cert,
+ BUILD_CERT, cert,
+ BUILD_END);
+
+ ck_assert(ocsp_req);
+
+ return ocsp_req;
+}
+
+/**
+ * Parse an ASN.1 encoded OCSP response
+ */
+static certificate_t* parse_ocsp_response(chunk_t encoding)
+{
+ certificate_t *ocsp_rsp;
+
+ ocsp_rsp = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ ck_assert(ocsp_rsp);
+
+ return ocsp_rsp;
+}
+
+/**
+ * Issue an attribute certificate with a given serial number
+ */
+static certificate_t* create_acert(chunk_t serial, certificate_t *cert)
+{
+ private_key_t *privkey;
+ public_key_t *pubkey;
+ certificate_t *acert;
+ linked_list_t *groups = linked_list_create();
+ time_t date = time(NULL);
+
+ privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
+ BUILD_END);
+ ck_assert(privkey);
+ pubkey = privkey->get_public_key(privkey);
+ ck_assert(pubkey);
+ groups->insert_last(groups, "research");
+ acert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_AC,
+ BUILD_NOT_BEFORE_TIME, date,
+ BUILD_NOT_AFTER_TIME, date + 30 * 24 * 3600,
+ BUILD_CERT, cert,
+ BUILD_SERIAL, serial,
+ BUILD_AC_GROUP_STRINGS, groups,
+ BUILD_SIGNING_CERT, cert,
+ BUILD_SIGNING_KEY, privkey,
+ BUILD_END);
+ ck_assert(acert);
+ groups->destroy(groups);
+ privkey->destroy(privkey);
+ pubkey->destroy(pubkey);
+
+ return acert;
+}
+
+/**
+ * Parse an ASN.1 encoded attribute certificate
+ */
+static certificate_t* parse_acert(chunk_t encoding)
+{
+ certificate_t *acert;
+
+ acert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ ck_assert(acert);
+
+ return acert;
+}
+
+typedef struct {
+ chunk_t serial;
+ chunk_t serial_asn1;
+} serial_number_t;
+
+static serial_number_t serial_numbers[] = {
+ { chunk_from_chars(0x00),
+ chunk_from_chars(0x01,0x00) },
+ { chunk_from_chars(0x01),
+ chunk_from_chars(0x01,0x01) },
+ { chunk_from_chars(0x7f),
+ chunk_from_chars(0x01,0x7f) },
+ { chunk_from_chars(0x80),
+ chunk_from_chars(0x02,0x00,0x80) },
+ { chunk_from_chars(0xff),
+ chunk_from_chars(0x02,0x00,0xff) },
+ { chunk_from_chars(0x01,0x00),
+ chunk_from_chars(0x02,0x01,0x00) },
+ { chunk_from_chars(0x7f,0xff),
+ chunk_from_chars(0x02,0x7f,0xff) },
+ { chunk_from_chars(0x80,0x00),
+ chunk_from_chars(0x03,0x00,0x80,0x00) },
+ { chunk_from_chars(0xff,0xff),
+ chunk_from_chars(0x03,0x00,0xff,0xff) },
+ { chunk_from_chars(0x01,0x00,0x00),
+ chunk_from_chars(0x03,0x01,0x00,0x00) },
+ { chunk_from_chars(0x7f,0xff,0xff),
+ chunk_from_chars(0x03,0x7f,0xff,0xff) },
+ { chunk_from_chars(0x80,0x00,0x00),
+ chunk_from_chars(0x04,0x00,0x80,0x00,0x00) },
+ { chunk_from_chars(0xff,0xff,0xff),
+ chunk_from_chars(0x04,0x00,0xff,0xff,0xff) },
+ { chunk_from_chars(0x01,0x00,0x00,0x00),
+ chunk_from_chars(0x04,0x01,0x00,0x00,0x00) },
+ { chunk_from_chars(0x7f,0xff,0xff,0xff),
+ chunk_from_chars(0x04,0x7f,0xff,0xff,0xff) },
+ { chunk_from_chars(0x80,0x00,0x00,0x00),
+ chunk_from_chars(0x05,0x00,0x80,0x00,0x00,0x00) },
+ { chunk_from_chars(0xff,0xff,0xff,0xff),
+ chunk_from_chars(0x05,0x00,0xff,0xff,0xff,0xff) },
+};
+
+static chunk_t ocsp_responses[] = {
+ chunk_from_chars(
+ 0x30,0x82,0x01,0x85,0x0a,0x01,0x00,0xa0,0x82,0x01,0x7e,0x30,0x82,0x01,0x7a,0x06,
+ 0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0x6b,0x30,0x82,
+ 0x01,0x67,0x30,0x81,0xd1,0xa1,0x33,0x30,0x31,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
+ 0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,
+ 0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0d,0x30,0x0b,0x06,
+ 0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x18,0x0f,0x32,0x30,0x32,0x32,
+ 0x31,0x31,0x32,0x32,0x30,0x39,0x31,0x36,0x34,0x37,0x5a,0x30,0x64,0x30,0x62,0x30,
+ 0x3a,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0xbd,0x25,
+ 0xa0,0xdf,0xc3,0x21,0xf2,0xd8,0xed,0x19,0x63,0x0a,0x4b,0x90,0x6d,0xc3,0x0f,0xe7,
+ 0x79,0x20,0x04,0x14,0xe2,0x6d,0x1e,0xdf,0x83,0x8e,0xa2,0x1f,0xc3,0x00,0xdd,0x44,
+ 0x6f,0x8a,0x4d,0x70,0x0c,0x02,0xe3,0x1f,0x02,0x01,0x7f,0x80,0x00,0x18,0x0f,0x32,
+ 0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x30,0x39,0x31,0x36,0x34,0x37,0x5a,0xa0,0x11,
+ 0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x31,0x39,0x31,0x36,0x34,0x37,
+ 0x5a,0xa1,0x23,0x30,0x21,0x30,0x1f,0x06,0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
+ 0x01,0x02,0x04,0x12,0x04,0x10,0x86,0x45,0x82,0x11,0xe6,0x62,0x43,0x83,0xbc,0x01,
+ 0xe4,0x5c,0x48,0x87,0xcd,0x2e,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
+ 0x01,0x01,0x0b,0x05,0x00,0x03,0x81,0x81,0x00,0x42,0x32,0xa9,0x24,0x97,0x8c,0xc5,
+ 0x35,0x37,0xe7,0x14,0xf0,0x84,0x7e,0x69,0xf1,0x99,0xf8,0xf0,0x02,0x7d,0xe4,0xd8,
+ 0x25,0x78,0x65,0x86,0x40,0xf6,0x30,0xc1,0x50,0x57,0x16,0x13,0xe9,0xe5,0xbc,0xa9,
+ 0xbb,0x87,0xce,0xb8,0x0d,0x35,0x5d,0xad,0x68,0x3b,0x34,0x9f,0x82,0x2b,0xe5,0x1f,
+ 0xcc,0xd5,0x54,0x8a,0xe3,0xd7,0xed,0xc9,0x7d,0xb6,0x50,0xd2,0xcb,0xc2,0xff,0x03,
+ 0x24,0x8c,0xcf,0x49,0x40,0xd4,0x7f,0xcb,0xc0,0x20,0x75,0x78,0x45,0xb8,0x50,0x3c,
+ 0x84,0xdd,0xdc,0xb7,0xfc,0xcd,0x64,0xc3,0x81,0xc6,0xb6,0xcd,0xc5,0xe9,0xc4,0x70,
+ 0x31,0x30,0x7c,0xff,0x93,0xc3,0x9d,0x55,0x7b,0x32,0x77,0x53,0x07,0x45,0xc2,0x80,
+ 0x7b,0x9b,0xfb,0x0e,0x45,0x27,0xf2,0xc5,0x16),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0x9c,0x0a,0x01,0x00,0xa0,0x82,0x01,0x95,0x30,0x82,0x01,0x91,0x06,
+ 0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0x82,0x30,0x82,
+ 0x01,0x7e,0x30,0x81,0xe8,0xa1,0x33,0x30,0x31,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
+ 0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,
+ 0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0d,0x30,0x0b,0x06,
+ 0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x18,0x0f,0x32,0x30,0x32,0x32,
+ 0x31,0x31,0x32,0x32,0x30,0x39,0x32,0x32,0x32,0x34,0x5a,0x30,0x7b,0x30,0x79,0x30,
+ 0x3b,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0xbd,0x25,
+ 0xa0,0xdf,0xc3,0x21,0xf2,0xd8,0xed,0x19,0x63,0x0a,0x4b,0x90,0x6d,0xc3,0x0f,0xe7,
+ 0x79,0x20,0x04,0x14,0xe2,0x6d,0x1e,0xdf,0x83,0x8e,0xa2,0x1f,0xc3,0x00,0xdd,0x44,
+ 0x6f,0x8a,0x4d,0x70,0x0c,0x02,0xe3,0x1f,0x02,0x02,0x00,0x80,0xa1,0x16,0x18,0x0f,
+ 0x32,0x30,0x32,0x32,0x31,0x31,0x31,0x35,0x31,0x38,0x34,0x30,0x35,0x34,0x5a,0xa0,
+ 0x03,0x0a,0x01,0x01,0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x30,0x39,
+ 0x32,0x32,0x32,0x34,0x5a,0xa0,0x11,0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,
+ 0x32,0x31,0x39,0x32,0x32,0x32,0x34,0x5a,0xa1,0x23,0x30,0x21,0x30,0x1f,0x06,0x09,
+ 0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02,0x04,0x12,0x04,0x10,0xf2,0x47,0xbd,
+ 0xd2,0xdd,0x6d,0x58,0xba,0xa4,0x6f,0xa5,0xed,0x31,0xb1,0x37,0x89,0x30,0x0d,0x06,
+ 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x81,0x81,0x00,
+ 0x17,0x96,0x3b,0x5a,0x4d,0x4e,0x90,0x8a,0xdf,0xe9,0x2b,0x1c,0x48,0x15,0x5d,0x8e,
+ 0xed,0xf0,0xa6,0x42,0x3a,0x9c,0x71,0xd9,0x6a,0xa6,0xc1,0xfd,0xef,0xe8,0x0a,0xa1,
+ 0x61,0x46,0xe4,0x04,0x5c,0x64,0xaf,0x47,0x95,0xdd,0x4c,0xba,0x8e,0x53,0xf6,0x9b,
+ 0xbc,0x16,0xcb,0xeb,0xfe,0x80,0x6a,0x70,0x54,0x10,0x59,0x40,0x5b,0xa0,0x2b,0xb3,
+ 0x62,0x27,0x9e,0x5d,0xd2,0xd6,0x15,0x2a,0x9d,0xa3,0xb1,0xcb,0x44,0x09,0xd8,0x29,
+ 0xb5,0x55,0xd9,0x63,0x86,0xd5,0xb3,0x3c,0x4b,0x78,0x14,0x5a,0x27,0x37,0x3a,0x28,
+ 0xd8,0xae,0x69,0x51,0x2e,0x7d,0xf1,0x06,0xc1,0xac,0x4e,0x5d,0x25,0x7a,0xd2,0xf4,
+ 0x41,0xfd,0x9f,0xbf,0x05,0xc1,0x70,0xa5,0x3f,0x7a,0x53,0x06,0x85,0x7b,0xeb,0x94)
+};
+
+START_TEST(test_gen_serial_numbers)
+{
+ chunk_t encoding, serial, serial_asn1;
+ certificate_t *cert, *crl, *ocsp_req, *acert, *acert1;
+ enumerator_t *enumerator;
+ crl_t *x509_crl;
+ x509_t *x509;
+ ac_t *ac;
+ size_t offset;
+ u_char *pos;
+
+ /**
+ * Use serial number with canonical encoding (no leading zeroes)
+ */
+
+ /* create X.509 certificate */
+ cert = create_cert(serial_numbers[_i].serial);
+
+ /* retrieve configured serial number */
+ x509 = (x509_t*)cert;
+ ck_assert_chunk_eq(x509->get_serial(x509), serial_numbers[_i].serial);
+
+ /* the ASN.1 TLV (Type-Length-Value) encoding of an X.509 certificate is
+ *
+ * 0 "x509", ASN1_SEQUENCE
+ * 1 "tbsCertificate", ASN1_SEQUENCE
+ * 2 "DEFAULT v1", ASN1_CONTEXT_C_0
+ * 3 "version", ASN1_INTEGER
+ * 4 "serialNumber", ASN1_INTEGER
+ * ...
+ *
+ * The one octet length field of the serialNumber (4) is at
+ * pos = 4 (TL0) + 4 (TL1) + 2 (TL2) + 3 (TLV3) + 1 (T4) = 14
+ */
+ ck_assert(cert->get_encoding(cert, CERT_ASN1_DER, &encoding));
+ DBG2(DBG_LIB, "cert: %B", &encoding);
+
+ /* check ASN.1 integer encoding of serial number */
+ pos = encoding.ptr + 14;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+ chunk_free(&encoding);
+
+ /* create X.509 crl */
+ crl = create_crl(serial_numbers[_i].serial, cert);
+
+ /* retrieve configured serial number */
+ x509_crl = (crl_t*)crl;
+ ck_assert_chunk_eq(x509_crl->get_serial(x509_crl), serial_numbers[_i].serial);
+
+ enumerator = x509_crl->create_enumerator(x509_crl);
+ ck_assert(enumerator->enumerate(enumerator, &serial, NULL, NULL));
+ ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
+ enumerator->destroy(enumerator);
+
+ /* retrieve configured base crl number */
+ ck_assert(x509_crl->is_delta_crl(x509_crl, &serial));
+ ck_assert_chunk_eq(x509_crl->get_serial(x509_crl), serial_numbers[_i].serial);
+
+ /* the ASN.1 TLV (Type-Length-Value) encoding of an X.509 crl is
+ *
+ * 0 "certificateList", ASN1_SEQUENCE
+ * 1 "tbsCertList", ASN1_SEQUENCE
+ * 2 "version", ASN1_INTEGER
+ * 3 "signature", ASN1_SEQUENCE
+ * 4 "issuer", ASN1_SEQUENCE
+ * 5 "thisUpdate" ASN1_UTCTIME
+ * 6 "nextUpdate" ASN1_UTCTIME
+ * 7 "revokedCertificates", ASN1_SEQUENCE
+ * 8 "certList", ASN1_SEQUENCE
+ * 9 "userCertificate", ASN1_INTEGER
+ * 10 "revocationDate", ASN1_UTCTIME
+ * 11 "crlEntryExtensions", ASN1_SEQUENCE
+ * 12 "optional extensions", ASN1_CONTEXT_C_0
+ * 13 "crlExtensions", ASN1_SEQUENCE
+ * 14 "extension", ASN1_SEQUENCE
+ * 15 "extnID", ASN1_OID
+ * 16 "critical", ASN1_BOOLEAN
+ * 17 "extnValue", ASN1_OCTET_STRING
+ * 18 "authorityKeyIdentifier", ASN1_SEQUENCE
+ * 19 "extension", ASN1_SEQUENCE
+ * 20 "extnID", ASN1_OID
+ * 21 "critical", ASN1_BOOLEAN
+ * 22 "extnValue", ASN1_OCTET_STRING
+ * 23 "crlNumber" ASN1_INTEGER
+ * 24 "extension", ASN1_SEQUENCE
+ * 25 "extnID", ASN1_OID
+ * 26 "critical", ASN1_BOOLEAN
+ * 27 "extnValue", ASN1_OCTET_STRING
+ * 28 "baseCrlNumber" ASN1_INTEGER
+ * ...
+ *
+ * The one octet length field of the revoked userCertificate (9) is at
+ * pos = 4 (TL0) + 3 (TL1) + 3 (TLV2) + 15 (TLV3) + 51 (TLV4) + 15 (TLV5) +
+ * 15 (TLV6) + 2 (TL7) + 2 (TL8) + 1 (T9) = 111
+ *
+ * The one octet length field of the crlNumber extension (19) is at
+ * offset = pos - 1 (T9) + *L8 + 2 (TL12) + 2 (TL13) + 33 (TLV14) + 1 (T19)
+ * = 110 + *L8 + 38
+ *
+ * The one octet length field of the crlNumber (23) is at
+ * pos = offset + 1 (L19) + 5 (TLV20) + 0 (TLV21) + 2 (TL22) + 1 (T23)
+ * = offset + 9
+ *
+ * The one octet length field of the baseCrlNumber (28) is at
+ * pos = offset + 1 (L19) + *L19 + 2 (TL24) + 5 (TLV25) + 3 (TLV26)
+ * + 2 (TL27) + 1 (T28)
+ * = offset + *L19 + 14
+ */
+ ck_assert(crl->get_encoding(crl, CERT_ASN1_DER, &encoding));
+ DBG2(DBG_LIB, "crl: %B", &encoding);
+
+ /* check ASN.1 integer encoding of revoked number */
+ pos = encoding.ptr + 111;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of crlNumber */
+ offset = 110 + encoding.ptr[109] + 38;
+ pos = encoding.ptr + offset + 9;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of baseCrlNumber */
+ pos = encoding.ptr + offset + encoding.ptr[offset] + 14;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+ chunk_free(&encoding);
+
+ /* create ocsp request */
+ ocsp_req = create_ocsp_request(cert);
+
+ /* the ASN.1 TLV (Type-Length-Value) encoding of an OCSP request is
+ *
+ * 0 "OCSPRequest", ASN1_SEQUENCE
+ * 1 "tbsRequest", ASN1_SEQUENCE
+ * 2 "requestList", ASN1_SEQUENCE
+ * 3 "request", ASN1_SEQUENCE
+ * 4 "reqCert", ASN1_SEQUENCE,
+ * 5 "hashAlgorithm", ASN1_SEQUENCE
+ * 6 "issuerNameHash", ASN1_OCTET STRING
+ * 7 "issuerKeyHash", ASN1_OCTET STRING
+ * 8 "serialNumber", ASN1_INTEGER
+ * ...
+ *
+ * The one octet length field of the serialNumber (8) is at
+ * pos = 3 (TL0) + 3 (TL1) + 2 (TL2) + 2 (TL3) + 2 (TL4) + 11 (TLV5) +
+ 22 (TLV6) + 22 (TLV7) + 1 (T8) = 68
+ */
+ ck_assert(ocsp_req->get_encoding(ocsp_req, CERT_ASN1_DER, &encoding));
+ DBG2(DBG_LIB, "ocsp request: %B", &encoding);
+
+ /* check ASN.1 integer encoding of requested serial number */
+ pos = encoding.ptr + 68;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+ chunk_free(&encoding);
+
+ /* test ocsp response */
+ if (_i == 2 || _i == 3)
+ {
+ certificate_t *ocsp_rsp;
+ ocsp_response_t *ocsp_resp;
+ cert_validation_t status;
+ crl_reason_t revocation_reason;
+ time_t revocation_time, this_update, next_update;
+ enumerator_t *enumerator;
+
+ ocsp_rsp = parse_ocsp_response(ocsp_responses[_i-2]);
+ ocsp_resp = (ocsp_response_t*)ocsp_rsp;
+
+ status = ocsp_resp->get_status(ocsp_resp, x509, x509, &revocation_time,
+ &revocation_reason, &this_update, &next_update);
+ if (_i == 2)
+ {
+ ck_assert(status == VALIDATION_GOOD);
+ }
+ else
+ {
+ ck_assert(status == VALIDATION_REVOKED);
+ ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
+ }
+
+ enumerator = ocsp_resp->create_response_enumerator(ocsp_resp);
+ ck_assert(enumerator->enumerate(enumerator, &serial, &status,
+ &revocation_time, &revocation_reason));
+ ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
+ if (_i == 2)
+ {
+ ck_assert(status == VALIDATION_GOOD);
+ }
+ else
+ {
+ ck_assert(status == VALIDATION_REVOKED);
+ ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
+ }
+ enumerator->destroy(enumerator);
+
+ ocsp_rsp->destroy(ocsp_rsp);
+ }
+
+ /* create attribute certificate */
+ acert = create_acert(serial_numbers[_i].serial, cert);
+
+ /* retrieve configured serial number */
+ ac = (ac_t*)acert;
+ ck_assert_chunk_eq(ac->get_serial(ac), serial_numbers[_i].serial);
+
+ /* retrieve configured holderSerial number */
+ ck_assert_chunk_eq(ac->get_holderSerial(ac), serial_numbers[_i].serial);
+
+ /* the ASN.1 TLV (Type-Length-Value) encoding of an attribute certificate is
+ *
+ * 0 "AttributeCertificate", ASN1_SEQUENCE
+ * 1 "AttributeCertificateInfo", ASN1_SEQUENCE
+ * 2 "version", ASN1_INTEGER
+ * 3 "holder", ASN1_SEQUENCE
+ * 4 "baseCertificateID", ASN1_CONTEXT_C_0
+ * 5 "issuer", ASN1_SEQUENCE
+ * 6 "serial", ASN1_INTEGER
+ * 7 "issuerUID", ASN1_BIT_STRING
+ * 8 "entityName", ASN1_CONTEXT_C_1
+ * 9 "objectDigestInfo", ASN1_CONTEXT_C_2
+ * 10 "v2Form", ASN1_CONTEXT_C_0
+ * 11 "signature", ASN1_SEQUENCE
+ * 12 "serialNumber" ASN1_INTEGER
+ * 13 "attrCertValidityPeriod", ASN1_SEQUENCE
+ * 14 "attributes", ASN1_SEQUENCE
+ * 15 "extensions", ASN1_SEQUENCE
+ * 16 "extension", ASN1_SEQUENCE
+ * 17 "extnID", ASN1_OID
+ * 18 "critical", ASN1_BOOLEAN
+ * 19 "extnValue", ASN1_OCTET_STRING
+ * 20 "authorityKeyIdentifier", ASN1_SEQUENCE
+ * 21 "keyIdentifier", ASN1_CONTEXT_S_0
+ * 22 "authorityCertIssuer", ASN1_CONTEXT_C_1
+ * 23 "authorityCertSerialNumber", ASN1_CONTEXT_S_2
+ * ...
+ *
+ * The one octet length field of the holder serial number (6) is at
+ * pos = 4 (TL0) + 4 (TL1) + 3 (TLV2) + 2 (TL3) + 2 (TL4) + 55 (TLV5) +
+ * 1 (T6) = 71
+ *
+ * The one octet length field of the serialNumber (12) is at
+ * offset = 4 (TL0) + 4 (TL1) + 3 (TLV2) + 2 (TL3) + *L3 + 57 (TLV10) +
+ * 15 (TLV11) + 1 (T12)
+ * = 13 + *L3 + 73
+ *
+ * The one octet length field of the authorityCertSerialNumber (23) is at
+ * pos = offset + *L12 + 1 (L12) + 36 (TLV13) + 30 (TLV14) + 2 (TL15)
+ * + 2 (TL16) + 5 (TLV17) + 0 (TLV18) + 2 (TL19) + 2 (TL20)
+ * + 22 (TLV21) + 55 (TLV22) + 1 (T23)
+ * pos = offset + *L12 + 158
+ */
+ ck_assert(acert->get_encoding(acert, CERT_ASN1_DER, &encoding));
+ DBG2(DBG_LIB, "acert: %B", &encoding);
+
+ /* check ASN.1 integer encoding of holder serial number */
+ pos = encoding.ptr + 71;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of the AC serialNumber */
+ offset = 13 + encoding.ptr[12] + 73;
+ pos = encoding.ptr + offset;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of serial number */
+ pos = encoding.ptr + offset + encoding.ptr[offset] + 158;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* parse ASN.1 encoded attribute certificate */
+ acert1 = parse_acert(encoding);
+ ac = (ac_t*)acert1;
+
+ /* check serial number */
+ ck_assert_chunk_eq(ac->get_serial(ac), serial_numbers[_i].serial);
+
+ /* check holderSerial number */
+ ck_assert_chunk_eq(ac->get_holderSerial(ac), serial_numbers[_i].serial);
+ chunk_free(&encoding);
+
+ cert->destroy(cert);
+ crl->destroy(crl);
+ ocsp_req->destroy(ocsp_req);
+ acert->destroy(acert);
+ acert1->destroy(acert1);
+
+ /**
+ * Use serial number with two's complement encoding
+ */
+
+ serial = chunk_skip(serial_numbers[_i].serial_asn1, 1);
+
+ /* create certificate */
+ cert = create_cert(serial);
+
+ /* retrieve configured serial number */
+ x509 = (x509_t*)cert;
+ ck_assert_chunk_eq(x509->get_serial(x509), serial_numbers[_i].serial);
+
+ /* check ASN.1 integer encoding */
+ ck_assert(cert->get_encoding(cert, CERT_ASN1_DER, &encoding));
+ pos = encoding.ptr + 14;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+ chunk_free(&encoding);
+
+ /* create crl */
+ crl = create_crl(serial, cert);
+
+ /* retrieve configured serial number */
+ x509_crl = (crl_t*)crl;
+ ck_assert_chunk_eq(x509_crl->get_serial(x509_crl), serial_numbers[_i].serial);
+
+ enumerator = x509_crl->create_enumerator(x509_crl);
+ if (enumerator->enumerate(enumerator, &serial, NULL, NULL))
+ {
+ ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
+ }
+ enumerator->destroy(enumerator);
+
+ /* check ASN.1 integer encoding of revoked number */
+ ck_assert(crl->get_encoding(crl, CERT_ASN1_DER, &encoding));
+ pos = encoding.ptr + 111;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of crlNumber */
+ offset = 110 + encoding.ptr[109] + 38;
+ pos = encoding.ptr + offset + 9;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+
+ /* check ASN.1 integer encoding of baseCrlNumber */
+ pos = encoding.ptr + offset + encoding.ptr[offset] + 14;
+ serial_asn1 = chunk_create(pos, 1 + *pos);
+ ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
+ chunk_free(&encoding);
+
+ cert->destroy(cert);
+ crl->destroy(crl);
+}
+END_TEST
+
+Suite *serial_gen_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("serial_gen");
+
+ tc = tcase_create("generate serial numbers");
+ tcase_add_loop_test(tc, test_gen_serial_numbers, 0, countof(serial_numbers));
+ suite_add_tcase(s, tc);
+
+ return s;
+}
--- /dev/null
+/*
+ * Copyright (C) 2022 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/crl.h>
+
+static certificate_t* parse_cert(chunk_t encoding)
+{
+ certificate_t *cert;
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ ck_assert(cert);
+
+ return cert;
+}
+
+static certificate_t* parse_crl(chunk_t encoding)
+{
+ certificate_t *crl;
+
+ crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ ck_assert(crl);
+
+ return crl;
+}
+
+typedef struct {
+ chunk_t serial;
+ chunk_t cert_encoding;
+ chunk_t crl_encoding;
+} serial_number_t;
+
+static serial_number_t serial_numbers[] = {
+ { chunk_from_chars(0x00),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0xD6,0x30,0x82,0x01,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x00,
+ 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,
+ 0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,
+ 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,0x53,
+ 0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,
+ 0x73,0x74,0x30,0x1E,0x17,0x0D,0x32,0x32,0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,
+ 0x34,0x34,0x5A,0x17,0x0D,0x32,0x33,0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,
+ 0x34,0x5A,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,
+ 0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,
+ 0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,
+ 0x04,0x74,0x65,0x73,0x74,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,0x81,
+ 0x81,0x00,0xB1,0x9B,0xD4,0x51,0x24,0xFC,0x56,0x1D,0x3D,0xFB,0xA2,0xEA,0x37,0x02,
+ 0x70,0x72,0x87,0x84,0x2F,0x3B,0x2D,0x6E,0x22,0xEF,0x3F,0x37,0x04,0xB2,0x6F,0xB7,
+ 0xE7,0xD8,0x58,0x05,0xDE,0x34,0xBF,0x99,0xE6,0x40,0x7A,0x56,0xA7,0x73,0xF5,0x98,
+ 0xCB,0xB0,0x37,0x90,0x5E,0xD1,0x3F,0xF4,0x73,0x50,0x7F,0x53,0x8E,0xF1,0x04,0x25,
+ 0xB4,0x77,0x22,0x4E,0x8A,0x9D,0x27,0x8F,0x6F,0xAF,0x59,0xBD,0xB0,0x0F,0xF0,0xAA,
+ 0x11,0x94,0x66,0x16,0x10,0x58,0xAD,0x77,0xA1,0xAC,0x58,0xB4,0xD0,0x0D,0xBC,0x11,
+ 0xE0,0xC0,0xE9,0x29,0xDC,0x42,0x63,0x01,0x23,0x4F,0x28,0x41,0x6D,0x34,0x9E,0x0C,
+ 0x4A,0xC8,0x62,0x83,0xB5,0x71,0x71,0x0B,0x51,0xC0,0x4C,0x37,0xD4,0x68,0x19,0x52,
+ 0x9A,0x8B,0x02,0x03,0x01,0x00,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,
+ 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x81,0x81,0x00,0x0D,0x3E,0x13,0x3D,0x58,0x72,
+ 0x90,0x21,0x06,0x29,0xBD,0xA5,0x06,0x87,0x67,0x80,0x2C,0xE0,0x61,0xF5,0x66,0x76,
+ 0x63,0xAB,0x97,0xD5,0x45,0x9B,0x2B,0x3C,0x6B,0xA7,0xB0,0xB4,0x31,0x52,0xC6,0xD9,
+ 0x72,0xFC,0xC5,0x37,0xE5,0xFF,0xD0,0x80,0x63,0x09,0xD2,0x1E,0xC1,0x77,0x92,0xCC,
+ 0x07,0x08,0x5D,0xD0,0x30,0x67,0x9A,0x6B,0x82,0x19,0x89,0x0E,0x10,0xC7,0xA4,0xA7,
+ 0x7C,0x96,0x76,0x8C,0x72,0xDB,0x73,0x13,0x49,0xE5,0x8B,0xAC,0x0B,0x1E,0xEB,0x31,
+ 0x74,0xEB,0xE4,0xA0,0x5D,0x49,0x9A,0x76,0x3C,0xA5,0xEF,0x55,0xE2,0x32,0x25,0x1A,
+ 0xE3,0x05,0x37,0xAC,0xFF,0x9F,0x94,0x92,0xE6,0x0E,0x53,0xC0,0xFC,0x52,0xB8,0xD0,
+ 0xFA,0x66,0x0B,0xCE,0xCA,0x88,0x66,0x3B,0x83,0x48),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0x5D,0x30,0x81,0xC7,0x02,0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,
+ 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,
+ 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
+ 0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,
+ 0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x17,0x0D,0x32,0x32,
+ 0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x17,0x0D,0x32,0x32,0x31,
+ 0x32,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x30,0x22,0x30,0x20,0x02,0x01,
+ 0x00,0x17,0x0D,0x32,0x32,0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,
+ 0x30,0x0C,0x30,0x0A,0x06,0x03,0x55,0x1D,0x15,0x04,0x03,0x0A,0x01,0x01,0xA0,0x3E,
+ 0x30,0x3C,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE2,
+ 0x6D,0x1E,0xDF,0x83,0x8E,0xA2,0x1F,0xC3,0x00,0xDD,0x44,0x6F,0x8A,0x4D,0x70,0x0C,
+ 0x02,0xE3,0x1F,0x30,0x0A,0x06,0x03,0x55,0x1D,0x14,0x04,0x03,0x02,0x01,0x00,0x30,
+ 0x0D,0x06,0x03,0x55,0x1D,0x1B,0x01,0x01,0xFF,0x04,0x03,0x02,0x01,0x00,0x30,0x0D,
+ 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x81,0x81,
+ 0x00,0x35,0x72,0x26,0x38,0x87,0x21,0xA2,0x5C,0xED,0x5C,0x04,0xD9,0x49,0xC0,0xB6,
+ 0x75,0x7C,0x5A,0xEA,0x46,0x6E,0x1E,0xED,0x3C,0x9B,0x41,0x31,0x37,0x3F,0xAA,0xE7,
+ 0x16,0x39,0x17,0x48,0x5F,0x84,0x48,0x6F,0xA4,0xF6,0x9D,0x79,0xDE,0xC3,0xE9,0x82,
+ 0x87,0xEE,0xD4,0xD0,0x2F,0xBF,0x8B,0x74,0x1E,0xA7,0x21,0x63,0xB6,0x5A,0x39,0xFF,
+ 0xDE,0xD0,0x6E,0xE3,0xB5,0x3B,0x0C,0x42,0x46,0x97,0x43,0x2E,0x6B,0x4D,0xF8,0x54,
+ 0x59,0x8F,0xD8,0x72,0xB3,0xB0,0x29,0xCB,0x56,0xA7,0x8A,0x01,0xD6,0xEA,0xE0,0x69,
+ 0xF7,0x36,0xC4,0x06,0xE6,0x05,0xC0,0x10,0xD2,0xB7,0x43,0x46,0xCC,0x8A,0x53,0xA1,
+ 0xA6,0xD3,0x88,0x73,0x53,0x29,0x10,0xC2,0xC6,0xCE,0x24,0xC3,0xCE,0x14,0xED,0xB0,
+ 0x64)
+ },
+ { chunk_from_chars(0x7f),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0xD6,0x30,0x82,0x01,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x7F,
+ 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,
+ 0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,
+ 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,0x53,
+ 0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,
+ 0x73,0x74,0x30,0x1E,0x17,0x0D,0x32,0x32,0x31,0x31,0x31,0x38,0x31,0x33,0x30,0x37,
+ 0x32,0x31,0x5A,0x17,0x0D,0x32,0x33,0x31,0x31,0x31,0x38,0x31,0x33,0x30,0x37,0x32,
+ 0x31,0x5A,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,
+ 0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,
+ 0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,
+ 0x04,0x74,0x65,0x73,0x74,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,0x81,
+ 0x81,0x00,0xB1,0x9B,0xD4,0x51,0x24,0xFC,0x56,0x1D,0x3D,0xFB,0xA2,0xEA,0x37,0x02,
+ 0x70,0x72,0x87,0x84,0x2F,0x3B,0x2D,0x6E,0x22,0xEF,0x3F,0x37,0x04,0xB2,0x6F,0xB7,
+ 0xE7,0xD8,0x58,0x05,0xDE,0x34,0xBF,0x99,0xE6,0x40,0x7A,0x56,0xA7,0x73,0xF5,0x98,
+ 0xCB,0xB0,0x37,0x90,0x5E,0xD1,0x3F,0xF4,0x73,0x50,0x7F,0x53,0x8E,0xF1,0x04,0x25,
+ 0xB4,0x77,0x22,0x4E,0x8A,0x9D,0x27,0x8F,0x6F,0xAF,0x59,0xBD,0xB0,0x0F,0xF0,0xAA,
+ 0x11,0x94,0x66,0x16,0x10,0x58,0xAD,0x77,0xA1,0xAC,0x58,0xB4,0xD0,0x0D,0xBC,0x11,
+ 0xE0,0xC0,0xE9,0x29,0xDC,0x42,0x63,0x01,0x23,0x4F,0x28,0x41,0x6D,0x34,0x9E,0x0C,
+ 0x4A,0xC8,0x62,0x83,0xB5,0x71,0x71,0x0B,0x51,0xC0,0x4C,0x37,0xD4,0x68,0x19,0x52,
+ 0x9A,0x8B,0x02,0x03,0x01,0x00,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,
+ 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x81,0x81,0x00,0xA4,0x92,0x32,0x35,0xD2,0xC7,
+ 0x67,0x12,0x1E,0x5E,0x7C,0x0C,0x08,0x92,0x95,0xEE,0xD4,0x43,0x59,0xEF,0x0C,0x0A,
+ 0x73,0x2C,0xB4,0x6C,0xB6,0x4A,0x98,0x85,0xD5,0xA2,0x96,0x6B,0x90,0xBA,0xB7,0xC2,
+ 0x67,0x5F,0x0D,0xCD,0x9E,0xB3,0x5B,0xDE,0xA0,0xF4,0x5C,0x49,0x80,0x66,0x7B,0x33,
+ 0x08,0x7F,0xCB,0x65,0xE6,0xCB,0x4F,0x50,0x59,0x16,0x23,0xEA,0xB6,0x70,0xFD,0x98,
+ 0xD3,0x65,0x2A,0x94,0x65,0x2E,0x77,0x93,0x48,0x99,0x12,0xC3,0x95,0xDE,0x56,0xA8,
+ 0xFE,0x33,0x1E,0x36,0x62,0x29,0x0A,0x5A,0x07,0xF9,0x19,0xF6,0x04,0x86,0xB5,0x43,
+ 0x2C,0x49,0x4B,0xC2,0x98,0x3F,0x96,0x95,0x61,0x96,0xF8,0x22,0x4C,0xFB,0x45,0x41,
+ 0x27,0x06,0x0E,0x44,0x36,0x19,0x7F,0x51,0x96,0x20),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0x5D,0x30,0x81,0xC7,0x02,0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,
+ 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,
+ 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
+ 0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,
+ 0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x17,0x0D,0x32,0x32,
+ 0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x17,0x0D,0x32,0x32,0x31,
+ 0x32,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x30,0x22,0x30,0x20,0x02,0x01,
+ 0x7F,0x17,0x0D,0x32,0x32,0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,
+ 0x30,0x0C,0x30,0x0A,0x06,0x03,0x55,0x1D,0x15,0x04,0x03,0x0A,0x01,0x01,0xA0,0x3E,
+ 0x30,0x3C,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE2,
+ 0x6D,0x1E,0xDF,0x83,0x8E,0xA2,0x1F,0xC3,0x00,0xDD,0x44,0x6F,0x8A,0x4D,0x70,0x0C,
+ 0x02,0xE3,0x1F,0x30,0x0A,0x06,0x03,0x55,0x1D,0x14,0x04,0x03,0x02,0x01,0x7F,0x30,
+ 0x0D,0x06,0x03,0x55,0x1D,0x1B,0x01,0x01,0xFF,0x04,0x03,0x02,0x01,0x7F,0x30,0x0D,
+ 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x81,0x81,
+ 0x00,0x00,0x93,0xAD,0x02,0x09,0x74,0x97,0x3C,0xBE,0x82,0x3D,0x39,0xCC,0xD0,0x55,
+ 0x8F,0xBA,0xE4,0xB5,0x53,0x83,0xF0,0x11,0x29,0xE8,0x2B,0x77,0x8D,0xC5,0xA2,0x0F,
+ 0x86,0x31,0x87,0x4D,0xAA,0x4B,0x78,0x44,0xFB,0x42,0xDB,0x81,0xC7,0xF0,0xA6,0x65,
+ 0x68,0x36,0xC9,0x2D,0x37,0xA7,0x1C,0x23,0xD3,0xA4,0x75,0x85,0x0B,0x09,0xF1,0x1E,
+ 0x24,0x19,0xB7,0xEE,0x5A,0x89,0x1C,0xF9,0x98,0xE7,0x6F,0xB8,0xF2,0x9A,0xB2,0x5E,
+ 0xC5,0x47,0xE3,0x6D,0x50,0x9D,0x13,0x61,0x85,0x71,0x0A,0xF2,0xF3,0xBC,0x03,0xE6,
+ 0xB8,0x1F,0x32,0x92,0x4C,0x95,0x31,0xF0,0xF4,0x85,0x41,0x97,0x1F,0x43,0xC7,0x51,
+ 0xD9,0x90,0xBE,0xA6,0xE5,0x06,0x92,0xEF,0xF6,0x81,0xC7,0xD4,0xB3,0xF7,0x1B,0xA3,
+ 0x1C),
+ },
+ { chunk_from_chars(0x80),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0xD7,0x30,0x82,0x01,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x02,0x00,
+ 0x80,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,
+ 0x30,0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,
+ 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,
+ 0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,
+ 0x65,0x73,0x74,0x30,0x1E,0x17,0x0D,0x32,0x32,0x31,0x31,0x31,0x38,0x31,0x33,0x30,
+ 0x37,0x32,0x31,0x5A,0x17,0x0D,0x32,0x33,0x31,0x31,0x31,0x38,0x31,0x33,0x30,0x37,
+ 0x32,0x31,0x5A,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
+ 0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x73,0x74,0x72,
+ 0x6F,0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,
+ 0x13,0x04,0x74,0x65,0x73,0x74,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,
+ 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,
+ 0x81,0x81,0x00,0xB1,0x9B,0xD4,0x51,0x24,0xFC,0x56,0x1D,0x3D,0xFB,0xA2,0xEA,0x37,
+ 0x02,0x70,0x72,0x87,0x84,0x2F,0x3B,0x2D,0x6E,0x22,0xEF,0x3F,0x37,0x04,0xB2,0x6F,
+ 0xB7,0xE7,0xD8,0x58,0x05,0xDE,0x34,0xBF,0x99,0xE6,0x40,0x7A,0x56,0xA7,0x73,0xF5,
+ 0x98,0xCB,0xB0,0x37,0x90,0x5E,0xD1,0x3F,0xF4,0x73,0x50,0x7F,0x53,0x8E,0xF1,0x04,
+ 0x25,0xB4,0x77,0x22,0x4E,0x8A,0x9D,0x27,0x8F,0x6F,0xAF,0x59,0xBD,0xB0,0x0F,0xF0,
+ 0xAA,0x11,0x94,0x66,0x16,0x10,0x58,0xAD,0x77,0xA1,0xAC,0x58,0xB4,0xD0,0x0D,0xBC,
+ 0x11,0xE0,0xC0,0xE9,0x29,0xDC,0x42,0x63,0x01,0x23,0x4F,0x28,0x41,0x6D,0x34,0x9E,
+ 0x0C,0x4A,0xC8,0x62,0x83,0xB5,0x71,0x71,0x0B,0x51,0xC0,0x4C,0x37,0xD4,0x68,0x19,
+ 0x52,0x9A,0x8B,0x02,0x03,0x01,0x00,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x81,0x81,0x00,0x54,0xC6,0x85,0x31,0x85,
+ 0x17,0x86,0xCB,0xFF,0x63,0x09,0x2A,0x90,0xDD,0x2C,0xC8,0x7E,0xD7,0x8B,0xE0,0x37,
+ 0xF7,0x2D,0xE2,0xCF,0x7E,0x57,0x26,0x4C,0x1D,0x3D,0x57,0xF0,0x6D,0x0D,0x18,0xA3,
+ 0xAB,0x49,0xD3,0x4E,0x08,0x70,0x4D,0xAE,0x05,0xF7,0xC5,0x47,0x99,0x89,0xFA,0xCA,
+ 0x15,0x36,0x3F,0xDA,0xA7,0x64,0xEE,0xE6,0x1C,0x6E,0x6E,0x9D,0x39,0x61,0xCB,0x5E,
+ 0x8F,0xAD,0x5C,0x90,0xD6,0xAE,0xCD,0xE9,0xBB,0x62,0xB9,0xCB,0x0E,0x51,0xDD,0x27,
+ 0xAF,0xF3,0xE2,0xD0,0xAC,0x9E,0x99,0x55,0xB5,0x2F,0x46,0x99,0xDB,0x2F,0xEC,0x23,
+ 0x76,0x0E,0x82,0xE3,0xA7,0xC3,0xF6,0xA2,0x61,0x32,0xC7,0x1F,0xD6,0x22,0x9B,0xFA,
+ 0xD8,0xFD,0x8F,0xB2,0xB7,0x6B,0x71,0xF0,0x92,0x1F,0x44),
+ chunk_from_chars(
+ 0x30,0x82,0x01,0x60,0x30,0x81,0xCA,0x02,0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,
+ 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,
+ 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
+ 0x0A,0x13,0x0A,0x73,0x74,0x72,0x6F,0x6E,0x67,0x53,0x77,0x61,0x6E,0x31,0x0D,0x30,
+ 0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x17,0x0D,0x32,0x32,
+ 0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x17,0x0D,0x32,0x32,0x31,
+ 0x32,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,0x5A,0x30,0x23,0x30,0x21,0x02,0x02,
+ 0x00,0x80,0x17,0x0D,0x32,0x32,0x31,0x31,0x32,0x30,0x31,0x30,0x31,0x37,0x34,0x34,
+ 0x5A,0x30,0x0C,0x30,0x0A,0x06,0x03,0x55,0x1D,0x15,0x04,0x03,0x0A,0x01,0x01,0xA0,
+ 0x40,0x30,0x3E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
+ 0xE2,0x6D,0x1E,0xDF,0x83,0x8E,0xA2,0x1F,0xC3,0x00,0xDD,0x44,0x6F,0x8A,0x4D,0x70,
+ 0x0C,0x02,0xE3,0x1F,0x30,0x0B,0x06,0x03,0x55,0x1D,0x14,0x04,0x04,0x02,0x02,0x00,
+ 0x80,0x30,0x0E,0x06,0x03,0x55,0x1D,0x1B,0x01,0x01,0xFF,0x04,0x04,0x02,0x02,0x00,
+ 0x80,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,
+ 0x03,0x81,0x81,0x00,0x7D,0x98,0x63,0x80,0x7B,0x43,0xE6,0x56,0xCD,0x59,0x0E,0xEC,
+ 0xD7,0x45,0x93,0xE5,0xD1,0x97,0x3E,0x47,0x87,0xFD,0x6F,0x8D,0x10,0xB0,0xDA,0x7C,
+ 0x5D,0xDC,0x0B,0x1B,0xC8,0x63,0x5D,0x8D,0x02,0xDE,0xD0,0xC7,0xBB,0xE4,0x50,0xEA,
+ 0xA7,0x2E,0x06,0xBC,0xF2,0x36,0x8D,0x7A,0xA2,0xE5,0x67,0x0F,0x03,0x9A,0x75,0x1D,
+ 0x18,0x0E,0x57,0x39,0x86,0xF3,0xEF,0x29,0xED,0xDE,0x24,0x50,0x9E,0x1F,0xC7,0x90,
+ 0x51,0x95,0xA0,0xD5,0x11,0x5E,0x96,0x0A,0xA5,0x4A,0x4D,0xFE,0x97,0xE4,0x1A,0xEA,
+ 0xC3,0x56,0x2A,0x21,0xA6,0x6E,0xE5,0xBA,0xAC,0x70,0xA5,0xE5,0x90,0x9A,0x3C,0x36,
+ 0xFF,0xD6,0x8B,0xC2,0x09,0x19,0xF4,0x21,0x68,0x50,0xEC,0x83,0xF8,0xF6,0xB5,0x24,
+ 0x8F,0x2B,0x77,0xB2)
+ }
+};
+
+START_TEST(test_parse_serial_numbers)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert, *crl;
+ crl_t *x509_crl;
+ x509_t *x509;
+ chunk_t serial;
+
+ /* parse ASN.1 DER encoded certificate */
+ cert = parse_cert(serial_numbers[_i].cert_encoding);
+
+ /* check parsed serial number */
+ x509 = (x509_t*)cert;
+ ck_assert_chunk_eq(x509->get_serial(x509), serial_numbers[_i].serial);
+ cert->destroy(cert);
+
+ /* parse ASN.1 DER encoded crl */
+ crl = parse_crl(serial_numbers[_i].crl_encoding);
+
+ /* check parsed serial number */
+ x509_crl = (crl_t*)crl;
+ ck_assert_chunk_eq(x509_crl->get_serial(x509_crl), serial_numbers[_i].serial);
+
+ enumerator = x509_crl->create_enumerator(x509_crl);
+ if (enumerator->enumerate(enumerator, &serial, NULL, NULL))
+ {
+ ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
+ }
+ enumerator->destroy(enumerator);
+
+ crl->destroy(crl);
+}
+END_TEST
+
+Suite *serial_parse_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("serial_parse");
+
+ tc = tcase_create("parse serial numbers");
+ tcase_add_loop_test(tc, test_parse_serial_numbers, 0, countof(serial_numbers));
+ suite_add_tcase(s, tc);
+
+ return s;
+}