/* Build a value tree from the already stored values. */ static gpg_error_t build_cri (ksba_certreq_t cr) { gpg_error_t err; ksba_writer_t writer; void *value = NULL; size_t valuelen; int certmode; /* If a serial number has been set, we don't create a CSR but a proper certificate. */ certmode = !!cr->x509.serial.der; err = ksba_writer_new (&writer); if (err) goto leave; err = ksba_writer_set_mem (writer, 2048); if (err) goto leave; if (!cr->key.der) { err = gpg_error (GPG_ERR_MISSING_VALUE); goto leave; } /* We write all stuff out to a temporary writer object, then use this object to create the cri and store the cri image */ if (certmode) { /* Store the version structure; version is 3 (encoded as 2): [0] { INTEGER 2 } */ err = ksba_writer_write (writer, "\xa0\x03\x02\x01\x02", 5); } else { /* Store version v1 (which is a 0). */ err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 1); if (!err) err = ksba_writer_write (writer, "", 1); } if (err) goto leave; /* For a certificate we need to store the s/n, the signature algorithm identifier, the issuer DN and the validity. */ if (certmode) { /* Store the serial number. */ err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, cr->x509.serial.derlen); if (!err) err = ksba_writer_write (writer, cr->x509.serial.der, cr->x509.serial.derlen); if (err) goto leave; /* Store the signature algorithm identifier. */ if (!cr->x509.siginfo.der) err = gpg_error (GPG_ERR_MISSING_VALUE); else err = ksba_writer_write (writer, cr->x509.siginfo.der, cr->x509.siginfo.derlen); if (err) goto leave; /* Store the issuer DN. If no issuer DN has been set we use the subject DN. */ if (cr->x509.issuer.der) err = ksba_writer_write (writer, cr->x509.issuer.der, cr->x509.issuer.derlen); else if (cr->subject.der) err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen); else err = gpg_error (GPG_ERR_MISSING_VALUE); if (err) goto leave; /* Store the Validity. */ { unsigned char templ[36]; unsigned char *tp; tp = templ; *tp++ = 0x30; *tp++ = 0x22; *tp++ = TYPE_GENERALIZED_TIME; *tp++ = 15; if (cr->x509.not_before[0]) { if (_ksba_cmp_time (cr->x509.not_before, "20500101T000000") >= 0) { memcpy (tp, cr->x509.not_before, 8); tp += 8; memcpy (tp, cr->x509.not_before+9, 6); tp += 6; } else { tp[-2] = TYPE_UTC_TIME; tp[-1] = 13; memcpy (tp, cr->x509.not_before+2, 6); tp += 6; memcpy (tp, cr->x509.not_before+9, 6); tp += 6; } } else { tp[-2] = TYPE_UTC_TIME; tp[-1] = 13; memcpy (tp, "110101000000", 12); tp += 12; } *tp++ = 'Z'; *tp++ = TYPE_GENERALIZED_TIME; *tp++ = 15; if (cr->x509.not_after[0]) { if (_ksba_cmp_time (cr->x509.not_after, "20500101T000000") >= 0) { memcpy (tp, cr->x509.not_after, 8); tp += 8; memcpy (tp, cr->x509.not_after+9, 6); tp += 6; } else { tp[-2] = TYPE_UTC_TIME; tp[-1] = 13; memcpy (tp, cr->x509.not_after+2, 6); tp += 6; memcpy (tp, cr->x509.not_after+9, 6); tp += 6; } } else { memcpy (tp,"20630405170000", 14); tp += 14; } *tp++ = 'Z'; assert (tp - templ <= 36); templ[1] = tp - templ - 2; /* Fixup the sequence length. */ err = ksba_writer_write (writer, templ, tp - templ); if (err) goto leave; } } /* store the subject */ if (!cr->subject.der) { err = gpg_error (GPG_ERR_MISSING_VALUE); goto leave; } err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen); if (err) goto leave; /* store the public key info */ err = ksba_writer_write (writer, cr->key.der, cr->key.derlen); if (err) goto leave; /* Copy generalNames objects to the extension list. */ if (cr->subject_alt_names) { err = add_general_names_to_extn (cr, cr->subject_alt_names, oidstr_subjectAltName); if (err) goto leave; while (cr->subject_alt_names) { struct general_names_s *tmp = cr->subject_alt_names->next; xfree (cr->subject_alt_names); cr->subject_alt_names = tmp; } cr->subject_alt_names = NULL; } /* Write the extensions. Note that the implicit SET OF is REQUIRED */ xfree (value); value = NULL; valuelen = 0; if (cr->extn_list) { err = build_extensions (cr, certmode, &value, &valuelen); if (err) goto leave; err = _ksba_ber_write_tl (writer, certmode? 3:0, CLASS_CONTEXT, 1, valuelen); if (!err) err = ksba_writer_write (writer, value, valuelen); if (err) goto leave; } else { /* We can't write an object of length zero using our ber_write function. So we must open encode it. */ err = ksba_writer_write (writer, certmode? "\xa3\x02\x30":"\xa0\x02\x30", 4); if (err) goto leave; } /* pack it into the sequence */ xfree (value); value = ksba_writer_snatch_mem (writer, &valuelen); if (!value) { err = gpg_error (GPG_ERR_ENOMEM); goto leave; } /* reinitialize the buffer to create the outer sequence */ err = ksba_writer_set_mem (writer, valuelen+10); if (err) goto leave; /* write outer sequence */ err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, valuelen); if (!err) err = ksba_writer_write (writer, value, valuelen); if (err) goto leave; /* and store the final result */ cr->cri.der = ksba_writer_snatch_mem (writer, &cr->cri.derlen); if (!cr->cri.der) err = gpg_error (GPG_ERR_ENOMEM); leave: ksba_writer_release (writer); xfree (value); return err; }
/* Build a value tree from the already stored values. */ static gpg_error_t build_cri (ksba_certreq_t cr) { gpg_error_t err; ksba_writer_t writer; void *value = NULL; size_t valuelen; err = ksba_writer_new (&writer); if (err) goto leave; err = ksba_writer_set_mem (writer, 2048); if (err) goto leave; /* We write all stuff out to a temporary writer object, then use this object to create the cri and store the cri image */ /* store version v1 (which is a 0) */ err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 1); if (!err) err = ksba_writer_write (writer, "", 1); if (err) goto leave; /* store the subject */ if (!cr->subject.der) { err = gpg_error (GPG_ERR_MISSING_VALUE); goto leave; } err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen); if (err) goto leave; /* store the public key info */ if (!cr->key.der) { err = gpg_error (GPG_ERR_MISSING_VALUE); goto leave; } err = ksba_writer_write (writer, cr->key.der, cr->key.derlen); if (err) goto leave; /* Copy generalNames objects to the extension list. */ if (cr->subject_alt_names) { err = add_general_names_to_extn (cr, cr->subject_alt_names, oidstr_subjectAltName); if (err) goto leave; while (cr->subject_alt_names) { struct general_names_s *tmp = cr->subject_alt_names->next; xfree (cr->subject_alt_names); cr->subject_alt_names = tmp; } cr->subject_alt_names = NULL; } /* Write the extensions. Note that the implicit SET OF is REQUIRED */ xfree (value); value = NULL; valuelen = 0; if (cr->extn_list) { err = build_extensions (cr, &value, &valuelen); if (err) goto leave; err = _ksba_ber_write_tl (writer, 0, CLASS_CONTEXT, 1, valuelen); if (!err) err = ksba_writer_write (writer, value, valuelen); if (err) goto leave; } else { /* We can't write an object of length zero using our ber_write function. So we must open encode it. */ err = ksba_writer_write (writer, "\xa0\x02\x30", 4); if (err) goto leave; } /* pack it into the sequence */ xfree (value); value = ksba_writer_snatch_mem (writer, &valuelen); if (!value) { err = gpg_error (GPG_ERR_ENOMEM); goto leave; } /* reinitialize the buffer to create the outer sequence */ err = ksba_writer_set_mem (writer, valuelen+10); if (err) goto leave; /* write outer sequence */ err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, valuelen); if (!err) err = ksba_writer_write (writer, value, valuelen); if (err) goto leave; /* and store the final result */ cr->cri.der = ksba_writer_snatch_mem (writer, &cr->cri.derlen); if (!cr->cri.der) err = gpg_error (GPG_ERR_ENOMEM); leave: ksba_writer_release (writer); xfree (value); return err; }