int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, int nid, int type, const void *bytes, int len) { if (X509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len)) return 1; return 0; }
int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, const unsigned char *bytes, int len) { if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL) return 1; return 0; }
int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, int nid, int type, const unsigned char *bytes, int len) { if(X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len)) return 1; return 0; }
int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen) { if (X509at_add1_attr_by_NID(&bag->attrib, NID_ms_csp_name, MBSTRING_ASC, (unsigned char *)name, namelen)) return 1; else return 0; }
int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name, int namelen) { if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, MBSTRING_BMP, name, namelen)) return 1; else return 0; }
int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen) { if (X509at_add1_attr_by_NID(&bag->attrib, NID_localKeyID, V_ASN1_OCTET_STRING, name, namelen)) return 1; else return 0; }
int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage) { unsigned char us_val; us_val = (unsigned char)usage; if (X509at_add1_attr_by_NID(&p8->attributes, NID_key_usage, V_ASN1_BIT_STRING, &us_val, 1)) return 1; else return 0; }
static TokenError saveKeys(const CertReq *reqs, const char *hostname, const char *password, FILE *file) { TokenError error = TokenError_Unknown; PKCS12 *p12 = NULL; // Add PKCS7 safes with the keys STACK_OF(PKCS7) *authsafes = NULL; uint32_t localKeyId = 0; size_t error_count = 0; while (reqs) { STACK_OF(PKCS12_SAFEBAG) *bags = NULL; X509 *cert = NULL; ASN1_OBJECT *objOwningHost = NULL; uint32_t keyid = htonl(localKeyId++); bool success = false; // Add private key PKCS12_SAFEBAG *bag = PKCS12_add_key(&bags, reqs->privkey, opensslKeyUsages[reqs->pkcs10->keyUsage], ENC_ITER, ENC_NID, (char*)password); if (!bag) goto loop_end; // Add name and localKeyId to the key bag // TODO extract name from subject DN char *name = "names are not implemented yet"; if (!X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, MBSTRING_UTF8, (unsigned char*)name, strlen(name)) || !PKCS12_add_localkeyid(bag, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; // Add a certificate so we can find the key by the subject name cert = X509_REQ_to_X509(reqs->x509, 3650, reqs->privkey); if (!cert || !X509_keyid_set1(cert, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; if (!X509_add_ext(cert, makeKeyUsageExt(reqs->pkcs10->keyUsage), -1)) goto loop_end; if (!PKCS12_add_cert(&bags, cert)) goto loop_end; // Add hostname (FriBID extension) so we can do same-origin checks // TODO maybe we should use document.domain instead of document.location.hostname? objOwningHost = OBJ_txt2obj(OID_OWNING_HOST, 1); if (!objOwningHost) goto loop_end; bag = sk_PKCS12_SAFEBAG_value(bags, sk_PKCS12_SAFEBAG_num(bags)-1); if (!X509at_add1_attr_by_OBJ(&bag->attrib, objOwningHost, MBSTRING_UTF8, (unsigned char*)hostname, strlen(hostname))) goto loop_end; // Add a new authsafe if (!PKCS12_add_safe(&authsafes, bags, -1, 0, NULL)) goto loop_end; // Success! success = true; loop_end: if (!success) { error_count--; certutil_updateErrorString(); } ASN1_OBJECT_free(objOwningHost); X509_free(cert); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); reqs = reqs->next; } if (error_count != 0) goto end; // Create the PKCS12 wrapper p12 = PKCS12_add_safes(authsafes, 0); if (!p12) { certutil_updateErrorString(); goto end; } PKCS12_set_mac(p12, (char*)password, -1, NULL, 0, MAC_ITER, NULL); // Save file if (i2d_PKCS12_fp(file, p12)) { error = TokenError_Success; } end: sk_PKCS7_pop_free(authsafes, PKCS7_free); PKCS12_free(p12); return error; }