1 1.1 christos /* 2 1.1 christos * Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos #include <assert.h> 10 1.1 christos #include <errno.h> 11 1.1 christos #include <stdio.h> 12 1.1 christos #include <string.h> 13 1.1 christos #include <ctype.h> 14 1.1 christos 15 1.1 christos #include "internal/nelem.h" 16 1.1 christos #include "../testutil.h" 17 1.1 christos #include "tu_local.h" 18 1.1 christos 19 1.1 christos int test_start_file(STANZA *s, const char *testfile) 20 1.1 christos { 21 1.1 christos TEST_info("Reading %s", testfile); 22 1.1 christos set_test_title(testfile); 23 1.1 christos memset(s, 0, sizeof(*s)); 24 1.1 christos if (!TEST_ptr(s->fp = BIO_new_file(testfile, "r"))) 25 1.1 christos return 0; 26 1.1 christos s->test_file = testfile; 27 1.1 christos return 1; 28 1.1 christos } 29 1.1 christos 30 1.1 christos int test_end_file(STANZA *s) 31 1.1 christos { 32 1.1 christos TEST_info("Completed %d tests with %d errors and %d skipped", 33 1.1.1.2 christos s->numtests, s->errors, s->numskip); 34 1.1 christos BIO_free(s->fp); 35 1.1 christos return 1; 36 1.1 christos } 37 1.1 christos 38 1.1 christos /* 39 1.1 christos * Read a PEM block. Return 1 if okay, 0 on error. 40 1.1 christos */ 41 1.1 christos static int read_key(STANZA *s) 42 1.1 christos { 43 1.1 christos char tmpbuf[128]; 44 1.1 christos 45 1.1 christos if (s->key == NULL) { 46 1.1 christos if (!TEST_ptr(s->key = BIO_new(BIO_s_mem()))) 47 1.1 christos return 0; 48 1.1 christos } else if (!TEST_int_gt(BIO_reset(s->key), 0)) { 49 1.1 christos return 0; 50 1.1 christos } 51 1.1 christos 52 1.1 christos /* Read to PEM end line and place content in memory BIO */ 53 1.1 christos while (BIO_gets(s->fp, tmpbuf, sizeof(tmpbuf))) { 54 1.1 christos s->curr++; 55 1.1 christos if (!TEST_int_gt(BIO_puts(s->key, tmpbuf), 0)) 56 1.1 christos return 0; 57 1.1 christos if (HAS_PREFIX(tmpbuf, "-----END")) 58 1.1 christos return 1; 59 1.1 christos } 60 1.1 christos TEST_error("Can't find key end"); 61 1.1 christos return 0; 62 1.1 christos } 63 1.1 christos 64 1.1 christos /* 65 1.1 christos * Delete leading and trailing spaces from a string 66 1.1 christos */ 67 1.1 christos static char *strip_spaces(char *p) 68 1.1 christos { 69 1.1 christos char *q; 70 1.1 christos 71 1.1 christos /* Skip over leading spaces */ 72 1.1 christos while (*p && isspace((unsigned char)*p)) 73 1.1 christos p++; 74 1.1 christos if (*p == '\0') 75 1.1 christos return NULL; 76 1.1 christos 77 1.1.1.2 christos for (q = p + strlen(p) - 1; q != p && isspace((unsigned char)*q);) 78 1.1 christos *q-- = '\0'; 79 1.1 christos return *p ? p : NULL; 80 1.1 christos } 81 1.1 christos 82 1.1 christos /* 83 1.1 christos * Read next test stanza; return 1 if found, 0 on EOF or error. 84 1.1 christos */ 85 1.1 christos int test_readstanza(STANZA *s) 86 1.1 christos { 87 1.1 christos PAIR *pp = s->pairs; 88 1.1 christos char *p, *equals, *key; 89 1.1 christos const char *value; 90 1.1 christos static char buff[131072]; 91 1.1 christos 92 1.1.1.2 christos for (s->numpairs = 0; BIO_gets(s->fp, buff, sizeof(buff));) { 93 1.1 christos s->curr++; 94 1.1 christos if (!TEST_ptr(p = strchr(buff, '\n'))) { 95 1.1 christos TEST_info("Line %d too long", s->curr); 96 1.1 christos return 0; 97 1.1 christos } 98 1.1 christos *p = '\0'; 99 1.1 christos 100 1.1 christos /* Blank line marks end of tests. */ 101 1.1 christos if (buff[0] == '\0') 102 1.1 christos break; 103 1.1 christos 104 1.1 christos /* Lines starting with a pound sign are ignored. */ 105 1.1 christos if (buff[0] == '#') 106 1.1 christos continue; 107 1.1 christos 108 1.1 christos /* Parse into key=value */ 109 1.1 christos if (!TEST_ptr(equals = strchr(buff, '='))) { 110 1.1 christos TEST_info("Missing = at line %d\n", s->curr); 111 1.1 christos return 0; 112 1.1 christos } 113 1.1 christos *equals++ = '\0'; 114 1.1 christos if (!TEST_ptr(key = strip_spaces(buff))) { 115 1.1 christos TEST_info("Empty field at line %d\n", s->curr); 116 1.1 christos return 0; 117 1.1 christos } 118 1.1 christos if ((value = strip_spaces(equals)) == NULL) 119 1.1 christos value = ""; 120 1.1 christos 121 1.1 christos if (strcmp(key, "Title") == 0) { 122 1.1 christos TEST_info("Starting \"%s\" tests at line %d", value, s->curr); 123 1.1 christos continue; 124 1.1 christos } 125 1.1 christos 126 1.1 christos if (s->numpairs == 0) 127 1.1 christos s->start = s->curr; 128 1.1 christos 129 1.1 christos if (strcmp(key, "PrivateKey") == 0 130 1.1.1.2 christos || strcmp(key, "PublicKey") == 0 131 1.1.1.2 christos || strcmp(key, "ParamKey") == 0) { 132 1.1 christos if (!read_key(s)) 133 1.1 christos return 0; 134 1.1 christos } 135 1.1 christos 136 1.1 christos if (!TEST_int_lt(s->numpairs++, TESTMAXPAIRS) 137 1.1.1.2 christos || !TEST_ptr(pp->key = OPENSSL_strdup(key)) 138 1.1.1.2 christos || !TEST_ptr(pp->value = OPENSSL_strdup(value))) 139 1.1 christos return 0; 140 1.1 christos pp++; 141 1.1 christos } 142 1.1 christos 143 1.1 christos /* If we read anything, return ok. */ 144 1.1 christos return 1; 145 1.1 christos } 146 1.1 christos 147 1.1 christos void test_clearstanza(STANZA *s) 148 1.1 christos { 149 1.1 christos PAIR *pp = s->pairs; 150 1.1 christos int i = s->numpairs; 151 1.1 christos 152 1.1.1.2 christos for (; --i >= 0; pp++) { 153 1.1 christos OPENSSL_free(pp->key); 154 1.1 christos OPENSSL_free(pp->value); 155 1.1 christos } 156 1.1 christos s->numpairs = 0; 157 1.1 christos } 158