1/*
2 * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10/* Internal tests for the asn1 module */
11
12/*
13 * RSA low level APIs are deprecated for public use, but still ok for
14 * internal use.
15 */
16#include "internal/deprecated.h"
17
18#include <stdio.h>
19#include <string.h>
20
21#include <openssl/asn1.h>
22#include <openssl/evp.h>
23#include <openssl/objects.h>
24#include "testutil.h"
25#include "internal/nelem.h"
26
27/**********************************************************************
28 *
29 * Test of a_strnid's tbl_standard
30 *
31 ***/
32
33#include "../crypto/asn1/tbl_standard.h"
34
35static int test_tbl_standard(void)
36{
37    const ASN1_STRING_TABLE *tmp;
38    int last_nid = -1;
39    size_t i;
40
41    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) {
42        if (tmp->nid < last_nid) {
43            last_nid = 0;
44            break;
45        }
46        last_nid = tmp->nid;
47    }
48
49    if (TEST_int_ne(last_nid, 0)) {
50        TEST_info("asn1 tbl_standard: Table order OK");
51        return 1;
52    }
53
54    TEST_info("asn1 tbl_standard: out of order");
55    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++)
56        TEST_note("asn1 tbl_standard: Index %zu, NID %d, Name=%s",
57                  i, tmp->nid, OBJ_nid2ln(tmp->nid));
58
59    return 0;
60}
61
62/**********************************************************************
63 *
64 * Test of ameth_lib's standard_methods
65 *
66 ***/
67
68#include "crypto/asn1.h"
69#include "../crypto/asn1/standard_methods.h"
70
71static int test_standard_methods(void)
72{
73    const EVP_PKEY_ASN1_METHOD **tmp;
74    int last_pkey_id = -1;
75    size_t i;
76    int ok = 1;
77
78    for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods);
79         i++, tmp++) {
80        if ((*tmp)->pkey_id < last_pkey_id) {
81            last_pkey_id = 0;
82            break;
83        }
84        last_pkey_id = (*tmp)->pkey_id;
85
86        /*
87         * One of the following must be true:
88         *
89         * pem_str == NULL AND ASN1_PKEY_ALIAS is set
90         * pem_str != NULL AND ASN1_PKEY_ALIAS is clear
91         *
92         * Anything else is an error and may lead to a corrupt ASN1 method table
93         */
94        if (!TEST_true(((*tmp)->pem_str == NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) != 0)
95                       || ((*tmp)->pem_str != NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
96            TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s",
97                      i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id));
98            ok = 0;
99        }
100    }
101
102    if (TEST_int_ne(last_pkey_id, 0)) {
103        TEST_info("asn1 standard methods: Table order OK");
104        return ok;
105    }
106
107    TEST_note("asn1 standard methods: out of order");
108    for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods);
109         i++, tmp++)
110        TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s",
111                  i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id));
112
113    return 0;
114}
115
116/**********************************************************************
117 *
118 * Test of that i2d fail on non-existing non-optional items
119 *
120 ***/
121
122#include <openssl/rsa.h>
123
124static int test_empty_nonoptional_content(void)
125{
126    RSA *rsa = NULL;
127    BIGNUM *n = NULL;
128    BIGNUM *e = NULL;
129    int ok = 0;
130
131    if (!TEST_ptr(rsa = RSA_new())
132        || !TEST_ptr(n = BN_new())
133        || !TEST_ptr(e = BN_new())
134        || !TEST_true(RSA_set0_key(rsa, n, e, NULL)))
135        goto end;
136
137    n = e = NULL;                /* They are now "owned" by |rsa| */
138
139    /*
140     * This SHOULD fail, as we're trying to encode a public key as a private
141     * key.  The private key bits MUST be present for a proper RSAPrivateKey.
142     */
143    if (TEST_int_le(i2d_RSAPrivateKey(rsa, NULL), 0))
144        ok = 1;
145
146 end:
147    RSA_free(rsa);
148    BN_free(n);
149    BN_free(e);
150    return ok;
151}
152
153/**********************************************************************
154 *
155 * Tests of the Unicode code point range
156 *
157 ***/
158
159static int test_unicode(const unsigned char *univ, size_t len, int expected)
160{
161    const unsigned char *end = univ + len;
162    int ok = 1;
163
164    for (; univ < end; univ += 4) {
165        if (!TEST_int_eq(ASN1_mbstring_copy(NULL, univ, 4, MBSTRING_UNIV,
166                                            B_ASN1_UTF8STRING),
167                         expected))
168            ok = 0;
169    }
170    return ok;
171}
172
173static int test_unicode_range(void)
174{
175    const unsigned char univ_ok[] = "\0\0\0\0"
176                                    "\0\0\xd7\xff"
177                                    "\0\0\xe0\x00"
178                                    "\0\x10\xff\xff";
179    const unsigned char univ_bad[] = "\0\0\xd8\x00"
180                                     "\0\0\xdf\xff"
181                                     "\0\x11\x00\x00"
182                                     "\x80\x00\x00\x00"
183                                     "\xff\xff\xff\xff";
184    int ok = 1;
185
186    if (!test_unicode(univ_ok, sizeof univ_ok - 1, V_ASN1_UTF8STRING))
187        ok = 0;
188    if (!test_unicode(univ_bad, sizeof univ_bad - 1, -1))
189        ok = 0;
190    return ok;
191}
192
193int setup_tests(void)
194{
195    ADD_TEST(test_tbl_standard);
196    ADD_TEST(test_standard_methods);
197    ADD_TEST(test_empty_nonoptional_content);
198    ADD_TEST(test_unicode_range);
199    return 1;
200}
201