/* $OpenBSD: example.c,v 1.6 2014/06/29 17:05:36 jsing Exp $ */ #include #include #include #include #include #include int add_signed_time(PKCS7_SIGNER_INFO *si) { ASN1_UTCTIME *sign_time; /* The last parameter is the amount to add/subtract from the current * time (in seconds) */ sign_time = X509_gmtime_adj(NULL, 0); PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME, (char *)sign_time); return (1); } ASN1_UTCTIME * get_signed_time(PKCS7_SIGNER_INFO *si) { ASN1_TYPE *so; so = PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime); if (so->type == V_ASN1_UTCTIME) return so->value.utctime; return NULL; } static int signed_string_nid = -1; void add_signed_string(PKCS7_SIGNER_INFO *si, char *str) { ASN1_OCTET_STRING *os; /* To a an object of OID 1.2.3.4.5, which is an octet string */ if (signed_string_nid == -1) signed_string_nid = OBJ_create("1.2.3.4.5","OID_example","Our example OID"); os = ASN1_OCTET_STRING_new(); ASN1_OCTET_STRING_set(os, (unsigned char*)str, strlen(str)); /* When we add, we do not free */ PKCS7_add_signed_attribute(si, signed_string_nid, V_ASN1_OCTET_STRING, (char *)os); } int get_signed_string(PKCS7_SIGNER_INFO *si, char *buf, int len) { ASN1_TYPE *so; ASN1_OCTET_STRING *os; int i; if (signed_string_nid == -1) signed_string_nid = OBJ_create("1.2.3.4.5","OID_example","Our example OID"); /* To retrieve */ so = PKCS7_get_signed_attribute(si, signed_string_nid); if (so != NULL) { if (so->type == V_ASN1_OCTET_STRING) { os = so->value.octet_string; i = os->length; if ((i + 1) > len) i = len - 1; memcpy(buf, os->data, i); return (i); } } return (0); } static int signed_seq2string_nid = -1; /* ########################################### */ int add_signed_seq2string(PKCS7_SIGNER_INFO *si, char *str1, char *str2) { /* To add an object of OID 1.9.999, which is a sequence containing * 2 octet strings */ unsigned char *p; ASN1_OCTET_STRING *os1, *os2; ASN1_STRING *seq; unsigned char *data; int i, total; if (signed_seq2string_nid == -1) signed_seq2string_nid = OBJ_create("1.9.9999","OID_example","Our example OID"); os1 = ASN1_OCTET_STRING_new(); os2 = ASN1_OCTET_STRING_new(); ASN1_OCTET_STRING_set(os1, (unsigned char*)str1, strlen(str1)); ASN1_OCTET_STRING_set(os2, (unsigned char*)str1, strlen(str1)); i = i2d_ASN1_OCTET_STRING(os1, NULL); i += i2d_ASN1_OCTET_STRING(os2, NULL); total = ASN1_object_size(1, i, V_ASN1_SEQUENCE); data = malloc(total); p = data; ASN1_put_object(&p, 1,i, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); i2d_ASN1_OCTET_STRING(os1, &p); i2d_ASN1_OCTET_STRING(os2, &p); seq = ASN1_STRING_new(); ASN1_STRING_set(seq, data, total); free(data); ASN1_OCTET_STRING_free(os1); ASN1_OCTET_STRING_free(os2); PKCS7_add_signed_attribute(si, signed_seq2string_nid, V_ASN1_SEQUENCE, (char *)seq); return (1); } /* For this case, I will malloc the return strings */ int get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) { ASN1_TYPE *so; if (signed_seq2string_nid == -1) signed_seq2string_nid = OBJ_create("1.9.9999","OID_example","Our example OID"); /* To retrieve */ so = PKCS7_get_signed_attribute(si, signed_seq2string_nid); if (so && (so->type == V_ASN1_SEQUENCE)) { ASN1_const_CTX c; ASN1_STRING *s; long length; ASN1_OCTET_STRING *os1, *os2; s = so->value.sequence; c.p = ASN1_STRING_data(s); c.max = c.p + ASN1_STRING_length(s); if (!asn1_GetSequence(&c, &length)) goto err; /* Length is the length of the seqence */ c.q = c.p; if ((os1 = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); c.q = c.p; if ((os2 = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); if (!asn1_const_Finish(&c)) goto err; *str1 = malloc(os1->length + 1); *str2 = malloc(os2->length + 1); memcpy(*str1, os1->data, os1->length); memcpy(*str2, os2->data, os2->length); (*str1)[os1->length]='\0'; (*str2)[os2->length]='\0'; ASN1_OCTET_STRING_free(os1); ASN1_OCTET_STRING_free(os2); return (1); } err: return (0); } /* ####################################### * THE OTHER WAY TO DO THINGS * ####################################### */ X509_ATTRIBUTE * create_time(void) { ASN1_UTCTIME *sign_time; X509_ATTRIBUTE *ret; /* The last parameter is the amount to add/subtract from the current * time (in seconds) */ sign_time = X509_gmtime_adj(NULL, 0); ret = X509_ATTRIBUTE_create(NID_pkcs9_signingTime, V_ASN1_UTCTIME, (char *)sign_time); return (ret); } ASN1_UTCTIME * sk_get_time(STACK_OF(X509_ATTRIBUTE) *sk) { ASN1_TYPE *so; PKCS7_SIGNER_INFO si; si.auth_attr = sk; so = PKCS7_get_signed_attribute(&si, NID_pkcs9_signingTime); if (so->type == V_ASN1_UTCTIME) return so->value.utctime; return NULL; } X509_ATTRIBUTE * create_string(char *str) { ASN1_OCTET_STRING *os; X509_ATTRIBUTE *ret; /* To a an object of OID 1.2.3.4.5, which is an octet string */ if (signed_string_nid == -1) signed_string_nid = OBJ_create("1.2.3.4.5","OID_example","Our example OID"); os = ASN1_OCTET_STRING_new(); ASN1_OCTET_STRING_set(os, (unsigned char*)str, strlen(str)); /* When we add, we do not free */ ret = X509_ATTRIBUTE_create(signed_string_nid, V_ASN1_OCTET_STRING, (char *)os); return (ret); } int sk_get_string(STACK_OF(X509_ATTRIBUTE) *sk, char *buf, int len) { ASN1_TYPE *so; ASN1_OCTET_STRING *os; int i; PKCS7_SIGNER_INFO si; si.auth_attr = sk; if (signed_string_nid == -1) signed_string_nid = OBJ_create("1.2.3.4.5","OID_example","Our example OID"); /* To retrieve */ so = PKCS7_get_signed_attribute(&si, signed_string_nid); if (so != NULL) { if (so->type == V_ASN1_OCTET_STRING) { os = so->value.octet_string; i = os->length; if ((i + 1) > len) i = len - 1; memcpy(buf, os->data, i); return (i); } } return (0); } X509_ATTRIBUTE * add_seq2string(PKCS7_SIGNER_INFO *si, char *str1, char *str2) { /* To add an object of OID 1.9.999, which is a sequence containing * 2 octet strings */ unsigned char *p; ASN1_OCTET_STRING *os1, *os2; ASN1_STRING *seq; X509_ATTRIBUTE *ret; unsigned char *data; int i, total; if (signed_seq2string_nid == -1) signed_seq2string_nid = OBJ_create("1.9.9999","OID_example","Our example OID"); os1 = ASN1_OCTET_STRING_new(); os2 = ASN1_OCTET_STRING_new(); ASN1_OCTET_STRING_set(os1, (unsigned char*)str1, strlen(str1)); ASN1_OCTET_STRING_set(os2, (unsigned char*)str1, strlen(str1)); i = i2d_ASN1_OCTET_STRING(os1, NULL); i += i2d_ASN1_OCTET_STRING(os2, NULL); total = ASN1_object_size(1, i, V_ASN1_SEQUENCE); data = malloc(total); p = data; ASN1_put_object(&p, 1,i, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); i2d_ASN1_OCTET_STRING(os1, &p); i2d_ASN1_OCTET_STRING(os2, &p); seq = ASN1_STRING_new(); ASN1_STRING_set(seq, data, total); free(data); ASN1_OCTET_STRING_free(os1); ASN1_OCTET_STRING_free(os2); ret = X509_ATTRIBUTE_create(signed_seq2string_nid, V_ASN1_SEQUENCE, (char *)seq); return (ret); } /* For this case, I will malloc the return strings */ int sk_get_seq2string(STACK_OF(X509_ATTRIBUTE) *sk, char **str1, char **str2) { ASN1_TYPE *so; PKCS7_SIGNER_INFO si; if (signed_seq2string_nid == -1) signed_seq2string_nid = OBJ_create("1.9.9999","OID_example","Our example OID"); si.auth_attr = sk; /* To retrieve */ so = PKCS7_get_signed_attribute(&si, signed_seq2string_nid); if (so->type == V_ASN1_SEQUENCE) { ASN1_const_CTX c; ASN1_STRING *s; long length; ASN1_OCTET_STRING *os1, *os2; s = so->value.sequence; c.p = ASN1_STRING_data(s); c.max = c.p + ASN1_STRING_length(s); if (!asn1_GetSequence(&c, &length)) goto err; /* Length is the length of the seqence */ c.q = c.p; if ((os1 = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); c.q = c.p; if ((os2 = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); if (!asn1_const_Finish(&c)) goto err; *str1 = malloc(os1->length + 1); *str2 = malloc(os2->length + 1); memcpy(*str1, os1->data, os1->length); memcpy(*str2, os2->data, os2->length); (*str1)[os1->length]='\0'; (*str2)[os2->length]='\0'; ASN1_OCTET_STRING_free(os1); ASN1_OCTET_STRING_free(os2); return (1); } err: return (0); }