static void sc_asn1_print_object_id(const u8 * buf, size_t buflen) { struct sc_object_id oid; int i = 0; char tmp[12]; char sbuf[(sizeof tmp)*SC_MAX_OBJECT_ID_OCTETS]; if (sc_asn1_decode_object_id(buf, buflen, &oid)) { printf("decode error"); return; } sbuf[0] = 0; for (i = 0; (i < SC_MAX_OBJECT_ID_OCTETS) && (oid.value[i] != -1); i++) { if (i) strcat(sbuf, "."); sprintf(tmp, "%d", oid.value[i]); strcat(sbuf, tmp); } printf("%s", sbuf); }
/* Get a component of Distinguished Name (e.i. subject or issuer) USING the oid tag. * dn can be either cert->subject or cert->issuer. * dn_len would be cert->subject_len or cert->issuer_len. * * Common types: * CN: struct sc_object_id type = {{2, 5, 4, 3, -1}}; * Country: struct sc_object_id type = {{2, 5, 4, 6, -1}}; * L: struct sc_object_id type = {{2, 5, 4, 7, -1}}; * S: struct sc_object_id type = {{2, 5, 4, 8, -1}}; * O: struct sc_object_id type = {{2, 5, 4, 10, -1}}; * OU: struct sc_object_id type = {{2, 5, 4, 11, -1}}; * * if *name is NULL, sc_pkcs15_get_name_from_dn will allocate space for name. */ int sc_pkcs15_get_name_from_dn(struct sc_context *ctx, const u8 *dn, size_t dn_len, const struct sc_object_id *type, u8 **name, size_t *name_len) { const u8 *rdn = NULL; const u8 *next_ava = NULL; size_t rdn_len = 0; size_t next_ava_len = 0; int rv; rdn = sc_asn1_skip_tag(ctx, &dn, &dn_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &rdn_len); if (rdn == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of Distiguished Name"); for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) { const u8 *ava, *dummy, *oidp; struct sc_object_id oid; size_t ava_len, dummy_len, oid_len; /* unwrap the set and point to the next ava */ ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len); if (ava == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA"); /* It would be nice to use sc_asn1_decode here to parse the entire AVA, but we are missing 1 critical * function in the templates: the ability to accept any tag for value. This prevents us from just * grabbing the value as is out of the template. AVA's can have tags of PRINTABLE_STRING, * TELETEXSTRING, T61STRING or UTF8_STRING with PRINTABLE_STRING and UTF8_STRING being the most common. * The other feature that would be nice is returning a pointer to our requested data using the space * of the parent (basically what this code is doing here), rather than allocating and copying. */ /* unwrap the sequence */ dummy = ava; dummy_len = ava_len; ava = sc_asn1_skip_tag(ctx, &dummy, &dummy_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &ava_len); if (ava == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA"); /* unwrap the oid */ oidp = sc_asn1_skip_tag(ctx, &ava, &ava_len, SC_ASN1_TAG_OBJECT, &oid_len); if (ava == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID"); /* Convert to OID */ rv = sc_asn1_decode_object_id(oidp, oid_len, &oid); if (rv != SC_SUCCESS) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID"); if (sc_compare_oid(&oid, type) == 0) continue; /* Yes, then return the name */ dummy = sc_asn1_skip_tag(ctx, &ava, &ava_len, ava[0] & SC_ASN1_TAG_PRIMITIVE, &dummy_len); if (*name == NULL) { *name = malloc(dummy_len); if (*name == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); *name_len = dummy_len; } *name_len = MIN(dummy_len, *name_len); memcpy(*name, dummy, *name_len); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } LOG_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND); }