asn_enc_rval_t BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_enc_rval_t erval; BOOLEAN_t *st = (BOOLEAN_t *)sptr; erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key); if(erval.encoded == -1) { erval.failed_type = td; erval.structure_ptr = sptr; return erval; } if(cb) { uint8_t bool_value; bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */ if(cb(&bool_value, 1, app_key) < 0) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = sptr; return erval; } } erval.encoded += 1; ASN__ENCODED_OK(erval); }
/* * Encode an always-primitive type using DER. */ asn_enc_rval_t der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_enc_rval_t erval; ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; ASN_DEBUG("%s %s as a primitive type (tm=%d)", cb?"Encoding":"Estimating", td->name, tag_mode); erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag, cb, app_key); ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded); if(erval.encoded == -1) { erval.failed_type = td; erval.structure_ptr = sptr; return erval; } if(cb && st->buf) { if(cb(st->buf, st->size, app_key) < 0) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = sptr; return erval; } } else { assert(st->buf || st->size == 0); } erval.encoded += st->size; _ASN_ENCODED_OK(erval); }
asn_enc_rval_t NULL_encode_der(asn_TYPE_descriptor_t *td, void *ptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_enc_rval_t erval; erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key); if(erval.encoded == -1) { erval.failed_type = td; erval.structure_ptr = ptr; } _ASN_ENCODED_OK(erval); }
/* * The DER encoder of the SET OF type. */ asn_enc_rval_t SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_TYPE_member_t *elm = td->elements; asn_TYPE_descriptor_t *elm_type = elm->type; der_type_encoder_f *der_encoder = elm_type->der_encoder; asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); size_t computed_size = 0; ssize_t encoding_size = 0; struct _el_buffer *encoded_els = NULL; ssize_t eels_count = 0; size_t max_encoded_len = 1; asn_enc_rval_t erval; int ret; int edx; ASN_DEBUG("Estimating size for SET OF %s", td->name); /* * Gather the length of the underlying members sequence. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; if(!memb_ptr) continue; erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); if(erval.encoded == -1) return erval; computed_size += erval.encoded; /* Compute maximum encoding's size */ if(max_encoded_len < (size_t)erval.encoded) max_encoded_len = erval.encoded; } /* * Encode the TLV for the sequence itself. */ encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); if(encoding_size == -1) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } computed_size += encoding_size; if(!cb || list->count == 0) { erval.encoded = computed_size; _ASN_ENCODED_OK(erval); } /* * DER mandates dynamic sorting of the SET OF elements * according to their encodings. Build an array of the * encoded elements. */ encoded_els = (struct _el_buffer *)MALLOC( list->count * sizeof(encoded_els[0])); if(encoded_els == NULL) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } ASN_DEBUG("Encoding members of %s SET OF", td->name); /* * Encode all members. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; struct _el_buffer *encoded_el = &encoded_els[eels_count]; if(!memb_ptr) continue; /* * Prepare space for encoding. */ encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); if(encoded_el->buf) { encoded_el->length = 0; encoded_el->size = max_encoded_len; } else { for(edx--; edx >= 0; edx--) /* coverity[uninit_use_in_call] Unused code TODO*/ FREEMEM(encoded_els[edx].buf); FREEMEM(encoded_els); erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } /* * Encode the member into the prepared space. */ erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, _el_addbytes, encoded_el); if(erval.encoded == -1) { for(; edx >= 0; edx--) FREEMEM(encoded_els[edx].buf); FREEMEM(encoded_els); return erval; } encoding_size += erval.encoded; eels_count++; } /* * Sort the encoded elements according to their encoding. */ qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); /* * Report encoded elements to the application. * Dispose of temporary sorted members table. */ ret = 0; for(edx = 0; edx < eels_count; edx++) { struct _el_buffer *encoded_el = &encoded_els[edx]; /* Report encoded chunks to the application */ if(ret == 0 && cb(encoded_el->buf, encoded_el->length, app_key) < 0) ret = -1; FREEMEM(encoded_el->buf); } FREEMEM(encoded_els); if(ret || computed_size != (size_t)encoding_size) { /* * Standard callback failed, or * encoded size is not equal to the computed size. */ erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; } else { erval.encoded = computed_size; } _ASN_ENCODED_OK(erval); }
/* * The DER encoder of the SEQUENCE type. */ asn_enc_rval_t SEQUENCE_encode_der(Allocator * allocator, asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { size_t computed_size = 0; asn_enc_rval_t erval; ssize_t ret; int edx; ASN_DEBUG("%s %s as SEQUENCE", cb?"Encoding":"Estimating", td->name); /* * Gather the length of the underlying members sequence. */ for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; if(elm->flags & ATF_POINTER) { memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; /* Mandatory element is missing */ _ASN_ENCODE_FAILED; } } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); } erval = elm->type->der_encoder(allocator, elm->type, memb_ptr, elm->tag_mode, elm->tag, 0, 0); if(erval.encoded == -1) return erval; computed_size += erval.encoded; ASN_DEBUG("Member %d %s estimated %ld bytes", edx, elm->name, (long)erval.encoded); } /* * Encode the TLV for the sequence itself. */ ret = der_write_tags(allocator, td, computed_size, tag_mode, 1, tag, cb, app_key); ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size); if(ret == -1) _ASN_ENCODE_FAILED; erval.encoded = computed_size + ret; if(!cb) _ASN_ENCODED_OK(erval); /* * Encode all members. */ for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm = &td->elements[edx]; asn_enc_rval_t tmperval; void *memb_ptr; if(elm->flags & ATF_POINTER) { memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) continue; } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); } tmperval = elm->type->der_encoder(allocator, elm->type, memb_ptr, elm->tag_mode, elm->tag, cb, app_key); if(tmperval.encoded == -1) return tmperval; computed_size -= tmperval.encoded; ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes", edx, elm->name, td->name, (long)tmperval.encoded); } if(computed_size != 0) /* * Encoded size is not equal to the computed size. */ _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(erval); }
/* * Encode OCTET STRING type using DER. */ asn_enc_rval_t OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_enc_rval_t er; asn_OCTET_STRING_specifics_t *specs = td->specifics ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; BIT_STRING_t *st = (BIT_STRING_t *)sptr; enum asn_OS_Subvariant type_variant = specs->subvariant; int fix_last_byte = 0; ASN_DEBUG("%s %s as OCTET STRING", cb?"Estimating":"Encoding", td->name); /* * Write tags. */ if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) { er.encoded = der_write_tags(td, (type_variant == ASN_OSUBV_BIT) + st->size, tag_mode, type_variant == ASN_OSUBV_ANY, tag, cb, app_key); if(er.encoded == -1) { er.failed_type = td; er.structure_ptr = sptr; return er; } } else { /* Disallow: [<tag>] IMPLICIT ANY */ assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1); er.encoded = 0; } if(!cb) { er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size; _ASN_ENCODED_OK(er); } /* * Prepare to deal with the last octet of BIT STRING. */ if(type_variant == ASN_OSUBV_BIT) { uint8_t b = st->bits_unused & 0x07; if(b && st->size) fix_last_byte = 1; _ASN_CALLBACK(&b, 1); er.encoded++; } /* Invoke callback for the main part of the buffer */ _ASN_CALLBACK(st->buf, st->size - fix_last_byte); /* The last octet should be stripped off the unused bits */ if(fix_last_byte) { uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused); _ASN_CALLBACK(&b, 1); } er.encoded += st->size; _ASN_ENCODED_OK(er); cb_failed: _ASN_ENCODE_FAILED; }
asn_enc_rval_t CHOICE_encode_der(Allocator * allocator, asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; asn_TYPE_member_t *elm; /* CHOICE element */ asn_enc_rval_t erval; void *memb_ptr; size_t computed_size = 0; int present; if(!sptr) _ASN_ENCODE_FAILED; ASN_DEBUG("%s %s as CHOICE", cb?"Encoding":"Estimating", td->name); present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size); /* * If the structure was not initialized, it cannot be encoded: * can't deduce what to encode in the choice type. */ if(present <= 0 || present > td->elements_count) { if(present == 0 && td->elements_count == 0) { /* The CHOICE is empty?! */ erval.encoded = 0; _ASN_ENCODED_OK(erval); } _ASN_ENCODE_FAILED; } /* * Seek over the present member of the structure. */ elm = &td->elements[present-1]; if(elm->flags & ATF_POINTER) { memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(memb_ptr == 0) { if(elm->optional) { erval.encoded = 0; _ASN_ENCODED_OK(erval); } /* Mandatory element absent */ _ASN_ENCODE_FAILED; } } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); } /* * If the CHOICE itself is tagged EXPLICIT: * T ::= [2] EXPLICIT CHOICE { ... } * Then emit the appropriate tags. */ if(tag_mode == 1 || td->tags_count) { /* * For this, we need to pre-compute the member. */ ssize_t ret; /* Encode member with its tag */ erval = elm->type->der_encoder(allocator, elm->type, memb_ptr, elm->tag_mode, elm->tag, 0, 0); if(erval.encoded == -1) return erval; /* Encode CHOICE with parent or my own tag */ ret = der_write_tags(allocator, td, erval.encoded, tag_mode, 1, tag, cb, app_key); if(ret == -1) _ASN_ENCODE_FAILED; computed_size += ret; } /* * Encode the single underlying member. */ erval = elm->type->der_encoder(allocator, elm->type, memb_ptr, elm->tag_mode, elm->tag, cb, app_key); if(erval.encoded == -1) return erval; ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)", (long)erval.encoded, (long)computed_size); erval.encoded += computed_size; return erval; }
/* * The DER encoder of the SEQUENCE OF type. */ asn_enc_rval_t SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_TYPE_member_t *elm = td->elements; asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr); size_t computed_size = 0; ssize_t encoding_size = 0; asn_enc_rval_t erval; int edx; ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name); /* * Gather the length of the underlying members sequence. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; if(!memb_ptr) continue; erval = elm->type->der_encoder(elm->type, memb_ptr, 0, elm->tag, 0, 0); if(erval.encoded == -1) return erval; computed_size += erval.encoded; } /* * Encode the TLV for the sequence itself. */ encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); if(encoding_size == -1) { erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; return erval; } computed_size += encoding_size; if(!cb) { erval.encoded = computed_size; _ASN_ENCODED_OK(erval); } ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name); /* * Encode all members. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; if(!memb_ptr) continue; erval = elm->type->der_encoder(elm->type, memb_ptr, 0, elm->tag, cb, app_key); if(erval.encoded == -1) return erval; encoding_size += erval.encoded; } if(computed_size != (size_t)encoding_size) { /* * Encoded size is not equal to the computed size. */ erval.encoded = -1; erval.failed_type = td; erval.structure_ptr = ptr; } else { erval.encoded = computed_size; erval.structure_ptr = 0; erval.failed_type = 0; } return erval; }
/* * The DER encoder of the SET OF type. */ asn_enc_rval_t SET_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { const asn_TYPE_member_t *elm = td->elements; const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); size_t computed_size = 0; ssize_t encoding_size = 0; struct _el_buffer *encoded_els; int edx; ASN_DEBUG("Estimating size for SET OF %s", td->name); /* * Gather the length of the underlying members sequence. */ for(edx = 0; edx < list->count; edx++) { void *memb_ptr = list->array[edx]; asn_enc_rval_t erval; if(!memb_ptr) ASN__ENCODE_FAILED; erval = elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag, 0, 0); if(erval.encoded == -1) return erval; computed_size += erval.encoded; } /* * Encode the TLV for the sequence itself. */ encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); if(encoding_size < 0) { ASN__ENCODE_FAILED; } computed_size += encoding_size; if(!cb || list->count == 0) { asn_enc_rval_t erval; erval.encoded = computed_size; ASN__ENCODED_OK(erval); } ASN_DEBUG("Encoding members of %s SET OF", td->name); /* * DER mandates dynamic sorting of the SET OF elements * according to their encodings. Build an array of the * encoded elements. */ encoded_els = SET_OF__encode_sorted(elm, list, SOES_DER); /* * Report encoded elements to the application. * Dispose of temporary sorted members table. */ for(edx = 0; edx < list->count; edx++) { struct _el_buffer *encoded_el = &encoded_els[edx]; /* Report encoded chunks to the application */ if(cb(encoded_el->buf, encoded_el->length, app_key) < 0) { break; } else { encoding_size += encoded_el->length; } } SET_OF__encode_sorted_free(encoded_els, list->count); if(edx == list->count) { asn_enc_rval_t erval; assert(computed_size == (size_t)encoding_size); erval.encoded = computed_size; ASN__ENCODED_OK(erval); } else { ASN__ENCODE_FAILED; } }