Разбор "ДРУГИХ" типов ASN.1 с OpenSSL 1.1 API - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь понять, как бороться с синтаксическим анализом типов ASN.1 с конкретным содержимым приложения. Учитывая довольно простую схему:

World-Schema DEFINITIONS AUTOMATIC TAGS ::= 
BEGIN
  Rocket ::= SEQUENCE       
  {                                                     
     name      IA5String,
     type      IA5String
  }                                                     
END

И данные:

value Rocket ::= {
  name "Falcon",
  type "Boo"
}

(я использую http://asn1 -playground.oss.com / для генерации сериализованных данных DER).

Я могу получить внешний контейнер с функцией d2i:

ASN1_SEQUENCE_ANY * container = d2i_ASN1_SEQUENCE_ANY(0, (const unsigned char**)&ptr, (long)len);
ASN1_TYPE * el = sk_ASN1_TYPE_value(container, 0);

То, что el имеет тип -3, это V_ASN1_OTHER, что правильно для моей схемы. Но я бьюсь головой о стену о том, как с помощью API ASN.1 углубиться в содержимое, которые являются IA5Strings. Я полагаю, что содержимое находится в el->value.asn1_value, но я не должен обращаться к нему напрямую (тип для меня непрозрачен), и я только рассматриваю функции, которые находятся в https://www.openssl.org/docs/man1.1.0/crypto/. Есть ли также какой-либо документ (ation), который объясняет, как это должно быть сделано?

1 Ответ

0 голосов
/ 11 сентября 2018

Документация OpenSSL довольно ограничена, когда речь идет о функциональности ASN.1. Лучший способ узнать об этом - просмотреть соответствующие заголовочные файлы asn1.h и asn1t.h, которые являются общедоступными. Они определяют набор макросов, которые позволяют вам создавать свои собственные типы ASN.1. Опять же, просмотр исходного кода - лучший способ понять, как они используются, например, в ts_asn1.c. Элементарное объяснение дано в ASN1_ITEM () . Веселитесь!

К счастью, ваш пример Rocket типа прост. Его определение типа ASN.1 с вспомогательными функциями может быть создано следующим образом:

/* Rocket.h */
#include <openssl/asn1.h>

typedef struct Rocket_st {
    ASN1_IA5STRING *name;
    ASN1_IA5STRING *type;
} ROCKET;

DECLARE_ASN1_FUNCTIONS(ROCKET)

Структура закодирована вручную, макрос DECLARE_ASN1_FUNCTIONS расширяется до набора вспомогательных функций, которые реализуются следующим образом:

/* Rocket.c */
#include "Rocket.h"
#include <openssl/asn1t.h>

ASN1_SEQUENCE(ROCKET) = {
        ASN1_SIMPLE(ROCKET, name, ASN1_IA5STRING),
        ASN1_SIMPLE(ROCKET, type, ASN1_IA5STRING),
} ASN1_SEQUENCE_END(ROCKET)

IMPLEMENT_ASN1_FUNCTIONS(ROCKET)

После компиляции таблица символов выглядит следующим образом (я использую Mac):

$ objdump -t Rocket.o

Rocket.o:   file format Mach-O 64-bit x86-64

SYMBOL TABLE:
00000000000000d0 l       __DATA,__const _ROCKET_seq_tt
00000000000000a0 g     F __TEXT,__text  _ROCKET_free
0000000000000120 g       __DATA,__const _ROCKET_it
0000000000000080 g     F __TEXT,__text  _ROCKET_new
0000000000000000 g     F __TEXT,__text  _d2i_ROCKET
0000000000000040 g     F __TEXT,__text  _i2d_ROCKET
0000000000000000         *UND*  _ASN1_IA5STRING_it
0000000000000000         *UND*  _ASN1_item_d2i
0000000000000000         *UND*  _ASN1_item_free
0000000000000000         *UND*  _ASN1_item_i2d
0000000000000000         *UND*  _ASN1_item_new

Неопределенные символы предоставляются библиотекой OpenSSL crypto. Вы можете использовать функции с ROCKET в их названии для преобразования туда и обратно между данными, структурированными в C и DER. Дополнительную информацию о функциях d2i и i2d можно найти на странице документации OpenSSL, которая называется d2i_X509. Код вашего приложения может выглядеть примерно так:

ROCKET *rocket;
ROCKET *rocket2;
unsigned char *rocketString;
const unsigned char *ptr;
int len;

rocket = ROCKET_new();
rocket->name = ASN1_IA5STRING_new();
ASN1_STRING_set(rocket->name, "Falcon", -1);
rocket->type = ASN1_IA5STRING_new();
ASN1_STRING_set(rocket->type, "Boo", -1);

len = i2d_ROCKET(rocket, &rocketString);
printf("DER-encoded Rocket has length %d\n", len);

ptr = rocketString;
rocket2 = d2i_ROCKET(NULL, &ptr, len);
printf("rocket2 fields are:\n  name = \"%s\"\n  type = \"%s\"\n",
   ASN1_STRING_get0_data(rocket2->name),
   ASN1_STRING_get0_data(rocket2->type));

Результат:

$ ./main
DER-encoded Rocket has length 15
rocket2 fields are:
  name = "Falcon"
  type = "Boo"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...