54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#pragma ident "%Z%%M% %I% %E% SMI"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* ... copyright ... */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* Novell key-format scheme:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf KrbKeySet ::= SEQUENCE {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf attribute-major-vno [0] UInt16,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf attribute-minor-vno [1] UInt16,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf kvno [2] UInt32,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf mkvno [3] UInt32 OPTIONAL,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf keys [4] SEQUENCE OF KrbKey,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ...
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf KrbKey ::= SEQUENCE {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt [0] KrbSalt OPTIONAL,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key [1] EncryptionKey,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf s2kparams [2] OCTET STRING OPTIONAL,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ...
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf KrbSalt ::= SEQUENCE {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf type [0] Int32,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt [1] OCTET STRING OPTIONAL
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf EncryptionKey ::= SEQUENCE {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf keytype [0] Int32,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf keyvalue [1] OCTET STRING
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include <k5-int.h>
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include <kdb.h>
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include "krbasn1.h"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include "asn1_encode.h"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include "asn1_decode.h"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include "asn1_make.h"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#include "asn1_get.h"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#define asn1_encode_sequence_of_keys krb5int_ldap_encode_sequence_of_keys
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#define asn1_decode_sequence_of_keys krb5int_ldap_decode_sequence_of_keys
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#define cleanup(err) \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf { \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = err; \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf goto last; \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#define checkerr \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (ret != 0) \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf goto last
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/************************************************************************/
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* Encode the Principal's keys */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/************************************************************************/
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfstatic asn1_error_code
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfasn1_encode_key(asn1buf *buf,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_key_data key_data,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int *retlen)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int length, sum = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Encode the key type and value. */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int key_len = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* key value */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_octetstring (buf,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_data.key_data_length[0],
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_data.key_data_contents[0],
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* key type */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_integer (buf, key_data.key_data_type[0], &length);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_sequence(buf, key_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, key_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += key_len;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Encode the salt type and value (optional) */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (key_data.key_data_ver > 1) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int salt_len = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* salt value (optional) */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (key_data.key_data_length[1] > 0) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_octetstring (buf,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_data.key_data_length[1],
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key_data.key_data_contents[1],
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* salt type */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_integer (buf, key_data.key_data_type[1], &length);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_sequence(buf, salt_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, salt_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf salt_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += salt_len;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_sequence(buf, sum, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *retlen = sum;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* Major version and minor version are both '1' - first version */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* asn1_error_code asn1_encode_sequence_of_keys (krb5_key_data *key_data, */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfkrb5_error_code
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfasn1_encode_sequence_of_keys (krb5_key_data *key_data,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_int16 n_key_data,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_int32 mkvno, /* Master key version number */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_data **code)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf *buf = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int length, sum = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned long tmp_ul;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *code = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (n_key_data == 0) cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Allocate the buffer */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_create(&buf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Sequence of keys */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int i;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int seq_len = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf for (i = n_key_data - 1; i >= 0; i--) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_key (buf, key_data[i], &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf seq_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_sequence(buf, seq_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf seq_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 4, seq_len, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf seq_len += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += seq_len;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* mkvno */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (mkvno < 0)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_BAD_FORMAT);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf tmp_ul = (unsigned long)mkvno;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 3, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* kvno (assuming all keys in array have same version) */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (key_data[0].key_data_kvno < 0)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_BAD_FORMAT);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf tmp_ul = (unsigned long)key_data[0].key_data_kvno;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 2, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* attribute-minor-vno == 1 */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* attribute-major-vno == 1 */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_make_sequence(buf, sum, &length); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf sum += length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* The reverse encoding is straightened out here */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn12krb5_buf (buf, code); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf_destroy (&buf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (ret != 0 && *code != NULL) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if ((*code)->data != NULL)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free ((*code)->data);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free (*code);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/************************************************************************/
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* Decode the Principal's keys */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/************************************************************************/
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#define safe_syncbuf(outer,inner) \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (! ((inner)->next == (inner)->bound + 1 && \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf (inner)->next == (outer)->next + buflen)) \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_BAD_LENGTH); \
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfstatic asn1_error_code
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfdecode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf tmp, subbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf taginfo t;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Work on a copy of 'buf' */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum != expectedtag)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = t.length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_decode_integer(&subbuf, val); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf(&tmp, &subbuf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *buf = tmp;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#if 0 /* not currently used */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfstatic asn1_error_code
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfdecode_tagged_unsigned_integer (asn1buf *buf, int expectedtag, unsigned long *val)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf tmp, subbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf taginfo t;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Work on a copy of 'buf' */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum != expectedtag)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = t.length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_decode_unsigned_integer(&subbuf, val); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf(&tmp, &subbuf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *buf = tmp;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf#endif
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfstatic asn1_error_code
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfdecode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int *len, asn1_octet **val)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf tmp, subbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf taginfo t;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *val = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Work on a copy of 'buf' */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_tag_2(&tmp, &t); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum != expectedtag)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = t.length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_decode_octetstring (&subbuf, len, val); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf(&tmp, &subbuf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *buf = tmp;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (ret != 0 && *val != NULL)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free (*val);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfstatic asn1_error_code asn1_decode_key(asn1buf *buf, krb5_key_data *key)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen, seqindef;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf subbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf taginfo t;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_contents[0] = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_contents[1] = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_sequence(buf, &length, &seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_get_tag_2(&subbuf, &t);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Salt */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum == 0) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf slt;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned long keytype;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int keylen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_ver = 2;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_get_sequence(&subbuf, &length, &seqindef);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf_imbed(&slt, &subbuf, length, seqindef);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&slt, 0, (long *) &keytype);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_type[1] = keytype; /* XXX range check?? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (asn1buf_remains(&slt, 0) != 0) { /* Salt value is optional */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_octetstring (&slt, 1, &keylen,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf &key->key_data_contents[1]); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf (&subbuf, &slt);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_length[1] = keylen; /* XXX range check?? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_tag_2(&subbuf, &t); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf } else
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_ver = 1;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Key */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf kbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf long lval;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int ival;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum != 1)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&kbuf, &subbuf, length, seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&kbuf, 0, &lval);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_type[0] = lval; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_octetstring (&kbuf, 1, &ival,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf &key->key_data_contents[0]); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_length[0] = ival; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf (&subbuf, &kbuf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf (buf, &subbuf);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (ret != 0) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (key->key_data_contents[0] != NULL) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free (key->key_data_contents[0]);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_contents[0] = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (key->key_data_contents[1] != NULL) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free (key->key_data_contents[1]);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf key->key_data_contents[1] = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf/* asn1_error_code asn1_decode_sequence_of_keys (krb5_data *in, */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillfkrb5_error_code asn1_decode_sequence_of_keys (krb5_data *in,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_key_data **out,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_int16 *n_key_data,
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int *mkvno)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf{
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1_error_code ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf buf, subbuf;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int seqindef;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf unsigned int length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf taginfo t;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int kvno, maj, min;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf long lval;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *n_key_data = 0;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *out = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_wrap_data(&buf, in); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_sequence(&buf, &length, &seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&subbuf, &buf, length, seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* attribute-major-vno */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&subbuf, 0, &lval); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf maj = lval; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* attribute-minor-vno */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&subbuf, 1, &lval); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf min = lval; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (maj != 1 || min != 1)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_BAD_FORMAT);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* kvno (assuming all keys in array have same version) */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&subbuf, 2, &lval); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf kvno = lval; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* mkvno (optional) */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = decode_tagged_integer (&subbuf, 3, &lval); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *mkvno = lval; /* XXX range check? */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_tag_2(&subbuf, &t); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /* Sequence of keys */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int i, buflen;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf asn1buf keyseq;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (t.tagnum != 4)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ASN1_MISSING_FIELD);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf buflen = length;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1buf_imbed(&keyseq, &subbuf, length, seqindef); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf for (i = 1, *out = NULL; ; i++) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf krb5_key_data *tmp;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf tmp = (krb5_key_data *) realloc (*out, i * sizeof (krb5_key_data));
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (tmp == NULL)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf cleanup (ENOMEM);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *out = tmp;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf (*out)[i - 1].key_data_kvno = kvno;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf ret = asn1_decode_key(&keyseq, &(*out)[i - 1]); checkerr;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf (*n_key_data)++;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (asn1buf_remains(&keyseq, 0) == 0)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf break; /* Not freeing the last key structure */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf safe_syncbuf (&subbuf, &keyseq);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf /*
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf * There could be other data inside the outermost sequence ... tags we don't
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)"
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf */
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillflast:
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if (ret != 0) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf int i;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf for (i = 0; i < *n_key_data; i++) {
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if ((*out)[i].key_data_contents[0] != NULL)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free ((*out)[i].key_data_contents[0]);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf if ((*out)[i].key_data_contents[1] != NULL)
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free ((*out)[i].key_data_contents[1]);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf free (*out);
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf *out = NULL;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf }
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf return ret;
54925bf60766fbb4f1f2d7c843721406a7b7a3fbwillf}