1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MAR_H__ 8 #define MAR_H__ 9 10 #include "mozilla/Assertions.h" 11 #include <stdint.h> 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 /* We have a MAX_SIGNATURES limit so that an invalid MAR will never 18 * waste too much of either updater's or signmar's time. 19 * It is also used at various places internally and will affect memory usage. 20 * If you want to increase this value above 9 then you need to adjust parsing 21 * code in tool/mar.c. 22 */ 23 #define MAX_SIGNATURES 8 24 #ifdef __cplusplus 25 static_assert(MAX_SIGNATURES <= 9, "too many signatures"); 26 #else 27 MOZ_STATIC_ASSERT(MAX_SIGNATURES <= 9, "too many signatures"); 28 #endif 29 30 struct ProductInformationBlock { 31 const char* MARChannelID; 32 const char* productVersion; 33 }; 34 35 /** 36 * The MAR item data structure. 37 */ 38 typedef struct MarItem_ { 39 struct MarItem_* next; /* private field */ 40 uint32_t offset; /* offset into archive */ 41 uint32_t length; /* length of data in bytes */ 42 uint32_t flags; /* contains file mode bits */ 43 char name[1]; /* file path */ 44 } MarItem; 45 46 /** 47 * File offset and length for tracking access of byte indexes 48 */ 49 typedef struct SeenIndex_ { 50 struct SeenIndex_* next; /* private field */ 51 uint32_t offset; /* offset into archive */ 52 uint32_t length; /* length of the data in bytes */ 53 } SeenIndex; 54 55 #define TABLESIZE 256 56 57 /** 58 * Mozilla ARchive (MAR) file data structure 59 */ 60 struct MarFile_ { 61 FILE* fp; /* file pointer to the archive */ 62 MarItem* item_table[TABLESIZE]; /* hash table of files in the archive */ 63 SeenIndex* index_list; /* file indexes processed */ 64 int item_table_is_valid; /* header and index validation flag */ 65 }; 66 67 typedef struct MarFile_ MarFile; 68 69 /** 70 * Signature of callback function passed to mar_enum_items. 71 * @param mar The MAR file being visited. 72 * @param item The MAR item being visited. 73 * @param data The data parameter passed by the caller of mar_enum_items. 74 * @return A non-zero value to stop enumerating. 75 */ 76 typedef int (*MarItemCallback)(MarFile* mar, const MarItem* item, void* data); 77 78 /** 79 * Open a MAR file for reading. 80 * @param path Specifies the path to the MAR file to open. This path must 81 * be compatible with fopen. 82 * @return NULL if an error occurs. 83 */ 84 MarFile* mar_open(const char* path); 85 86 #ifdef XP_WIN 87 MarFile* mar_wopen(const wchar_t* path); 88 #endif 89 90 /** 91 * Close a MAR file that was opened using mar_open. 92 * @param mar The MarFile object to close. 93 */ 94 void mar_close(MarFile* mar); 95 96 /** 97 * Find an item in the MAR file by name. 98 * @param mar The MarFile object to query. 99 * @param item The name of the item to query. 100 * @return A const reference to a MAR item or NULL if not found. 101 */ 102 const MarItem* mar_find_item(MarFile* mar, const char* item); 103 104 /** 105 * Enumerate all MAR items via callback function. 106 * @param mar The MAR file to enumerate. 107 * @param callback The function to call for each MAR item. 108 * @param data A caller specified value that is passed along to the 109 * callback function. 110 * @return 0 if the enumeration ran to completion. Otherwise, any 111 * non-zero return value from the callback is returned. 112 */ 113 int mar_enum_items(MarFile* mar, MarItemCallback callback, void* data); 114 115 /** 116 * Read from MAR item at given offset up to bufsize bytes. 117 * @param mar The MAR file to read. 118 * @param item The MAR item to read. 119 * @param offset The byte offset relative to the start of the item. 120 * @param buf A pointer to a buffer to copy the data into. 121 * @param bufsize The length of the buffer to copy the data into. 122 * @return The number of bytes written or a negative value if an 123 * error occurs. 124 */ 125 int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf, 126 int bufsize); 127 128 /** 129 * Create a MAR file from a set of files. 130 * @param dest The path to the file to create. This path must be 131 * compatible with fopen. 132 * @param numfiles The number of files to store in the archive. 133 * @param files The list of null-terminated file paths. Each file 134 * path must be compatible with fopen. 135 * @param infoBlock The information to store in the product information block. 136 * @return A non-zero value if an error occurs. 137 */ 138 int mar_create(const char* dest, int numfiles, char** files, 139 struct ProductInformationBlock* infoBlock); 140 141 /** 142 * Extract a MAR file to the current working directory. 143 * @param path The path to the MAR file to extract. This path must be 144 * compatible with fopen. 145 * @return A non-zero value if an error occurs. 146 */ 147 int mar_extract(const char* path); 148 149 #define MAR_MAX_CERT_SIZE (16 * 1024) // Way larger than necessary 150 151 /* Read the entire file (not a MAR file) into a newly-allocated buffer. 152 * This function does not write to stderr. Instead, the caller should 153 * write whatever error messages it sees fit. The caller must free the returned 154 * buffer using free(). 155 * 156 * @param filePath The path to the file that should be read. 157 * @param maxSize The maximum valid file size. 158 * @param data On success, *data will point to a newly-allocated buffer 159 * with the file's contents in it. 160 * @param size On success, *size will be the size of the created buffer. 161 * 162 * @return 0 on success, -1 on error 163 */ 164 int mar_read_entire_file(const char* filePath, uint32_t maxSize, 165 /*out*/ const uint8_t** data, 166 /*out*/ uint32_t* size); 167 168 /** 169 * Verifies a MAR file by verifying each signature with the corresponding 170 * certificate. That is, the first signature will be verified using the first 171 * certificate given, the second signature will be verified using the second 172 * certificate given, etc. The signature count must exactly match the number of 173 * certificates given, and all signature verifications must succeed. 174 * We do not check that the certificate was issued by any trusted authority. 175 * We assume it to be self-signed. We do not check whether the certificate 176 * is valid for this usage. 177 * 178 * @param mar The already opened MAR file. 179 * @param certData Pointer to the first element in an array of certificate 180 * file data. 181 * @param certDataSizes Pointer to the first element in an array for size of 182 * the cert data. 183 * @param certCount The number of elements in certData and certDataSizes 184 * @return 0 on success 185 * a negative number if there was an error 186 * a positive number if the signature does not verify 187 */ 188 int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData, 189 const uint32_t* certDataSizes, uint32_t certCount); 190 191 /** 192 * Reads the product info block from the MAR file's additional block section. 193 * The caller is responsible for freeing the fields in infoBlock 194 * if the return is successful. 195 * 196 * @param infoBlock Out parameter for where to store the result to 197 * @return 0 on success, -1 on failure 198 */ 199 int mar_read_product_info_block(MarFile* mar, 200 struct ProductInformationBlock* infoBlock); 201 202 #ifdef __cplusplus 203 } 204 #endif 205 206 #endif /* MAR_H__ */ 207