1 /* 2 * Copyright (c) 2009-2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google, Inc. nor the names of its contributors 15 * may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 33 #include <openssl/pem.h> 34 #include <openssl/engine.h> 35 #include <openssl/x509.h> 36 #include <openssl/x509v3.h> 37 #include <openssl/pem.h> 38 #include <openssl/cms.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <unistd.h> 42 43 #include "secure.h" 44 #include "debug.h" 45 #include "utils.h" 46 47 48 void cert_init_crypto() { 49 CRYPTO_malloc_init(); 50 ERR_load_crypto_strings(); 51 OpenSSL_add_all_algorithms(); 52 ENGINE_load_builtin_engines(); 53 } 54 55 X509_STORE *cert_store_from_path(const char *path) { 56 57 X509_STORE *store; 58 struct stat st; 59 X509_LOOKUP *lookup; 60 61 if (stat(path, &st)) { 62 D(ERR, "Unable to stat cert path"); 63 goto error; 64 } 65 66 if (!(store = X509_STORE_new())) { 67 goto error; 68 } 69 70 if (S_ISDIR(st.st_mode)) { 71 lookup = X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); 72 if (lookup == NULL) 73 goto error; 74 if (!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) { 75 D(ERR, "Error loading cert directory %s", path); 76 goto error; 77 } 78 } 79 else if(S_ISREG(st.st_mode)) { 80 lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file()); 81 if (lookup == NULL) 82 goto error; 83 if (!X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM)) { 84 D(ERR, "Error loading cert directory %s", path); 85 goto error; 86 } 87 } 88 else { 89 D(ERR, "cert path is not directory or regular file"); 90 goto error; 91 } 92 93 return store; 94 95 error: 96 return NULL; 97 } 98 99 100 int cert_read(int fd, CMS_ContentInfo **content, BIO **output) { 101 BIO *input; 102 *output = NULL; 103 104 105 input = BIO_new_fd(fd, BIO_NOCLOSE); 106 if (input == NULL) { 107 D(ERR, "Unable to open input"); 108 goto error; 109 } 110 111 //TODO: 112 // read with d2i_CMS_bio to support DER 113 // with java or just encode data with base64 114 *content = SMIME_read_CMS(input, output); 115 if (*content == NULL) { 116 unsigned long err = ERR_peek_last_error(); 117 D(ERR, "Unable to parse input file: %s", ERR_lib_error_string(err)); 118 goto error_read; 119 } 120 121 BIO_free(input); 122 123 return 0; 124 125 error_read: 126 BIO_free(input); 127 error: 128 return 1; 129 } 130 131 int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd) { 132 BIO *output_temp; 133 int ret; 134 135 *out_fd = create_temp_file(); 136 if (*out_fd < 0) { 137 D(ERR, "unable to create temporary file"); 138 return -1; 139 } 140 141 output_temp = BIO_new_fd(*out_fd, BIO_NOCLOSE); 142 if (output_temp == NULL) { 143 D(ERR, "unable to create temporary bio"); 144 close(*out_fd); 145 return -1; 146 } 147 148 ret = CMS_verify(content_info, NULL ,store, content, output_temp, 0); 149 150 if (ret == 0) { 151 char buf[256]; 152 unsigned long err = ERR_peek_last_error(); 153 D(ERR, "Verification failed with reason: %s, %s", ERR_lib_error_string(err), ERR_error_string(err, buf)); 154 D(ERR, "Data used: content %p", content); 155 } 156 157 ERR_clear_error(); 158 ERR_remove_state(0); 159 160 BIO_free(output_temp); 161 162 return ret; 163 } 164 165 void cert_release(BIO *content, CMS_ContentInfo *info) { 166 BIO_free(content); 167 CMS_ContentInfo_free(info); 168 } 169 170