x509aux.c revision 1.1.1.1
1/* 2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL licenses, (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * https://www.openssl.org/source/license.html 8 * or in the file LICENSE in the source distribution. 9 */ 10 11#include <stdio.h> 12#include <string.h> 13#include <errno.h> 14 15#include <openssl/x509.h> 16#include <openssl/pem.h> 17#include <openssl/conf.h> 18#include <openssl/err.h> 19 20#include "../e_os.h" 21 22static const char *progname; 23 24static void test_usage(void) 25{ 26 fprintf(stderr, "usage: %s certfile\n", progname); 27} 28 29static void print_errors(void) 30{ 31 unsigned long err; 32 char buffer[1024]; 33 const char *file; 34 const char *data; 35 int line; 36 int flags; 37 38 while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) { 39 ERR_error_string_n(err, buffer, sizeof(buffer)); 40 if (flags & ERR_TXT_STRING) 41 fprintf(stderr, "Error: %s:%s:%d:%s\n", buffer, file, line, data); 42 else 43 fprintf(stderr, "Error: %s:%s:%d\n", buffer, file, line); 44 } 45} 46 47static int test_certs(BIO *fp) 48{ 49 int count; 50 char *name = 0; 51 char *header = 0; 52 unsigned char *data = 0; 53 long len; 54 typedef X509 *(*d2i_X509_t)(X509 **, const unsigned char **, long); 55 typedef int (*i2d_X509_t)(X509 *, unsigned char **); 56 int err = 0; 57 58 for (count = 0; 59 !err && PEM_read_bio(fp, &name, &header, &data, &len); 60 ++count) { 61 int trusted = strcmp(name, PEM_STRING_X509_TRUSTED) == 0; 62 d2i_X509_t d2i = trusted ? d2i_X509_AUX : d2i_X509; 63 i2d_X509_t i2d = trusted ? i2d_X509_AUX : i2d_X509; 64 X509 *cert = NULL; 65 const unsigned char *p = data; 66 unsigned char *buf = NULL; 67 unsigned char *bufp; 68 long enclen; 69 70 if (!trusted 71 && strcmp(name, PEM_STRING_X509) != 0 72 && strcmp(name, PEM_STRING_X509_OLD) != 0) { 73 fprintf(stderr, "unexpected PEM object: %s\n", name); 74 err = 1; 75 goto next; 76 } 77 cert = d2i(NULL, &p, len); 78 79 if (cert == NULL || (p - data) != len) { 80 fprintf(stderr, "error parsing input %s\n", name); 81 err = 1; 82 goto next; 83 } 84 85 /* Test traditional 2-pass encoding into caller allocated buffer */ 86 enclen = i2d(cert, NULL); 87 if (len != enclen) { 88 fprintf(stderr, "encoded length %ld of %s != input length %ld\n", 89 enclen, name, len); 90 err = 1; 91 goto next; 92 } 93 if ((buf = bufp = OPENSSL_malloc(len)) == NULL) { 94 perror("malloc"); 95 err = 1; 96 goto next; 97 } 98 enclen = i2d(cert, &bufp); 99 if (len != enclen) { 100 fprintf(stderr, "encoded length %ld of %s != input length %ld\n", 101 enclen, name, len); 102 err = 1; 103 goto next; 104 } 105 enclen = (long) (bufp - buf); 106 if (enclen != len) { 107 fprintf(stderr, "unexpected buffer position after encoding %s\n", 108 name); 109 err = 1; 110 goto next; 111 } 112 if (memcmp(buf, data, len) != 0) { 113 fprintf(stderr, "encoded content of %s does not match input\n", 114 name); 115 err = 1; 116 goto next; 117 } 118 OPENSSL_free(buf); 119 buf = NULL; 120 121 /* Test 1-pass encoding into library allocated buffer */ 122 enclen = i2d(cert, &buf); 123 if (len != enclen) { 124 fprintf(stderr, "encoded length %ld of %s != input length %ld\n", 125 enclen, name, len); 126 err = 1; 127 goto next; 128 } 129 if (memcmp(buf, data, len) != 0) { 130 fprintf(stderr, "encoded content of %s does not match input\n", 131 name); 132 err = 1; 133 goto next; 134 } 135 136 if (trusted) { 137 /* Encode just the cert and compare with initial encoding */ 138 OPENSSL_free(buf); 139 buf = NULL; 140 141 /* Test 1-pass encoding into library allocated buffer */ 142 enclen = i2d(cert, &buf); 143 if (enclen > len) { 144 fprintf(stderr, "encoded length %ld of %s > input length %ld\n", 145 enclen, name, len); 146 err = 1; 147 goto next; 148 } 149 if (memcmp(buf, data, enclen) != 0) { 150 fprintf(stderr, "encoded cert content does not match input\n"); 151 err = 1; 152 goto next; 153 } 154 } 155 156 /* 157 * If any of these were null, PEM_read() would have failed. 158 */ 159 next: 160 X509_free(cert); 161 OPENSSL_free(buf); 162 OPENSSL_free(name); 163 OPENSSL_free(header); 164 OPENSSL_free(data); 165 } 166 167 if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) { 168 /* Reached end of PEM file */ 169 if (count > 0) { 170 ERR_clear_error(); 171 return 1; 172 } 173 } 174 175 /* Some other PEM read error */ 176 print_errors(); 177 return 0; 178} 179 180int main(int argc, char *argv[]) 181{ 182 BIO *bio_err; 183 const char *p; 184 int ret = 1; 185 186 progname = argv[0]; 187 if (argc < 2) { 188 test_usage(); 189 EXIT(ret); 190 } 191 192 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); 193 194 p = getenv("OPENSSL_DEBUG_MEMORY"); 195 if (p != NULL && strcmp(p, "on") == 0) 196 CRYPTO_set_mem_debug(1); 197 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 198 199 argc--; 200 argv++; 201 202 while (argc >= 1) { 203 BIO *f = BIO_new_file(*argv, "r"); 204 int ok; 205 206 if (f == NULL) { 207 fprintf(stderr, "%s: Error opening cert file: '%s': %s\n", 208 progname, *argv, strerror(errno)); 209 EXIT(ret); 210 } 211 ret = !(ok = test_certs(f)); 212 BIO_free(f); 213 214 if (!ok) { 215 printf("%s ERROR\n", *argv); 216 ret = 1; 217 break; 218 } 219 printf("%s OK\n", *argv); 220 221 argc--; 222 argv++; 223 } 224 225#ifndef OPENSSL_NO_CRYPTO_MDEBUG 226 if (CRYPTO_mem_leaks(bio_err) <= 0) 227 ret = 1; 228#endif 229 BIO_free(bio_err); 230 EXIT(ret); 231} 232