sc_asn1_put_tag - support larger tags
Enhance sc_asn1_put_tag to support larger tag names and larger tags. Prior to this, sc_asn1_put_tag did only support tags with a length of at most 127 bytes and tag names of one byte.
This commit is contained in:
parent
3961275d8c
commit
7e7a44acff
|
@ -740,23 +740,70 @@ static int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr)
|
int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr)
|
||||||
{
|
{
|
||||||
|
size_t c = 0;
|
||||||
|
size_t tag_len;
|
||||||
|
size_t ii;
|
||||||
u8 *p = out;
|
u8 *p = out;
|
||||||
|
u8 tag_char[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
if (outlen < 2)
|
/* Check tag */
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
if (tag == 0 || tag > 0xFFFFFFFF) {
|
||||||
if (datalen > 127)
|
/* A tag of 0x00 is not valid and at most 4-byte tag names are supported. */
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_DATA;
|
||||||
*p++ = tag & 0xFF; /* FIXME: Support longer tags */
|
}
|
||||||
outlen--;
|
for (tag_len = 0; tag; tag >>= 8) {
|
||||||
*p++ = datalen;
|
/* Note: tag char will be reversed order. */
|
||||||
outlen--;
|
tag_char[tag_len++] = tag & 0xFF;
|
||||||
if (outlen < datalen)
|
}
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
|
||||||
|
|
||||||
memcpy(p, data, datalen);
|
if (tag_len > 1) {
|
||||||
p += datalen;
|
if ((tag_char[tag_len - 1] & SC_ASN1_TAG_PRIMITIVE) != SC_ASN1_TAG_ESCAPE_MARKER) {
|
||||||
|
/* First byte is not escape marker. */
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
for (ii = 1; ii < tag_len - 1; ii++) {
|
||||||
|
if ((tag_char[ii] & 0x80) != 0x80) {
|
||||||
|
/* MS bit is not 'one'. */
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((tag_char[0] & 0x80) != 0x00) {
|
||||||
|
/* MS bit of the last byte is not 'zero'. */
|
||||||
|
return SC_ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the number of additional bytes necessary to encode the length. */
|
||||||
|
/* c+1 is the size of the length field. */
|
||||||
|
if (datalen > 127) {
|
||||||
|
c = 1;
|
||||||
|
while (datalen >> (c << 3))
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
if (outlen == 0 || out == NULL) {
|
||||||
|
/* Caller only asks for the length that would be written. */
|
||||||
|
return tag_len + (c+1) + datalen;
|
||||||
|
}
|
||||||
|
/* We will write the tag, so check the length. */
|
||||||
|
if (outlen < tag_len + (c+1) + datalen)
|
||||||
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
for (ii=0;ii<tag_len;ii++)
|
||||||
|
*p++ = tag_char[tag_len - ii - 1];
|
||||||
|
|
||||||
|
if (c > 0) {
|
||||||
|
*p++ = 0x80 | c;
|
||||||
|
while (c--)
|
||||||
|
*p++ = (datalen >> (c << 3)) & 0xFF;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*p++ = datalen & 0x7F;
|
||||||
|
}
|
||||||
|
if(data && datalen > 0) {
|
||||||
|
memcpy(p, data, datalen);
|
||||||
|
p += datalen;
|
||||||
|
}
|
||||||
if (ptr != NULL)
|
if (ptr != NULL)
|
||||||
*ptr = p;
|
*ptr = p;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -84,8 +84,10 @@ const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf,
|
||||||
/* DER encoding */
|
/* DER encoding */
|
||||||
|
|
||||||
/* Argument 'ptr' is set to the location of the next possible ASN.1 object.
|
/* Argument 'ptr' is set to the location of the next possible ASN.1 object.
|
||||||
* If NULL, no action on 'ptr' is performed. */
|
* If NULL, no action on 'ptr' is performed.
|
||||||
int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr);
|
* If out is NULL or outlen is zero, the length that would be written is returned.
|
||||||
|
* If data is NULL, the data field will not be written. This is helpful for constructed structures. */
|
||||||
|
int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr);
|
||||||
|
|
||||||
/* ASN.1 printing functions */
|
/* ASN.1 printing functions */
|
||||||
void sc_asn1_print_tags(const u8 * buf, size_t buflen);
|
void sc_asn1_print_tags(const u8 * buf, size_t buflen);
|
||||||
|
|
Loading…
Reference in New Issue