1 /* 2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@dragonflybsd.org> 6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hammer2.h" 37 38 #include <openssl/rsa.h> /* public/private key functions */ 39 #include <openssl/pem.h> /* public/private key file load */ 40 #include <openssl/err.h> 41 42 /* 43 * Should be run as root. Creates /etc/hammer2/rsa.{pub,prv} using 44 * an openssl command. 45 */ 46 int 47 cmd_rsainit(const char *dir_path) 48 { 49 struct stat st; 50 int ecode; 51 char *str1; 52 char *str2; 53 char *cmd; 54 mode_t old_umask; 55 56 /* 57 * Create the directory if necessary 58 */ 59 if (stat(dir_path, &st) < 0) { 60 str1 = strdup(dir_path); 61 str2 = str1 - 1; 62 63 while ((str2 = strchr(str2 + 1, '/')) != NULL) { 64 *str2 = 0; 65 mkdir(str1, 0755); 66 *str2 = '/'; 67 } 68 mkdir(str1, 0700); 69 free(str1); 70 } 71 asprintf(&str1, "%s/rsa.prv", dir_path); 72 asprintf(&str2, "%s/rsa.pub", dir_path); 73 74 if (stat(str1, &st) < 0) { 75 old_umask = umask(077); 76 asprintf(&cmd, "openssl genrsa -out %s 2048", str1); 77 umask(old_umask); 78 ecode = system(cmd); 79 free(cmd); 80 chmod(str1, 0400); 81 if (ecode) { 82 fprintf(stderr, 83 "hammer2 rsainit: private key gen failed\n"); 84 free(str2); 85 free(str1); 86 return 1; 87 } 88 printf("hammer2 rsainit: created %s\n", str1); 89 remove(str2); 90 } else { 91 printf("hammer2 rsainit: Using existing private key in %s\n", 92 str1); 93 } 94 if (stat(str2, &st) < 0) { 95 asprintf(&cmd, "openssl rsa -in %s -out %s -pubout", 96 str1, str2); 97 ecode = system(cmd); 98 free(cmd); 99 if (ecode) { 100 fprintf(stderr, 101 "hammer2 rsainit: public key gen failed\n"); 102 free(str2); 103 free(str1); 104 return 1; 105 } 106 printf("hammer2 rsainit: created %s\n", str2); 107 } else { 108 printf("hammer2 rsainit: both keys already exist\n"); 109 } 110 free(str2); 111 free(str1); 112 113 return 0; 114 } 115 116 int 117 cmd_rsaenc(const char **keyfiles, int nkeys) 118 { 119 RSA **keys = calloc(nkeys, sizeof(RSA *)); 120 int *ispub = calloc(nkeys, sizeof(int)); 121 int ecode = 0; 122 int blksize = 0; 123 int i; 124 int off; 125 int n; 126 unsigned char *data_in; 127 unsigned char *data_out; 128 129 for (i = 0; i < nkeys; ++i) { 130 FILE *fp; 131 const char *sfx; 132 133 sfx = strrchr(keyfiles[i], '.'); 134 if (sfx && strcmp(sfx, ".pub") == 0) { 135 fp = fopen(keyfiles[i], "r"); 136 if (fp == NULL) { 137 fprintf(stderr, "hammer2 rsaenc: unable to " 138 "open %s\n", keyfiles[i]); 139 ecode = 1; 140 goto done; 141 } 142 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 143 ispub[i] = 1; 144 fclose(fp); 145 if (keys[i] == NULL) { 146 fprintf(stderr, "hammer2 rsaenc: unable to " 147 "parse public key from %s\n", 148 keyfiles[i]); 149 ecode = 1; 150 goto done; 151 } 152 } else if (sfx && strcmp(sfx, ".prv") == 0) { 153 fp = fopen(keyfiles[i], "r"); 154 if (fp == NULL) { 155 fprintf(stderr, "hammer2 rsaenc: unable to " 156 "open %s\n", keyfiles[i]); 157 ecode = 1; 158 goto done; 159 } 160 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 161 fclose(fp); 162 if (keys[i] == NULL) { 163 fprintf(stderr, "hammer2 rsaenc: unable to " 164 "parse private key from %s\n", 165 keyfiles[i]); 166 ecode = 1; 167 goto done; 168 } 169 } else { 170 fprintf(stderr, "hammer2: rsaenc: key files must end " 171 "in .pub or .prv\n"); 172 ecode = 1; 173 goto done; 174 } 175 if (i == 0) 176 blksize = RSA_size(keys[i]); 177 else 178 assert(blksize == RSA_size(keys[i])); 179 } 180 fprintf(stderr, "blksize %d\n", blksize); 181 182 /* 183 * 184 */ 185 data_in = malloc(blksize); 186 data_out = malloc(blksize); 187 off = 0; 188 while ((n = read(0, data_in + off, blksize - off)) > 0) { 189 off += n; 190 if (off == blksize) { 191 for (i = 0; i < nkeys; ++i) { 192 if (ispub[i]) 193 RSA_public_encrypt(blksize, 194 data_in, data_out, 195 keys[i], 196 RSA_NO_PADDING); 197 else 198 RSA_private_encrypt(blksize, 199 data_in, data_out, 200 keys[i], 201 RSA_NO_PADDING); 202 if (i + 1 != nkeys) 203 bcopy(data_out, data_in, blksize); 204 } 205 if (write(1, data_out, blksize) != blksize) { 206 perror("write"); 207 ecode = 1; 208 break; 209 } 210 off = 0; 211 } 212 } 213 if (off && ecode == 0) { 214 if (off < blksize) 215 bzero(data_in + off, blksize - off); 216 for (i = 0; i < nkeys; ++i) { 217 if (ispub[i]) 218 RSA_public_encrypt(blksize, 219 data_in, data_out, 220 keys[i], 221 RSA_NO_PADDING); 222 else 223 RSA_private_encrypt(blksize, 224 data_in, data_out, 225 keys[i], 226 RSA_NO_PADDING); 227 if (i + 1 != nkeys) 228 bcopy(data_out, data_in, blksize); 229 } 230 if (write(1, data_out, blksize) != blksize) { 231 perror("write"); 232 ecode = 1; 233 } 234 } 235 if (n < 0) { 236 perror("read"); 237 ecode = 1; 238 } 239 free(data_out); 240 free(data_in); 241 done: 242 for (i = 0; i < nkeys; ++i) { 243 if (keys[i]) 244 RSA_free(keys[i]); 245 } 246 free(keys); 247 free(ispub); 248 return (ecode); 249 } 250 251 int 252 cmd_rsadec(const char **keyfiles, int nkeys) 253 { 254 RSA **keys = calloc(nkeys, sizeof(RSA *)); 255 int *ispub = calloc(nkeys, sizeof(int)); 256 int ecode = 0; 257 int blksize = 0; 258 int i; 259 int off; 260 int n; 261 unsigned char *data_in; 262 unsigned char *data_out; 263 264 for (i = 0; i < nkeys; ++i) { 265 FILE *fp; 266 const char *sfx; 267 268 sfx = strrchr(keyfiles[i], '.'); 269 if (sfx && strcmp(sfx, ".pub") == 0) { 270 fp = fopen(keyfiles[i], "r"); 271 if (fp == NULL) { 272 fprintf(stderr, "hammer2 rsaenc: unable to " 273 "open %s\n", keyfiles[i]); 274 ecode = 1; 275 goto done; 276 } 277 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 278 ispub[i] = 1; 279 fclose(fp); 280 if (keys[i] == NULL) { 281 fprintf(stderr, "hammer2 rsaenc: unable to " 282 "parse public key from %s\n", 283 keyfiles[i]); 284 ecode = 1; 285 goto done; 286 } 287 } else if (sfx && strcmp(sfx, ".prv") == 0) { 288 fp = fopen(keyfiles[i], "r"); 289 if (fp == NULL) { 290 fprintf(stderr, "hammer2 rsaenc: unable to " 291 "open %s\n", keyfiles[i]); 292 ecode = 1; 293 goto done; 294 } 295 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 296 fclose(fp); 297 if (keys[i] == NULL) { 298 fprintf(stderr, "hammer2 rsaenc: unable to " 299 "parse private key from %s\n", 300 keyfiles[i]); 301 ecode = 1; 302 goto done; 303 } 304 } else { 305 fprintf(stderr, "hammer2: rsaenc: key files must end " 306 "in .pub or .prv\n"); 307 ecode = 1; 308 goto done; 309 } 310 if (i == 0) 311 blksize = RSA_size(keys[i]); 312 else 313 assert(blksize == RSA_size(keys[i])); 314 } 315 316 /* 317 * 318 */ 319 data_in = malloc(blksize); 320 data_out = malloc(blksize); 321 off = 0; 322 while ((n = read(0, data_in + off, blksize - off)) > 0) { 323 off += n; 324 if (off == blksize) { 325 for (i = 0; i < nkeys; ++i) { 326 if (ispub[i]) 327 RSA_public_decrypt(blksize, 328 data_in, data_out, 329 keys[i], 330 RSA_NO_PADDING); 331 else 332 RSA_private_decrypt(blksize, 333 data_in, data_out, 334 keys[i], 335 RSA_NO_PADDING); 336 if (i + 1 != nkeys) 337 bcopy(data_out, data_in, blksize); 338 } 339 if (write(1, data_out, blksize) != blksize) { 340 perror("write"); 341 ecode = 1; 342 break; 343 } 344 off = 0; 345 } 346 } 347 if (off) { 348 if (off < blksize) 349 bzero(data_in + off, blksize - off); 350 for (i = 0; i < nkeys; ++i) { 351 if (ispub[i]) 352 RSA_public_decrypt(blksize, 353 data_in, data_out, 354 keys[i], 355 RSA_NO_PADDING); 356 else 357 RSA_private_decrypt(blksize, 358 data_in, data_out, 359 keys[i], 360 RSA_NO_PADDING); 361 if (i + 1 != nkeys) 362 bcopy(data_out, data_in, blksize); 363 } 364 if (write(1, data_out, blksize) != blksize) { 365 perror("write"); 366 ecode = 1; 367 } 368 } 369 if (n < 0) { 370 perror("read"); 371 ecode = 1; 372 } 373 free(data_out); 374 free(data_in); 375 done: 376 for (i = 0; i < nkeys; ++i) { 377 if (keys[i]) 378 RSA_free(keys[i]); 379 } 380 free(keys); 381 free(ispub); 382 return (ecode); 383 } 384