]> git.saurik.com Git - apple/security.git/blobdiff - sec/Security/SecCertificateRequest.c
Security-57031.1.35.tar.gz
[apple/security.git] / sec / Security / SecCertificateRequest.c
diff --git a/sec/Security/SecCertificateRequest.c b/sec/Security/SecCertificateRequest.c
deleted file mode 100644 (file)
index 7f748f4..0000000
+++ /dev/null
@@ -1,1171 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- */
-
-#include <libDER/oids.h>
-#include <libDER/DER_Encode.h>
-
-#include <security_asn1/SecAsn1Types.h>
-#include <security_asn1/csrTemplates.h>
-#include <security_asn1/certExtensionTemplates.h>
-#include <security_asn1/secasn1.h>
-#include <security_asn1/SecAsn1Types.h>
-#include <security_asn1/oidsalg.h>
-#include <security_asn1/nameTemplates.h>
-
-#include <TargetConditionals.h>
-#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
-// ENABLE_CMS 0
-OSStatus SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **objs2);
-#else
-// ENABLE_CMS 1
-#include <security_smime/cmspriv.h>
-#endif
-
-#include <Security/SecInternal.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecIdentity.h>
-#include <Security/SecCertificateInternal.h>
-#include <Security/SecItem.h>
-#include <Security/SecKey.h>
-#include <Security/SecRSAKey.h>
-#include <Security/SecKeyPriv.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <CommonCrypto/CommonDigestSPI.h>
-#include <CoreFoundation/CFNumber.h>
-#include <CoreFoundation/CFString.h>
-
-#include <AssertMacros.h>
-
-#include "SecCertificateRequest.h"
-
-CFTypeRef kSecOidCommonName = CFSTR("CN");
-CFTypeRef kSecOidCountryName = CFSTR("C");
-CFTypeRef kSecOidStateProvinceName = CFSTR("ST");
-CFTypeRef kSecOidLocalityName = CFSTR("L");
-CFTypeRef kSecOidOrganization = CFSTR("O");
-CFTypeRef kSecOidOrganizationalUnit = CFSTR("OU");
-//CFTypeRef kSecOidEmailAddress = CFSTR("1.2.840.113549.1.9.1");
-// keep natural order: C > ST > L > O > OU > CN > Email
-
-const unsigned char SecASN1PrintableString = SEC_ASN1_PRINTABLE_STRING;
-const unsigned char SecASN1UTF8String = SEC_ASN1_UTF8_STRING;
-
-static uint8_t * mod128_oid_encoding_ptr(uint8_t *ptr, uint32_t src, bool final)
-{
-    if (src > 128)
-        ptr = mod128_oid_encoding_ptr(ptr, src / 128, false);
-    
-    unsigned char octet = src % 128;
-    if (!final)
-        octet |= 128;
-    *ptr++ = octet;
-
-    return ptr;
-}
-
-static uint8_t * oid_der_data(PRArenaPool *poolp, CFStringRef oid_string, size_t *oid_data_len)
-{
-    /* estimate encoded length from base 10 (4 bits) to base 128 (7 bits) */
-    size_t tmp_oid_length = ((CFStringGetLength(oid_string) * 4) / 7) + 1;
-    uint8_t *tmp_oid_data = PORT_ArenaAlloc(poolp, tmp_oid_length);
-    uint8_t *tmp_oid_data_ptr = tmp_oid_data;
-
-    CFArrayRef oid = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault,
-                                                            oid_string, CFSTR("."));
-    CFIndex i = 0, count = CFArrayGetCount(oid);
-    SInt32 first_digit = 0, digit;
-    for (i = 0; i < count; i++) {
-        CFStringRef oid_octet = CFArrayGetValueAtIndex(oid, i);
-        SInt32 oid_octet_int_value = CFStringGetIntValue(oid_octet);
-        require(abs(oid_octet_int_value) != INT32_MAX, out);
-        if (i == 0)
-            first_digit = oid_octet_int_value;
-        else {
-            if (i == 1)
-                digit = 40 * first_digit + oid_octet_int_value;
-            else
-                digit = oid_octet_int_value;
-            tmp_oid_data_ptr = mod128_oid_encoding_ptr(tmp_oid_data_ptr, digit, true);
-        }
-    }
-    CFReleaseSafe(oid);
-
-    *oid_data_len = tmp_oid_data_ptr - tmp_oid_data;
-    return tmp_oid_data;
-out:
-    return NULL;
-}
-
-
-/*
-Get challenge password conversion and apply this:
-
-ASCII ? => PrintableString subset: [A-Za-z0-9 '()+,-./:=?] ?
-
-PrintableString > IA5String > UTF8String
-
-Consider using IA5String for email address
-*/
-
-static inline bool printable_string(CFStringRef string)
-{
-    bool result = true;
-    
-    CFCharacterSetRef printable_charset = 
-        CFCharacterSetCreateWithCharactersInString(kCFAllocatorDefault,
-            CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                    "abcdefghijklmnopqrstuvwxyz"
-                    "0123456789 '()+,-./:=?"));
-    CFCharacterSetRef not_printable_charset = 
-        CFCharacterSetCreateInvertedSet(kCFAllocatorDefault, printable_charset);
-    CFRange found;
-    if (CFStringFindCharacterFromSet(string, not_printable_charset, 
-        CFRangeMake(0, CFStringGetLength(string)), 0, &found))
-            result = false;
-
-    CFReleaseSafe(printable_charset);
-    CFReleaseSafe(not_printable_charset);
-
-    return result;
-}
-
-static bool make_nss_atv(PRArenaPool *poolp, 
-    const void * oid, const void * value, const unsigned char type_in, NSS_ATV *nss_atv)
-{
-    size_t length = 0;
-    char *buffer = NULL;
-    unsigned char type = type_in;
-    if (CFGetTypeID(value) == CFStringGetTypeID()) {
-        length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
-            kCFStringEncodingUTF8);
-        buffer = PORT_ArenaAlloc(poolp, length);
-        /* TODO: Switch to using CFStringGetBytes,since this code will do the wrong thing for embedded 0's */
-        if (!CFStringGetCString(value, buffer, length, kCFStringEncodingASCII)) {
-            if (!CFStringGetCString(value, buffer, length, kCFStringEncodingUTF8))
-                return false;
-            if (type && type != SecASN1UTF8String)
-                return false;
-            type = SecASN1UTF8String;
-        }
-        else {
-            if (!type || type == SecASN1PrintableString) {
-                if (!printable_string(value))
-                    type = SEC_ASN1_IA5_STRING;
-                else
-                    type = SEC_ASN1_PRINTABLE_STRING;
-            }
-        }
-        length = strlen(buffer);
-    }
-    else if (CFGetTypeID(value) == CFDataGetTypeID()) {
-        /* will remain valid for the duration of the operation, still maybe copy into pool */
-        length = CFDataGetLength(value);
-        buffer = (char *)CFDataGetBytePtr(value);
-    }
-    size_t oid_length = 0;
-    uint8_t *oid_data = NULL;
-    if (CFGetTypeID(oid) == CFStringGetTypeID()) {
-        if (CFEqual(kSecOidCommonName, oid)) {
-            oid_length = oidCommonName.length; oid_data = oidCommonName.data;
-        } else if (CFEqual(kSecOidCountryName, oid)) {
-            oid_length = oidCountryName.length; oid_data = oidCountryName.data;
-        } else if (CFEqual(kSecOidStateProvinceName, oid)) {
-            oid_length = oidStateOrProvinceName.length; oid_data = oidStateOrProvinceName.data;
-        } else if (CFEqual(kSecOidLocalityName, oid)) {
-            oid_length = oidLocalityName.length; oid_data = oidLocalityName.data;
-        } else if (CFEqual(kSecOidOrganization, oid)) {
-            oid_length = oidOrganizationName.length; oid_data = oidOrganizationName.data;
-        } else if (CFEqual(kSecOidOrganizationalUnit, oid)) {
-            oid_length = oidOrganizationalUnitName.length; oid_data = oidOrganizationalUnitName.data;
-        } else {
-            oid_data = oid_der_data(poolp, oid, &oid_length);
-            require(oid_data, out);
-        }
-    } else if (CFGetTypeID(oid) == CFDataGetTypeID()) {
-        /* will remain valid for the duration of the operation, still maybe copy into pool */
-        oid_length = CFDataGetLength(oid);
-        oid_data = (uint8_t *)CFDataGetBytePtr(oid);
-    }    
-    NSS_ATV stage_nss_atv = { { oid_length, oid_data }, 
-        { { length, (uint8_t*)buffer }, type } };
-    *nss_atv = stage_nss_atv;
-    return true;
-out:
-    return false;
-}
-
-static NSS_RDN **make_subject(PRArenaPool *poolp, CFArrayRef subject)
-{
-    if (!subject)
-        return NULL;
-    CFIndex rdn_ix, rdn_count = CFArrayGetCount(subject);
-    NSS_RDN **rdnps = PORT_ArenaZNewArray(poolp, NSS_RDN *, rdn_count + 1);
-    NSS_RDN *rdns = PORT_ArenaZNewArray(poolp, NSS_RDN, rdn_count);
-    for (rdn_ix = 0; rdn_ix < rdn_count; rdn_ix++) {
-        rdnps[rdn_ix] = &rdns[rdn_ix];
-        CFArrayRef rdn = CFArrayGetValueAtIndex(subject, rdn_ix);
-        CFIndex atv_ix, atv_count = CFArrayGetCount(rdn);
-        rdns[rdn_ix].atvs = PORT_ArenaZNewArray(poolp, NSS_ATV *, atv_count + 1);
-        NSS_ATV *atvs = PORT_ArenaZNewArray(poolp, NSS_ATV, atv_count);
-        for (atv_ix = 0; atv_ix < atv_count; atv_ix++) {
-            rdns[rdn_ix].atvs[atv_ix] = &atvs[atv_ix];
-            CFArrayRef atv = CFArrayGetValueAtIndex(rdn, atv_ix);
-            if ((CFArrayGetCount(atv) != 2) 
-                || !make_nss_atv(poolp, CFArrayGetValueAtIndex(atv, 0),
-                        CFArrayGetValueAtIndex(atv, 1), 0, &atvs[atv_ix]))
-                return NULL;
-        }
-    }
-    return rdnps;
-}
-
-struct make_general_names_context {
-    PRArenaPool *poolp;
-    SecAsn1Item *names;
-    uint32_t count;
-    uint32_t capacity;
-};
-
-static void make_general_names(const void *key, const void *value, void *context)
-{
-    struct make_general_names_context *gn = (struct make_general_names_context *)context;
-    require(value,out);
-    CFArrayRef gn_values = NULL;
-    CFStringRef gn_value = NULL;
-    CFIndex entry_ix, entry_count = 0;
-    if (CFGetTypeID(value) == CFArrayGetTypeID()) {
-        gn_values = (CFArrayRef)value;
-        entry_count = CFArrayGetCount(value);
-    } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
-        gn_value = (CFStringRef)value;
-        entry_count = 1;
-    }
-
-    require(entry_count > 0, out);
-    
-    require(key,out);
-    require(CFGetTypeID(key) == CFStringGetTypeID(), out);
-
-    if (!gn->names || (gn->count == gn->capacity)) {
-        uint32_t capacity = gn->capacity;
-        if (capacity)
-            capacity *= 2;
-        else
-            capacity = 10;
-        
-        void * new_array = PORT_ArenaZNewArray(gn->poolp, SecAsn1Item, capacity);
-        if (gn->names)
-            memcpy(new_array, gn->names, gn->capacity);
-        gn->names = new_array;
-        gn->capacity = capacity;
-    }
-
-    NSS_GeneralName general_name_item = { { }, -1 };
-    if (kCFCompareEqualTo == CFStringCompare(CFSTR("dNSName"), key, kCFCompareCaseInsensitive))
-        general_name_item.tag = NGT_DNSName;
-    else if (kCFCompareEqualTo == CFStringCompare(CFSTR("rfc822Name"), key, kCFCompareCaseInsensitive))
-        general_name_item.tag = NGT_RFC822Name;
-    else if (kCFCompareEqualTo == CFStringCompare(CFSTR("uniformResourceIdentifier"), key, kCFCompareCaseInsensitive))
-        general_name_item.tag = NGT_URI;
-       else if (kCFCompareEqualTo == CFStringCompare(CFSTR("ntPrincipalName"), key, kCFCompareCaseInsensitive))
-       {
-        /*
-            NT Principal in SubjectAltName is defined in the context of Smartcards:
-
-            http://www.oid-info.com/get/1.3.6.1.4.1.311.20.2.3
-            http://support.microsoft.com/default.aspx?scid=kb;en-us;281245
-
-            Subject Alternative Name = Other Name: Principal Name= (UPN). For example:
-            UPN = user1@name.com
-            The UPN OtherName OID is : "1.3.6.1.4.1.311.20.2.3"
-            The UPN OtherName value: Must be ASN1-encoded UTF8 string
-            Subject = Distinguished name of user. This field is a mandatory extension, but the population of this field is optional.
-        */
-
-               /* OtherName ::= SEQUENCE {
-                                                       type-id OBJECT IDENTIFIER,
-                                                       value [0] EXPLICIT ANY DEFINED BY type-id
-                                               } */
-               uint8_t nt_principal_oid[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03 };
-        typedef struct {
-               SecAsn1Oid typeId;
-               SecAsn1Item value;
-        } nt_principal_other_name;
-        nt_principal_other_name name = {};
-
-        const SecAsn1Template my_other_name_template[] = {
-            { SEC_ASN1_SEQUENCE,
-              0, NULL, sizeof(nt_principal_other_name) },
-            { SEC_ASN1_OBJECT_ID,
-              offsetof(nt_principal_other_name,typeId), },
-            { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, offsetof(nt_principal_other_name,value), kSecAsn1UTF8StringTemplate, },
-            { 0, }
-        };
-        const SecAsn1Template my_other_name_template_cons[] = {
-            { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_OtherName,
-            0, my_other_name_template, sizeof(nt_principal_other_name) }
-        };
-
-        size_t length = 0;
-        char *buffer = NULL;
-
-               require(gn_value, out);
-        require(CFGetTypeID(gn_value) == CFStringGetTypeID(), out);
-        length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
-            kCFStringEncodingUTF8);
-        buffer = PORT_ArenaAlloc(gn->poolp, length);
-        if (!CFStringGetCString(value, buffer, length, kCFStringEncodingUTF8))
-            goto out;
-
-        name.typeId.Length = sizeof(nt_principal_oid);
-        name.typeId.Data = nt_principal_oid;
-        name.value.Length = strlen(buffer);
-        name.value.Data = (uint8_t*)buffer;
-               SEC_ASN1EncodeItem(gn->poolp, &gn->names[gn->count], &name, my_other_name_template_cons);
-        gn->count++;
-
-        /* We already encoded the value for the general name */
-               goto out;
-       }
-       else
-        goto out;
-    
-    if (gn_values) {
-        for (entry_ix = 0; entry_ix < entry_count; entry_ix++) {
-            CFTypeRef entry_value = CFArrayGetValueAtIndex(gn_values, entry_ix);
-            CFIndex buffer_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength((CFStringRef)entry_value),
-                kCFStringEncodingUTF8); /* we only allow ASCII => only expect IA5Strings */
-            char *buffer = (char *)PORT_ArenaZNewArray(gn->poolp, uint8_t, buffer_size);
-            require(CFStringGetCString((CFStringRef)entry_value, buffer, buffer_size, kCFStringEncodingASCII), out);
-            general_name_item.item.Data = (uint8_t*)buffer;
-            general_name_item.item.Length = strlen(buffer);
-            SEC_ASN1EncodeItem(gn->poolp, &gn->names[gn->count], &general_name_item, kSecAsn1GeneralNameTemplate);
-            gn->count++;
-        }
-    } else if (gn_value) {
-        CFIndex buffer_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(gn_value),
-            kCFStringEncodingUTF8);
-        char *buffer = (char *)PORT_ArenaZNewArray(gn->poolp, uint8_t, buffer_size);
-        require(CFStringGetCString(gn_value, buffer, buffer_size, kCFStringEncodingASCII), out);
-        general_name_item.item.Data = (uint8_t*)buffer;
-        general_name_item.item.Length = strlen(buffer);
-        SEC_ASN1EncodeItem(gn->poolp, &gn->names[gn->count], &general_name_item, kSecAsn1GeneralNameTemplate);
-        gn->count++;
-    }
-out:
-    return;
-}
-
-static SecAsn1Item make_subjectAltName_extension(PRArenaPool *poolp, CFDictionaryRef subjectAltNames)
-{
-    SecAsn1Item subjectAltExt = {};
-    
-    struct make_general_names_context context = { poolp, NULL, 0 };
-    CFDictionaryApplyFunction(subjectAltNames, make_general_names, &context);
-
-    // all general names in a sequence:
-    uint32_t ix;
-    SecAsn1Item **general_names = PORT_ArenaZNewArray(poolp, SecAsn1Item *, context.count + 1);
-    for (ix = 0; ix < context.count; ix++)
-        general_names[ix] = &context.names[ix];
-    NSS_GeneralNames gnames = { general_names };
-    SEC_ASN1EncodeItem(poolp, &subjectAltExt, &gnames, kSecAsn1GeneralNamesTemplate);
-
-    return subjectAltExt;
-}
-
-CFTypeRef kSecCSRChallengePassword = CFSTR("csrChallengePassword");
-CFTypeRef kSecSubjectAltName = CFSTR("subjectAltName");
-CFTypeRef kSecCertificateKeyUsage = CFSTR("keyUsage");
-CFTypeRef kSecCSRBasicContraintsPathLen = CFSTR("basicConstraints");
-CFTypeRef kSecCertificateExtensions = CFSTR("certificateExtensions");
-
-static const uint8_t pkcs9ExtensionsRequested[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 14 };
-static const uint8_t pkcs9ChallengePassword[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 7 };
-
-static const uint8_t encoded_asn1_true = 0xFF;
-static const SecAsn1Item asn1_true =
-    { sizeof(encoded_asn1_true), (uint8_t*)&encoded_asn1_true };
-
-static inline uint32_t highest_bit(uint32_t n)
-{
-    return ((n) >> 16 ? ((n)>>=16, 16) : 0) + \
-            ((n) >> 8 ? ((n)>>=8, 8) : 0) + \
-            ((n) >> 4 ? ((n)>>=4, 4) : 0) + \
-            ((n) >> 2 ? ((n)>>=2, 2) : 0) + \
-            ((n) >> 1 ? ((n)>>=1, 1) : 0) + \
-            (n);
-}
-
-struct add_custom_extension_args {
-    PLArenaPool *poolp;
-    NSS_CertExtension *csr_extension;
-    uint32_t num_extensions;
-    uint32_t max_extensions;
-};
-
-static void add_custom_extension(const void *key, const void *value, void *context)
-{
-    struct add_custom_extension_args *args = (struct add_custom_extension_args *)context;
-    size_t der_data_len;
-
-    require(args->num_extensions < args->max_extensions, out);
-
-    uint8_t * der_data = oid_der_data(args->poolp, key, &der_data_len);
-    SecAsn1Item encoded_value = {};
-
-    if (CFGetTypeID(value) == CFStringGetTypeID()) {
-        CFIndex buffer_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8);
-        char *buffer = (char *)PORT_ArenaZNewArray(args->poolp, uint8_t, buffer_size);
-        if (!CFStringGetCString(value, buffer, buffer_size, kCFStringEncodingUTF8))
-            goto out;
-
-        SecAsn1Item buffer_item = { strlen(buffer), (uint8_t*)buffer };
-        SEC_ASN1EncodeItem(args->poolp, &encoded_value, &buffer_item, kSecAsn1UTF8StringTemplate);
-    } else if (CFGetTypeID(value) == CFDataGetTypeID()) {
-        SecAsn1Item data_item = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) };
-        SEC_ASN1EncodeItem(args->poolp, &encoded_value, &data_item, kSecAsn1OctetStringTemplate);
-    } else
-        goto out;
-
-
-    if (der_data && encoded_value.Length) {
-        args->csr_extension[args->num_extensions].value = encoded_value;
-        args->csr_extension[args->num_extensions].extnId.Length = der_data_len;
-        args->csr_extension[args->num_extensions].extnId.Data = der_data;
-        args->num_extensions++;
-    }
-out:
-    return;
-}
-
-static
-NSS_CertExtension **
-extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters)
-{
-    uint32_t num_extensions = 0, max_extensions = 10;
-    NSS_CertExtension **csr_extensions = PORT_ArenaZNewArray(poolp, NSS_CertExtension *, max_extensions + 1); /* NULL terminated array */
-    NSS_CertExtension *csr_extension = PORT_ArenaZNewArray(poolp, NSS_CertExtension, max_extensions);
-
-    CFNumberRef basic_contraints_num = CFDictionaryGetValue(parameters, kSecCSRBasicContraintsPathLen);
-    if (basic_contraints_num) {
-        NSS_BasicConstraints basic_contraints = { asn1_true, {} };
-        uint8_t path_len;
-        
-        int basic_contraints_path_len = 0;
-        require(CFNumberGetValue(basic_contraints_num, kCFNumberIntType, &basic_contraints_path_len), out);
-        if (basic_contraints_path_len >= 0 && basic_contraints_path_len < 256) {
-            path_len = (uint8_t)basic_contraints_path_len;
-            basic_contraints.pathLenConstraint.Length = sizeof(path_len);
-            basic_contraints.pathLenConstraint.Data = &path_len;
-        }
-        
-        csr_extension[num_extensions].extnId.Data = oidBasicConstraints.data;
-        csr_extension[num_extensions].extnId.Length = oidBasicConstraints.length;
-        csr_extension[num_extensions].critical = asn1_true;
-        
-        SEC_ASN1EncodeItem(poolp, &csr_extension[num_extensions].value, &basic_contraints, 
-            kSecAsn1BasicConstraintsTemplate);
-        require(num_extensions++ < max_extensions, out);
-    }
-
-    CFDictionaryRef subject_alternate_names = CFDictionaryGetValue(parameters, kSecSubjectAltName);
-    if (subject_alternate_names) {
-        require(CFGetTypeID(subject_alternate_names) == CFDictionaryGetTypeID(), out);
-        csr_extension[num_extensions].value = make_subjectAltName_extension(poolp, subject_alternate_names);
-        /* set up subjectAltName cert request value */
-        csr_extension[num_extensions].extnId.Length = oidSubjectAltName.length;
-        csr_extension[num_extensions].extnId.Data = oidSubjectAltName.data;
-        require(num_extensions++ < max_extensions, out);
-    }
-
-    CFNumberRef key_usage_requested = CFDictionaryGetValue(parameters, kSecCertificateKeyUsage);
-    SecAsn1Item key_usage_asn1_value = { 0 };
-    if (key_usage_requested) {
-        int key_usage_value;
-        require(CFNumberGetValue(key_usage_requested, kCFNumberIntType, &key_usage_value), out);
-        if (key_usage_value > 0) {
-            uint32_t key_usage_value_be = 0, key_usage_mask = 1<<31;
-            uint32_t key_usage_value_max_bitlen = 9, key_usage_value_bitlen = 0;
-            while(key_usage_value_max_bitlen) {
-                if (key_usage_value & 1) {
-                    key_usage_value_be |= key_usage_mask;
-                    key_usage_value_bitlen = 10 - key_usage_value_max_bitlen;
-                }
-                key_usage_value >>= 1;
-                key_usage_value_max_bitlen--;
-                key_usage_mask >>= 1;
-            }
-
-            SecAsn1Item key_usage_input = { key_usage_value_bitlen, 
-                ((uint8_t*)&key_usage_value_be) + 3 - (key_usage_value_bitlen >> 3) };
-            SEC_ASN1EncodeItem(poolp, &key_usage_asn1_value, &key_usage_input, kSecAsn1BitStringTemplate);
-
-            csr_extension[num_extensions].extnId.Data = oidKeyUsage.data;
-            csr_extension[num_extensions].extnId.Length = oidKeyUsage.length;
-            csr_extension[num_extensions].critical = asn1_true;
-            csr_extension[num_extensions].value = key_usage_asn1_value;
-            require(num_extensions++ < max_extensions, out);
-        }
-    }
-
-    CFDictionaryRef custom_extension_requested = CFDictionaryGetValue(parameters, kSecCertificateExtensions);
-    if (custom_extension_requested) {
-        require(CFGetTypeID(custom_extension_requested) == CFDictionaryGetTypeID(), out);
-        struct add_custom_extension_args args = {
-            poolp,
-            csr_extension,
-            num_extensions,
-            max_extensions
-        };
-        CFDictionaryApplyFunction(custom_extension_requested, add_custom_extension, &args);
-        num_extensions = args.num_extensions;
-    }
-
-    /* extensions requested (subjectAltName, keyUsage) sequence of extension sequences */
-    uint32_t ix = 0;
-    for (ix = 0; ix < num_extensions; ix++)
-        csr_extensions[ix] = csr_extension[ix].extnId.Length ? &csr_extension[ix] : NULL;
-
-out:
-    return csr_extensions;
-}
-
-
-
-static
-NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictionaryRef parameters)
-{
-    /* A challenge-password attribute must have a single attribute value.
-
-       ChallengePassword attribute values generated in accordance with this
-       version of this document SHOULD use the PrintableString encoding
-       whenever possible.  If internationalization issues make this
-       impossible, the UTF8String alternative SHOULD be used.  PKCS #9-
-       attribute processing systems MUST be able to recognize and process
-       all string types in DirectoryString values. 
-       
-       Upperbound of 255 defined for all PKCS#9 attributes.
-       
-       pkcs-9 OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840)
-                                        rsadsi(113549) pkcs(1) 9}
-       pkcs-9-at-challengePassword   OBJECT IDENTIFIER ::= {pkcs-9 7}
-       
-    */
-    if (!parameters)
-        return NULL;
-    uint32_t num_attrs = 0;
-
-    CFStringRef challenge = CFDictionaryGetValue(parameters, kSecCSRChallengePassword);
-    NSS_Attribute challenge_password_attr = {};
-    if (challenge) {
-        CFIndex buffer_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(challenge),
-            kCFStringEncodingUTF8); /* we only allow UTF8 or ASCII */
-        char *buffer = (char *)PORT_ArenaZNewArray(poolp, uint8_t, buffer_size);
-        bool utf8 = false;
-        if (!CFStringGetCString(challenge, buffer, buffer_size, kCFStringEncodingASCII)) {
-            if (!CFStringGetCString(challenge, buffer, buffer_size, kCFStringEncodingUTF8))
-                return NULL;
-            utf8 = true;
-        } else
-            if (!printable_string(challenge))
-                utf8 = true;
-
-        SecAsn1Item *challenge_password_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1);        
-        SecAsn1Item challenge_password_raw = { strlen(buffer), (uint8_t*)buffer };
-        SEC_ASN1EncodeItem(poolp, challenge_password_value, &challenge_password_raw, 
-            utf8 ? kSecAsn1UTF8StringTemplate : kSecAsn1PrintableStringTemplate);
-        SecAsn1Item **challenge_password_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2);        
-        challenge_password_values[0] = challenge_password_value;
-        challenge_password_attr.attrType.Length = sizeof(pkcs9ChallengePassword);
-        challenge_password_attr.attrType.Data = (uint8_t*)&pkcs9ChallengePassword;
-        challenge_password_attr.attrValue = challenge_password_values;
-        num_attrs++;
-    }
-
-    NSS_CertExtension **extensions = extensions_from_parameters(poolp, parameters);
-    NSS_Attribute extensions_requested_attr = {};
-    if (extensions) {
-        SecAsn1Item *extensions_requested_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1);
-        SEC_ASN1EncodeItem(poolp, extensions_requested_value, &extensions, kSecAsn1SequenceOfCertExtensionTemplate);
-        SecAsn1Item **extensions_requested_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2);
-        extensions_requested_values[0] = extensions_requested_value;
-        extensions_requested_values[1] = NULL;
-        extensions_requested_attr.attrType.Length = sizeof(pkcs9ExtensionsRequested);
-        extensions_requested_attr.attrType.Data = (uint8_t*)pkcs9ExtensionsRequested;
-        extensions_requested_attr.attrValue = extensions_requested_values;
-        num_attrs++;
-    }
-    
-    NSS_Attribute **attributes_ptr = PORT_ArenaZNewArray(poolp, NSS_Attribute *, num_attrs + 1);
-    NSS_Attribute *attributes = PORT_ArenaZNewArray(poolp, NSS_Attribute, num_attrs);
-    if (challenge_password_attr.attrType.Length) {
-        --num_attrs;
-        attributes[num_attrs] = challenge_password_attr;
-        attributes_ptr[num_attrs] = &attributes[num_attrs];
-    }
-    if (extensions_requested_attr.attrType.Length) {
-        --num_attrs;
-        attributes[num_attrs] = extensions_requested_attr;
-        attributes_ptr[num_attrs] = &attributes[num_attrs];
-    }
-    return attributes_ptr;
-#if 0
-out:
-    return NULL;
-#endif
-}
-
-static const uint8_t encoded_null[2] = { SEC_ASN1_NULL, 0 };
-static const SecAsn1Item asn1_null = { sizeof(encoded_null), (uint8_t*)encoded_null };
-
-CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, 
-    CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey)
-{
-    CFDataRef csr = NULL;
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    CFDictionaryRef pubkey_attrs = NULL;
-    
-    if (!poolp)
-        return NULL;
-
-       NSSCertRequest certReq;
-       memset(&certReq, 0, sizeof(certReq));
-
-    /* version */
-    unsigned char version = 0;
-    certReq.reqInfo.version.Length = sizeof(version);
-    certReq.reqInfo.version.Data = &version;
-
-    /* subject */
-    unsigned atv_num = 0, num = 0;
-    SecRDN *one_rdn;
-    SecATV *one_atv;
-    for (one_rdn = subject; *one_rdn; one_rdn++) {
-        for (one_atv = *one_rdn; one_atv->oid; one_atv++)
-            atv_num++;
-        atv_num++; /* one more */
-        num++;
-    }
-    NSS_ATV atvs[atv_num];
-    NSS_ATV *atvps[atv_num];
-    NSS_RDN rdns[num];
-    NSS_RDN *rdnps[num+1];
-    atv_num = 0;
-    unsigned rdn_num = 0;
-    for (one_rdn = subject; *one_rdn; one_rdn++) {
-        rdns[rdn_num].atvs = &atvps[atv_num];
-        rdnps[rdn_num] = &rdns[rdn_num];
-        rdn_num++;
-        for (one_atv = *one_rdn; one_atv->oid; one_atv++) {
-            if (!make_nss_atv(poolp, one_atv->oid, one_atv->value, 
-                    one_atv->type, &atvs[atv_num]))
-                return NULL;
-            atvps[atv_num] = &atvs[atv_num];
-            atv_num++;
-        }
-        atvps[atv_num++] = NULL;
-    }
-    rdnps[rdn_num] = NULL;
-    certReq.reqInfo.subject.rdns = rdnps;
-    
-    /* public key info */
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.algorithm.Length = oidRsa.length;
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.algorithm.Data = oidRsa.data;
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters = asn1_null;
-    
-    pubkey_attrs = SecKeyCopyAttributeDictionary(publicKey);
-    CFDataRef pkcs1_pubkey = (CFDataRef)CFDictionaryGetValue(pubkey_attrs, kSecValueData);
-    uint8_t signature[8 * CFDataGetLength(pkcs1_pubkey)];
-    size_t signature_length = sizeof(signature);
-
-    certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Length = 8 * CFDataGetLength(pkcs1_pubkey);
-    certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Data = (uint8_t*)CFDataGetBytePtr(pkcs1_pubkey);
-    
-    certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters);
-    SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL);
-
-    /* encode request info by itself to calculate signature */
-    SecAsn1Item reqinfo = {};
-    SEC_ASN1EncodeItem(poolp, &reqinfo, &certReq.reqInfo, kSecAsn1CertRequestInfoTemplate);
-
-    /* calculate signature */
-    uint8_t reqinfo_hash[CC_SHA1_DIGEST_LENGTH];
-    CCDigest(kCCDigestSHA1, reqinfo.Data, (CC_LONG)reqinfo.Length, reqinfo_hash);
-    require_noerr_quiet(SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, 
-        reqinfo_hash, sizeof(reqinfo_hash), signature, &signature_length), out);
-    
-    /* signature and info */
-    certReq.signatureAlgorithm.algorithm.Length = oidSha1Rsa.length;
-    certReq.signatureAlgorithm.algorithm.Data = oidSha1Rsa.data;
-    certReq.signatureAlgorithm.parameters = asn1_null;
-    certReq.signature.Data = signature;
-    certReq.signature.Length = signature_length * 8;
-    
-    /* encode csr */
-    SecAsn1Item cert_request = {};
-    require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, 
-        kSecAsn1CertRequestTemplate), out);
-    csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length);
-    
-out:
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    CFReleaseSafe(pubkey_attrs);
-    return csr;
-}
-
-CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, 
-    CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey)
-{
-    CFDataRef csr = NULL;
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    CFDictionaryRef pubkey_attrs = NULL;
-    
-    if (!poolp)
-        return NULL;
-
-       NSSCertRequest certReq;
-       memset(&certReq, 0, sizeof(certReq));
-
-    /* version */
-    unsigned char version = 0;
-    certReq.reqInfo.version.Length = sizeof(version);
-    certReq.reqInfo.version.Data = &version;
-
-    /* subject */
-    certReq.reqInfo.subject.rdns = make_subject(poolp, (CFArrayRef)subject);
-    
-    /* public key info */
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.algorithm.Length = oidRsa.length;
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.algorithm.Data = oidRsa.data;
-    certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters = asn1_null;
-    
-    pubkey_attrs = SecKeyCopyAttributeDictionary(publicKey);
-    CFDataRef pkcs1_pubkey = (CFDataRef)CFDictionaryGetValue(pubkey_attrs, kSecValueData);
-    uint8_t signature[8 * CFDataGetLength(pkcs1_pubkey)];
-    size_t signature_length = sizeof(signature);
-
-    certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Length = 8 * CFDataGetLength(pkcs1_pubkey);
-    certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Data = (uint8_t*)CFDataGetBytePtr(pkcs1_pubkey);
-    
-    certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters);
-    SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL);
-
-    /* encode request info by itself to calculate signature */
-    SecAsn1Item reqinfo = {};
-    SEC_ASN1EncodeItem(poolp, &reqinfo, &certReq.reqInfo, kSecAsn1CertRequestInfoTemplate);
-
-    /* calculate signature */
-    uint8_t reqinfo_hash[CC_SHA1_DIGEST_LENGTH];
-    CCDigest(kCCDigestSHA1, reqinfo.Data, reqinfo.Length, reqinfo_hash);
-    require_noerr_quiet(SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, 
-        reqinfo_hash, sizeof(reqinfo_hash), signature, &signature_length), out);
-    
-    /* signature and info */
-    certReq.signatureAlgorithm.algorithm.Length = oidSha1Rsa.length;
-    certReq.signatureAlgorithm.algorithm.Data = oidSha1Rsa.data;
-    certReq.signatureAlgorithm.parameters = asn1_null;
-    certReq.signature.Data = signature;
-    certReq.signature.Length = signature_length * 8;
-    
-    /* encode csr */
-    SecAsn1Item cert_request = {};
-    require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, 
-        kSecAsn1CertRequestTemplate), out);
-    csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length);
-    
-out:
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    CFReleaseSafe(pubkey_attrs);
-    return csr;
-}
-
-bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey,
-    CFStringRef *challenge, CFDataRef *subject, CFDataRef *extensions)
-{
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    SecKeyRef candidatePublicKey = NULL;
-    bool valid = false;
-       NSSCertRequest certReq;
-       memset(&certReq, 0, sizeof(certReq));
-    SecAsn1Item csr_item = { CFDataGetLength(csr), (uint8_t*)CFDataGetBytePtr(csr) };
-    require_noerr_quiet(SEC_ASN1DecodeItem(poolp, &certReq, kSecAsn1CertRequestTemplate, 
-        &csr_item), out);
-
-    /* signature and info */
-    require(certReq.signatureAlgorithm.algorithm.Length == oidSha1Rsa.length, out);
-    require_noerr(memcmp(oidSha1Rsa.data, certReq.signatureAlgorithm.algorithm.Data,
-        oidSha1Rsa.length), out);
-    require(certReq.signatureAlgorithm.parameters.Length == asn1_null.Length, out);
-    require_noerr(memcmp(asn1_null.Data, certReq.signatureAlgorithm.parameters.Data, 
-        asn1_null.Length), out);
-
-    /* encode request info by itself to calculate signature */
-    SecAsn1Item reqinfo = {};
-    SEC_ASN1EncodeItem(poolp, &reqinfo, &certReq.reqInfo, kSecAsn1CertRequestInfoTemplate);
-
-    /* calculate signature */
-    uint8_t reqinfo_hash[CC_SHA1_DIGEST_LENGTH];
-    require(reqinfo.Length<=UINT32_MAX, out);
-    CCDigest(kCCDigestSHA1, reqinfo.Data, (CC_LONG)reqinfo.Length, reqinfo_hash);
-
-    /* @@@ check for version 0 */
-
-    require(candidatePublicKey = SecKeyCreateRSAPublicKey(kCFAllocatorDefault, 
-        certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Data,
-        certReq.reqInfo.subjectPublicKeyInfo.subjectPublicKey.Length / 8, 
-        kSecKeyEncodingPkcs1), out);
-
-    require_noerr_quiet(SecKeyRawVerify(candidatePublicKey, kSecPaddingPKCS1SHA1, 
-        reqinfo_hash, sizeof(reqinfo_hash), 
-        certReq.signature.Data, certReq.signature.Length / 8), out);
-        
-    SecAsn1Item subject_item = { 0 }, extensions_item = { 0 }, challenge_item = { 0 };
-    require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, 
-        &certReq.reqInfo.subject, kSecAsn1NameTemplate), out);
-
-    if (*certReq.reqInfo.attributes) {
-        uint32_t ix;
-        for (ix = 0; certReq.reqInfo.attributes[ix]; ix++) {
-            NSS_Attribute *attr = certReq.reqInfo.attributes[ix];
-            if ( (sizeof(pkcs9ChallengePassword) == attr->attrType.Length) &&
-                !memcmp(pkcs9ChallengePassword, attr->attrType.Data, sizeof(pkcs9ChallengePassword)))
-                    challenge_item = *attr->attrValue[0];
-            else if ( (sizeof(pkcs9ExtensionsRequested) == attr->attrType.Length) &&
-                !memcmp(pkcs9ExtensionsRequested, attr->attrType.Data, sizeof(pkcs9ExtensionsRequested)))
-                    extensions_item = *attr->attrValue[0];
-        }
-    }
-    
-    if (subject && subject_item.Length)
-        *subject = CFDataCreate(kCFAllocatorDefault, subject_item.Data, subject_item.Length);
-    if (extensions && extensions_item.Length)
-        *extensions = CFDataCreate(kCFAllocatorDefault, extensions_item.Data, extensions_item.Length);
-    if (challenge && challenge_item.Length) {
-        SecAsn1Item string = { 0 };
-        SECStatus rv = SEC_ASN1DecodeItem(poolp, &string, kSecAsn1UTF8StringTemplate, &challenge_item);
-        if (rv)
-            rv = SEC_ASN1DecodeItem(poolp, &string, kSecAsn1PrintableStringTemplate, &challenge_item);
-        if (!rv)
-            *challenge = CFStringCreateWithBytes(kCFAllocatorDefault, string.Data, string.Length, kCFStringEncodingUTF8, false);
-        else
-            *challenge = NULL;
-    }
-    if (publicKey) {
-        *publicKey = candidatePublicKey;
-        candidatePublicKey = NULL;
-    }
-    valid = true;
-out:
-    CFReleaseSafe(candidatePublicKey);
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    return valid;
-}
-
-#define HIDIGIT(v) (((v) / 10) + '0')    
-#define LODIGIT(v) (((v) % 10) + '0')     
-
-static OSStatus
-DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTime)
-{
-    CFGregorianDate gdate =  CFAbsoluteTimeGetGregorianDate(date, NULL /* GMT */);
-    unsigned char *d;
-    SInt8 second;
-
-    utcTime->Length = 13;
-    utcTime->Data = d = PORT_ArenaAlloc(poolp, 13);
-    if (!utcTime->Data)
-       return SECFailure;
-
-    /* UTC time does not handle the years before 1950 */
-    if (gdate.year < 1950)
-            return SECFailure;
-
-    /* remove the century since it's added to the year by the
-       CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */
-    gdate.year %= 100;
-    second = gdate.second;
-
-    d[0] = HIDIGIT(gdate.year);
-    d[1] = LODIGIT(gdate.year);
-    d[2] = HIDIGIT(gdate.month);   
-    d[3] = LODIGIT(gdate.month);
-    d[4] = HIDIGIT(gdate.day);
-    d[5] = LODIGIT(gdate.day);
-    d[6] = HIDIGIT(gdate.hour);
-    d[7] = LODIGIT(gdate.hour);  
-    d[8] = HIDIGIT(gdate.minute);
-    d[9] = LODIGIT(gdate.minute);
-    d[10] = HIDIGIT(second);
-    d[11] = LODIGIT(second);
-    d[12] = 'Z';
-    return SECSuccess;
-}
-
-SecCertificateRef
-SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, 
-    SecKeyRef publicKey, SecKeyRef privateKey)
-{
-    SecCertificateRef cert = NULL;
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    CFDictionaryRef pubkey_attrs = NULL;
-    if (!poolp)
-        return NULL;
-
-    NSS_Certificate cert_tmpl;
-    memset(&cert_tmpl, 0, sizeof(cert_tmpl));
-
-    /* version */
-    unsigned char version = 2;
-    cert_tmpl.tbs.version.Length = sizeof(version);
-    cert_tmpl.tbs.version.Data = &version;
-
-    /* serialno */
-    unsigned char serialNumber = 1;
-    cert_tmpl.tbs.serialNumber.Length = sizeof(serialNumber);
-    cert_tmpl.tbs.serialNumber.Data = &serialNumber;
-
-    /* subject/issuer */
-    cert_tmpl.tbs.issuer.rdns = make_subject(poolp, (CFArrayRef)subject);
-    cert_tmpl.tbs.subject.rdns = cert_tmpl.tbs.issuer.rdns;
-
-    DER_CFDateToUTCTime(poolp, CFAbsoluteTimeGetCurrent(), &cert_tmpl.tbs.validity.notBefore.item);
-    cert_tmpl.tbs.validity.notBefore.tag = SEC_ASN1_UTC_TIME;
-    DER_CFDateToUTCTime(poolp, CFAbsoluteTimeGetCurrent() + 3600*24*365, &cert_tmpl.tbs.validity.notAfter.item);
-    cert_tmpl.tbs.validity.notAfter.tag = SEC_ASN1_UTC_TIME;
-
-    /* extensions */
-    cert_tmpl.tbs.extensions = extensions_from_parameters(poolp, parameters);
-
-    /* @@@ we only handle rsa keys */
-    pubkey_attrs = SecKeyCopyAttributeDictionary(publicKey);
-    CFTypeRef key_type = CFDictionaryGetValue(pubkey_attrs, kSecAttrKeyType);
-    if (key_type && CFEqual(key_type, kSecAttrKeyTypeRSA)) {
-        /* public key data and algorithm */
-        cert_tmpl.tbs.subjectPublicKeyInfo.algorithm.algorithm = CSSMOID_RSA;
-        cert_tmpl.tbs.subjectPublicKeyInfo.algorithm.parameters = asn1_null;
-
-        CFDataRef pkcs1_pubkey = (CFDataRef)CFDictionaryGetValue(pubkey_attrs, kSecValueData);
-        cert_tmpl.tbs.subjectPublicKeyInfo.subjectPublicKey.Length = 8 * CFDataGetLength(pkcs1_pubkey);
-        cert_tmpl.tbs.subjectPublicKeyInfo.subjectPublicKey.Data = (uint8_t*)CFDataGetBytePtr(pkcs1_pubkey);
-
-        /* signature algorithm */
-        cert_tmpl.tbs.signature.algorithm = CSSMOID_SHA1WithRSA;
-        cert_tmpl.tbs.signature.parameters = asn1_null;
-        cert_tmpl.signatureAlgorithm.algorithm = CSSMOID_SHA1WithRSA;
-        cert_tmpl.signatureAlgorithm.parameters = asn1_null;
-
-        /* encode request info by itself to calculate signature */
-        SecAsn1Item tbscert = {};
-        SEC_ASN1EncodeItem(poolp, &tbscert, &cert_tmpl.tbs, kSecAsn1TBSCertificateTemplate);
-
-        /* calculate signature */
-        uint8_t tbscert_hash[CC_SHA1_DIGEST_LENGTH];
-        CCDigest(kCCDigestSHA1, tbscert.Data, tbscert.Length, tbscert_hash);
-        uint8_t signature[8 * CFDataGetLength(pkcs1_pubkey)];
-        size_t signature_length = sizeof(signature);
-        require_noerr_quiet(SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, 
-                    tbscert_hash, sizeof(tbscert_hash), signature, &signature_length), out);
-
-        /* signature */
-        cert_tmpl.signature.Data = signature;
-        cert_tmpl.signature.Length = signature_length * 8;
-
-        /* encode cert */
-        SecAsn1Item signed_cert = {};
-        require_quiet(SEC_ASN1EncodeItem(poolp, &signed_cert, &cert_tmpl, 
-                    kSecAsn1SignedCertTemplate), out);
-        cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, 
-                signed_cert.Data, signed_cert.Length);
-    }
-out:
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    CFReleaseSafe(pubkey_attrs);
-    return cert;
-}
-
-
-SecCertificateRef
-SecIdentitySignCertificate(SecIdentityRef issuer, CFDataRef serialno,
-    SecKeyRef publicKey, CFTypeRef subject, CFTypeRef extensions)
-{
-    SecCertificateRef cert = NULL;
-    SecKeyRef privateKey = NULL;
-
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    CFDictionaryRef pubkey_attrs = NULL;
-    if (!poolp)
-        return NULL;
-
-    NSS_Certificate cert_tmpl;
-    memset(&cert_tmpl, 0, sizeof(cert_tmpl));
-
-    /* version */
-    unsigned char version = 2;
-    cert_tmpl.tbs.version.Length = sizeof(version);
-    cert_tmpl.tbs.version.Data = &version;
-
-    /* serialno */
-    cert_tmpl.tbs.serialNumber.Length = CFDataGetLength(serialno);
-    cert_tmpl.tbs.serialNumber.Data = (uint8_t*)CFDataGetBytePtr(serialno);
-
-    /* subject/issuer */
-    if (CFArrayGetTypeID() == CFGetTypeID(subject))
-        cert_tmpl.tbs.subject.rdns = make_subject(poolp, (CFArrayRef)subject);
-    else if (CFDataGetTypeID() == CFGetTypeID(subject)) {
-        SecAsn1Item subject_item = { CFDataGetLength(subject), (uint8_t*)CFDataGetBytePtr(subject) };
-        require_noerr_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.subject.rdns, kSecAsn1NameTemplate, &subject_item), out);
-    } else
-        goto out;
-
-    SecCertificateRef issuer_cert = NULL;
-    require_noerr(SecIdentityCopyCertificate(issuer, &issuer_cert), out);
-    CFDataRef issuer_name = SecCertificateCopySubjectSequence(issuer_cert);
-    SecAsn1Item issuer_item = { CFDataGetLength(issuer_name), (uint8_t*)CFDataGetBytePtr(issuer_name) };
-    require_noerr_action_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.issuer.rdns, 
-        kSecAsn1NameTemplate, &issuer_item), out, CFReleaseNull(issuer_name));
-    CFReleaseNull(issuer_name);
-
-    DER_CFDateToUTCTime(poolp, CFAbsoluteTimeGetCurrent(), &cert_tmpl.tbs.validity.notBefore.item);
-    cert_tmpl.tbs.validity.notBefore.tag = SEC_ASN1_UTC_TIME;
-    DER_CFDateToUTCTime(poolp, CFAbsoluteTimeGetCurrent() + 3600*24*365, &cert_tmpl.tbs.validity.notAfter.item);
-    cert_tmpl.tbs.validity.notAfter.tag = SEC_ASN1_UTC_TIME;
-
-    /* extensions */
-       if (extensions) {
-        if (CFDataGetTypeID() == CFGetTypeID(extensions)) {
-            SecAsn1Item requested_extensions = { CFDataGetLength(extensions), (uint8_t*)CFDataGetBytePtr(extensions) };
-            //NSS_CertExtension **requested_extensions_decoded;
-            require_noerr_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.extensions,
-                        kSecAsn1SequenceOfCertExtensionTemplate, &requested_extensions), out);
-        } else if (CFDictionaryGetTypeID() == CFGetTypeID(extensions)) {
-            cert_tmpl.tbs.extensions = extensions_from_parameters(poolp, extensions);
-        }
-    }
-
-    /* @@@ we only handle rsa keys */
-    pubkey_attrs = SecKeyCopyAttributeDictionary(publicKey);
-    CFTypeRef key_type = CFDictionaryGetValue(pubkey_attrs, kSecAttrKeyType);
-    if (key_type && CFEqual(key_type, kSecAttrKeyTypeRSA)) {
-        /* public key data and algorithm */
-        cert_tmpl.tbs.subjectPublicKeyInfo.algorithm.algorithm = CSSMOID_RSA;
-        cert_tmpl.tbs.subjectPublicKeyInfo.algorithm.parameters = asn1_null;
-
-        CFDataRef pkcs1_pubkey = (CFDataRef)CFDictionaryGetValue(pubkey_attrs, kSecValueData);
-        cert_tmpl.tbs.subjectPublicKeyInfo.subjectPublicKey.Length = 8 * CFDataGetLength(pkcs1_pubkey);
-        cert_tmpl.tbs.subjectPublicKeyInfo.subjectPublicKey.Data = (uint8_t*)CFDataGetBytePtr(pkcs1_pubkey);
-
-        /* signature algorithm */
-        cert_tmpl.tbs.signature.algorithm = CSSMOID_SHA1WithRSA;
-        cert_tmpl.tbs.signature.parameters = asn1_null;
-        cert_tmpl.signatureAlgorithm.algorithm = CSSMOID_SHA1WithRSA;
-        cert_tmpl.signatureAlgorithm.parameters = asn1_null;
-
-        /* encode request info by itself to calculate signature */
-        SecAsn1Item tbscert = {};
-        SEC_ASN1EncodeItem(poolp, &tbscert, &cert_tmpl.tbs, kSecAsn1TBSCertificateTemplate);
-
-        /* calculate signature */
-        uint8_t tbscert_hash[CC_SHA1_DIGEST_LENGTH];
-        CCDigest(kCCDigestSHA1, tbscert.Data, tbscert.Length, tbscert_hash);
-        uint8_t signature[8 * CFDataGetLength(pkcs1_pubkey)];
-        size_t signature_length = sizeof(signature);
-        
-        require_noerr_quiet(SecIdentityCopyPrivateKey(issuer, &privateKey), out);
-        require_noerr_quiet(SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, 
-                    tbscert_hash, sizeof(tbscert_hash), signature, &signature_length), out);
-
-        /* signature */
-        cert_tmpl.signature.Data = signature;
-        cert_tmpl.signature.Length = signature_length * 8;
-
-        /* encode cert */
-        SecAsn1Item signed_cert = {};
-        require_quiet(SEC_ASN1EncodeItem(poolp, &signed_cert, &cert_tmpl, 
-                    kSecAsn1SignedCertTemplate), out);
-        cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, 
-                signed_cert.Data, signed_cert.Length);
-    }
-out:
-        CFReleaseSafe(privateKey);
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    CFReleaseSafe(pubkey_attrs);
-    return cert;
-}
-
-CFDataRef
-SecGenerateCertificateRequestSubject(SecCertificateRef ca_certificate, CFArrayRef subject)
-{
-    CFMutableDataRef sequence = NULL;
-    PRArenaPool *poolp = PORT_NewArena(1024);
-    if (!poolp)
-        return NULL;
-
-    /*
-        Going agains the spec here:
-
-            3.2.3.  GetCertInitial
-
-           The messageData for this type consists of a DER-encoded
-           IssuerAndSubject (Section 3.2.3.1).  The issuer is set to the
-           issuerName from the certification authority from which we are issued
-           certificates.  The Subject is set to the SubjectName we used when
-           requesting the certificate.
-
-        That clearly says use the issuer of the cert issuing certificate.  Since
-        it is combined with the subject of the to-be-issued certificate, that
-        seems a mistake.  If we take the subject of the issuer and the subject
-        of the certificate we're interested in, we get the issuer and subject
-        the certificate to be returned will have.
-
-    */
-    CFDataRef issuer_sequence = SecCertificateCopySubjectSequence(ca_certificate);
-    SecAsn1Item subject_item = { 0 };
-    SecAsn1Item issuer_item = { CFDataGetLength(issuer_sequence), (uint8_t*)CFDataGetBytePtr(issuer_sequence) };
-    NSS_Name nss_subject = { make_subject(poolp, subject) };
-    require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, &nss_subject, kSecAsn1NameTemplate), out);
-
-    DERSize sequence_length = DERLengthOfLength(subject_item.Length + issuer_item.Length);
-    DERSize seq_len_length = subject_item.Length + issuer_item.Length + 1 /* SEQUENCE */ +
-        sequence_length;
-    sequence = CFDataCreateMutable(kCFAllocatorDefault, 0);
-    CFDataSetLength(sequence, seq_len_length);
-    uint8_t *sequence_ptr = CFDataGetMutableBytePtr(sequence);
-    *sequence_ptr++ = 0x30; //ASN1_CONSTR_SEQUENCE;
-    require_noerr_quiet(DEREncodeLength(subject_item.Length + issuer_item.Length, sequence_ptr, &sequence_length), out);
-    sequence_ptr += sequence_length;
-    memcpy(sequence_ptr, issuer_item.Data, issuer_item.Length);
-    memcpy(sequence_ptr + issuer_item.Length, subject_item.Data, subject_item.Length);
-
-out:
-    CFReleaseSafe(issuer_sequence);
-    if (poolp)
-        PORT_FreeArena(poolp, PR_TRUE);
-    return sequence;
-}