2 * Copyright 2020 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 "internal/der.h"
14 #include "crypto/bn.h"
16 static int int_start_context(WPACKET
*pkt
, int tag
)
20 if (!ossl_assert(tag
<= 30))
22 return WPACKET_start_sub_packet(pkt
);
25 static int int_end_context(WPACKET
*pkt
, int tag
)
28 * If someone set the flag WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH on this
29 * sub-packet and this sub-packet has nothing written to it, the DER length
30 * will not be written, and the total written size will be unchanged before
31 * and after WPACKET_close(). We use size1 and size2 to determine if
32 * anything was written, and only write our tag if it has.
39 if (!ossl_assert(tag
<= 30))
42 /* Context specific are normally (?) constructed */
43 tag
|= DER_F_CONSTRUCTED
| DER_C_CONTEXT
;
45 return WPACKET_get_total_written(pkt
, &size1
)
47 && WPACKET_get_total_written(pkt
, &size2
)
48 && (size1
== size2
|| WPACKET_put_bytes_u8(pkt
, tag
));
51 int ossl_DER_w_precompiled(WPACKET
*pkt
, int tag
,
52 const unsigned char *precompiled
,
55 return int_start_context(pkt
, tag
)
56 && WPACKET_memcpy(pkt
, precompiled
, precompiled_n
)
57 && int_end_context(pkt
, tag
);
60 int ossl_DER_w_boolean(WPACKET
*pkt
, int tag
, int b
)
62 return int_start_context(pkt
, tag
)
63 && WPACKET_start_sub_packet(pkt
)
64 && (!b
|| WPACKET_put_bytes_u8(pkt
, 0xFF))
65 && !WPACKET_close(pkt
)
66 && !WPACKET_put_bytes_u8(pkt
, DER_P_BOOLEAN
)
67 && int_end_context(pkt
, tag
);
70 int ossl_DER_w_octet_string(WPACKET
*pkt
, int tag
,
71 const unsigned char *data
, size_t data_n
)
73 return int_start_context(pkt
, tag
)
74 && WPACKET_start_sub_packet(pkt
)
75 && WPACKET_memcpy(pkt
, data
, data_n
)
77 && WPACKET_put_bytes_u8(pkt
, DER_P_OCTET_STRING
)
78 && int_end_context(pkt
, tag
);
81 int ossl_DER_w_octet_string_uint32(WPACKET
*pkt
, int tag
, uint32_t value
)
83 unsigned char tmp
[4] = { 0, 0, 0, 0 };
84 unsigned char *pbuf
= tmp
+ (sizeof(tmp
) - 1);
87 *pbuf
-- = (value
& 0xFF);
90 return ossl_DER_w_octet_string(pkt
, tag
, tmp
, sizeof(tmp
));
93 static int int_der_w_integer(WPACKET
*pkt
, int tag
,
94 int (*put_bytes
)(WPACKET
*pkt
, const void *v
,
95 unsigned int *top_byte
),
98 unsigned int top_byte
= 0;
100 return int_start_context(pkt
, tag
)
101 && WPACKET_start_sub_packet(pkt
)
102 && put_bytes(pkt
, v
, &top_byte
)
103 && ((top_byte
& 0x80) == 0 || WPACKET_put_bytes_u8(pkt
, 0))
104 && WPACKET_close(pkt
)
105 && WPACKET_put_bytes_u8(pkt
, DER_P_INTEGER
)
106 && int_end_context(pkt
, tag
);
109 static int int_put_bytes_ulong(WPACKET
*pkt
, const void *v
,
110 unsigned int *top_byte
)
112 const unsigned long *value
= v
;
113 unsigned long tmp
= *value
;
118 *top_byte
= (tmp
& 0xFF);
124 return WPACKET_put_bytes__(pkt
, *value
, n
);
127 /* For integers, we only support unsigned values for now */
128 int ossl_DER_w_ulong(WPACKET
*pkt
, int tag
, unsigned long v
)
130 return int_der_w_integer(pkt
, tag
, int_put_bytes_ulong
, &v
);
133 static int int_put_bytes_bn(WPACKET
*pkt
, const void *v
,
134 unsigned int *top_byte
)
136 unsigned char *p
= NULL
;
137 size_t n
= BN_num_bytes(v
);
139 /* The BIGNUM limbs are in LE order */
141 ((bn_get_words(v
) [(n
- 1) / BN_BYTES
]) >> (8 * ((n
- 1) % BN_BYTES
)))
144 if (!WPACKET_allocate_bytes(pkt
, n
, &p
))
151 int ossl_DER_w_bn(WPACKET
*pkt
, int tag
, const BIGNUM
*v
)
153 if (v
== NULL
|| BN_is_negative(v
))
156 return ossl_DER_w_ulong(pkt
, tag
, 0);
158 return int_der_w_integer(pkt
, tag
, int_put_bytes_bn
, v
);
161 int ossl_DER_w_null(WPACKET
*pkt
, int tag
)
163 return int_start_context(pkt
, tag
)
164 && WPACKET_start_sub_packet(pkt
)
165 && WPACKET_close(pkt
)
166 && WPACKET_put_bytes_u8(pkt
, DER_P_NULL
)
167 && int_end_context(pkt
, tag
);
170 /* Constructed things need a start and an end */
171 int ossl_DER_w_begin_sequence(WPACKET
*pkt
, int tag
)
173 return int_start_context(pkt
, tag
)
174 && WPACKET_start_sub_packet(pkt
);
177 int ossl_DER_w_end_sequence(WPACKET
*pkt
, int tag
)
180 * If someone set the flag WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH on this
181 * sub-packet and this sub-packet has nothing written to it, the DER length
182 * will not be written, and the total written size will be unchanged before
183 * and after WPACKET_close(). We use size1 and size2 to determine if
184 * anything was written, and only write our tag if it has.
186 * Because we know that int_end_context() needs to do the same check,
187 * we reproduce this flag if the written length was unchanged, or we will
188 * have an erroneous context tag.
192 return WPACKET_get_total_written(pkt
, &size1
)
193 && WPACKET_close(pkt
)
194 && WPACKET_get_total_written(pkt
, &size2
)
196 ? WPACKET_set_flags(pkt
, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH
)
197 : WPACKET_put_bytes_u8(pkt
, DER_F_CONSTRUCTED
| DER_P_SEQUENCE
))
198 && int_end_context(pkt
, tag
);