]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/asn1/asn1_lib.c
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #include "internal/cryptlib.h"
13 #include <openssl/asn1.h>
14 #include "asn1_local.h"
16 static int asn1_get_length(const unsigned char **pp
, int *inf
, long *rl
,
18 static void asn1_put_length(unsigned char **pp
, int length
);
20 static int _asn1_check_infinite_end(const unsigned char **p
, long len
)
23 * If there is 0 or 1 byte left, the length check should pick things up
28 if ((len
>= 2) && ((*p
)[0] == 0) && ((*p
)[1] == 0)) {
36 int ASN1_check_infinite_end(unsigned char **p
, long len
)
38 return _asn1_check_infinite_end((const unsigned char **)p
, len
);
41 int ASN1_const_check_infinite_end(const unsigned char **p
, long len
)
43 return _asn1_check_infinite_end(p
, len
);
46 int ASN1_get_object(const unsigned char **pp
, long *plength
, int *ptag
,
47 int *pclass
, long omax
)
51 const unsigned char *p
= *pp
;
57 ret
= (*p
& V_ASN1_CONSTRUCTED
);
58 xclass
= (*p
& V_ASN1_PRIVATE
);
59 i
= *p
& V_ASN1_PRIMITIVE_TAG
;
60 if (i
== V_ASN1_PRIMITIVE_TAG
) { /* high-tag */
70 if (len
> (INT_MAX
>> 7L))
86 if (!asn1_get_length(&p
, &inf
, plength
, max
))
89 if (inf
&& !(ret
& V_ASN1_CONSTRUCTED
))
92 if (*plength
> (omax
- (p
- *pp
))) {
93 ERR_raise(ERR_LIB_ASN1
, ASN1_R_TOO_LONG
);
95 * Set this so that even if things are not long enough the values are
103 ERR_raise(ERR_LIB_ASN1
, ASN1_R_HEADER_TOO_LONG
);
108 * Decode a length field.
109 * The short form is a single byte defining a length 0 - 127.
110 * The long form is a byte 0 - 127 with the top bit set and this indicates
111 * the number of following octets that contain the length. These octets
112 * are stored most significant digit first.
114 static int asn1_get_length(const unsigned char **pp
, int *inf
, long *rl
,
117 const unsigned char *p
= *pp
;
118 unsigned long ret
= 0;
132 /* Skip leading zeroes */
133 while (i
> 0 && *p
== 0) {
137 if (i
> (int)sizeof(long))
156 * class 0 is constructed constructed == 2 for indefinite length constructed
158 void ASN1_put_object(unsigned char **pp
, int constructed
, int length
, int tag
,
161 unsigned char *p
= *pp
;
164 i
= (constructed
) ? V_ASN1_CONSTRUCTED
: 0;
165 i
|= (xclass
& V_ASN1_PRIVATE
);
167 *(p
++) = i
| (tag
& V_ASN1_PRIMITIVE_TAG
);
169 *(p
++) = i
| V_ASN1_PRIMITIVE_TAG
;
170 for (i
= 0, ttag
= tag
; ttag
> 0; i
++)
181 if (constructed
== 2)
184 asn1_put_length(&p
, length
);
188 int ASN1_put_eoc(unsigned char **pp
)
190 unsigned char *p
= *pp
;
198 static void asn1_put_length(unsigned char **pp
, int length
)
200 unsigned char *p
= *pp
;
204 *(p
++) = (unsigned char)length
;
207 for (i
= 0; len
> 0; i
++)
212 p
[i
] = length
& 0xff;
220 int ASN1_object_size(int constructed
, int length
, int tag
)
232 if (constructed
== 2) {
244 if (ret
>= INT_MAX
- length
)
249 int ASN1_STRING_copy(ASN1_STRING
*dst
, const ASN1_STRING
*str
)
253 dst
->type
= str
->type
;
254 if (!ASN1_STRING_set(dst
, str
->data
, str
->length
))
256 /* Copy flags but preserve embed value */
257 dst
->flags
&= ASN1_STRING_FLAG_EMBED
;
258 dst
->flags
|= str
->flags
& ~ASN1_STRING_FLAG_EMBED
;
262 ASN1_STRING
*ASN1_STRING_dup(const ASN1_STRING
*str
)
268 ret
= ASN1_STRING_new();
271 if (!ASN1_STRING_copy(ret
, str
)) {
272 ASN1_STRING_free(ret
);
278 int ASN1_STRING_set(ASN1_STRING
*str
, const void *_data
, int len_in
)
281 const char *data
= _data
;
289 len
= (size_t)len_in
;
292 * Verify that the length fits within an integer for assignment to
293 * str->length below. The additional 1 is subtracted to allow for the
294 * '\0' terminator even though this isn't strictly necessary.
296 if (len
> INT_MAX
- 1) {
297 ERR_raise(ERR_LIB_ASN1
, ASN1_R_TOO_LARGE
);
300 if ((size_t)str
->length
<= len
|| str
->data
== NULL
) {
302 str
->data
= OPENSSL_realloc(c
, len
+ 1);
303 if (str
->data
== NULL
) {
304 ERR_raise(ERR_LIB_ASN1
, ERR_R_MALLOC_FAILURE
);
311 memcpy(str
->data
, data
, len
);
312 /* an allowance for strings :-) */
313 str
->data
[len
] = '\0';
318 void ASN1_STRING_set0(ASN1_STRING
*str
, void *data
, int len
)
320 OPENSSL_free(str
->data
);
325 ASN1_STRING
*ASN1_STRING_new(void)
327 return ASN1_STRING_type_new(V_ASN1_OCTET_STRING
);
330 ASN1_STRING
*ASN1_STRING_type_new(int type
)
334 ret
= OPENSSL_zalloc(sizeof(*ret
));
336 ERR_raise(ERR_LIB_ASN1
, ERR_R_MALLOC_FAILURE
);
343 void ossl_asn1_string_embed_free(ASN1_STRING
*a
, int embed
)
347 if (!(a
->flags
& ASN1_STRING_FLAG_NDEF
))
348 OPENSSL_free(a
->data
);
353 void ASN1_STRING_free(ASN1_STRING
*a
)
357 ossl_asn1_string_embed_free(a
, a
->flags
& ASN1_STRING_FLAG_EMBED
);
360 void ASN1_STRING_clear_free(ASN1_STRING
*a
)
364 if (a
->data
&& !(a
->flags
& ASN1_STRING_FLAG_NDEF
))
365 OPENSSL_cleanse(a
->data
, a
->length
);
369 int ASN1_STRING_cmp(const ASN1_STRING
*a
, const ASN1_STRING
*b
)
373 i
= (a
->length
- b
->length
);
375 i
= memcmp(a
->data
, b
->data
, a
->length
);
377 return a
->type
- b
->type
;
385 int ASN1_STRING_length(const ASN1_STRING
*x
)
390 #ifndef OPENSSL_NO_DEPRECATED_3_0
391 void ASN1_STRING_length_set(ASN1_STRING
*x
, int len
)
397 int ASN1_STRING_type(const ASN1_STRING
*x
)
402 const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING
*x
)
407 #ifndef OPENSSL_NO_DEPRECATED_1_1_0
408 unsigned char *ASN1_STRING_data(ASN1_STRING
*x
)
414 char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING
) *text
,
416 size_t max_len
/* excluding NUL terminator */)
419 ASN1_UTF8STRING
*current
;
420 size_t length
= 0, sep_len
;
424 if (!ossl_assert(sep
!= NULL
))
426 sep_len
= strlen(sep
);
428 for (i
= 0; i
< sk_ASN1_UTF8STRING_num(text
); ++i
) {
429 current
= sk_ASN1_UTF8STRING_value(text
, i
);
432 length
+= ASN1_STRING_length(current
);
433 if (length
> max_len
)
436 if ((result
= OPENSSL_malloc(length
+ 1)) == NULL
)
439 for (i
= 0, p
= result
; i
< sk_ASN1_UTF8STRING_num(text
); ++i
) {
440 current
= sk_ASN1_UTF8STRING_value(text
, i
);
441 length
= ASN1_STRING_length(current
);
442 if (i
> 0 && sep_len
> 0) {
443 strncpy(p
, sep
, sep_len
+ 1);
446 strncpy(p
, (const char *)ASN1_STRING_get0_data(current
), length
);