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 old_umask = umask(077); 75 if (stat(str1, &st) < 0) { 76 asprintf(&cmd, "openssl genrsa -out %s 2048", str1); 77 ecode = system(cmd); 78 free(cmd); 79 chmod(str1, 0400); 80 if (ecode) { 81 fprintf(stderr, 82 "hammer2 rsainit: private key gen failed\n"); 83 free(str2); 84 free(str1); 85 umask(old_umask); 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 umask(old_umask); 105 return 1; 106 } 107 printf("hammer2 rsainit: created %s\n", str2); 108 } else { 109 printf("hammer2 rsainit: both keys already exist\n"); 110 } 111 umask(old_umask); 112 free(str2); 113 free(str1); 114 115 return 0; 116 } 117 118 int 119 cmd_rsaenc(const char **keyfiles, int nkeys) 120 { 121 RSA **keys = calloc(nkeys, sizeof(RSA *)); 122 int *ispub = calloc(nkeys, sizeof(int)); 123 int ecode = 0; 124 int blksize = 0; 125 int i; 126 int off; 127 int n; 128 unsigned char *data_in; 129 unsigned char *data_out; 130 131 for (i = 0; i < nkeys; ++i) { 132 FILE *fp; 133 const char *sfx; 134 135 sfx = strrchr(keyfiles[i], '.'); 136 if (sfx && strcmp(sfx, ".pub") == 0) { 137 fp = fopen(keyfiles[i], "r"); 138 if (fp == NULL) { 139 fprintf(stderr, "hammer2 rsaenc: unable to " 140 "open %s\n", keyfiles[i]); 141 ecode = 1; 142 goto done; 143 } 144 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 145 ispub[i] = 1; 146 fclose(fp); 147 if (keys[i] == NULL) { 148 fprintf(stderr, "hammer2 rsaenc: unable to " 149 "parse public key from %s\n", 150 keyfiles[i]); 151 ecode = 1; 152 goto done; 153 } 154 } else if (sfx && strcmp(sfx, ".prv") == 0) { 155 fp = fopen(keyfiles[i], "r"); 156 if (fp == NULL) { 157 fprintf(stderr, "hammer2 rsaenc: unable to " 158 "open %s\n", keyfiles[i]); 159 ecode = 1; 160 goto done; 161 } 162 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 163 fclose(fp); 164 if (keys[i] == NULL) { 165 fprintf(stderr, "hammer2 rsaenc: unable to " 166 "parse private key from %s\n", 167 keyfiles[i]); 168 ecode = 1; 169 goto done; 170 } 171 } else { 172 fprintf(stderr, "hammer2: rsaenc: key files must end " 173 "in .pub or .prv\n"); 174 ecode = 1; 175 goto done; 176 } 177 if (i == 0) 178 blksize = RSA_size(keys[i]); 179 else 180 assert(blksize == RSA_size(keys[i])); 181 } 182 fprintf(stderr, "blksize %d\n", blksize); 183 184 /* 185 * 186 */ 187 data_in = malloc(blksize); 188 data_out = malloc(blksize); 189 off = 0; 190 while ((n = read(0, data_in + off, blksize - off)) > 0) { 191 off += n; 192 if (off == blksize) { 193 for (i = 0; i < nkeys; ++i) { 194 if (ispub[i]) 195 RSA_public_encrypt(blksize, 196 data_in, data_out, 197 keys[i], 198 RSA_NO_PADDING); 199 else 200 RSA_private_encrypt(blksize, 201 data_in, data_out, 202 keys[i], 203 RSA_NO_PADDING); 204 if (i + 1 != nkeys) 205 bcopy(data_out, data_in, blksize); 206 } 207 if (write(1, data_out, blksize) != blksize) { 208 perror("write"); 209 ecode = 1; 210 break; 211 } 212 off = 0; 213 } 214 } 215 if (off && ecode == 0) { 216 if (off < blksize) 217 bzero(data_in + off, blksize - off); 218 for (i = 0; i < nkeys; ++i) { 219 if (ispub[i]) 220 RSA_public_encrypt(blksize, 221 data_in, data_out, 222 keys[i], 223 RSA_NO_PADDING); 224 else 225 RSA_private_encrypt(blksize, 226 data_in, data_out, 227 keys[i], 228 RSA_NO_PADDING); 229 if (i + 1 != nkeys) 230 bcopy(data_out, data_in, blksize); 231 } 232 if (write(1, data_out, blksize) != blksize) { 233 perror("write"); 234 ecode = 1; 235 } 236 } 237 if (n < 0) { 238 perror("read"); 239 ecode = 1; 240 } 241 free(data_out); 242 free(data_in); 243 done: 244 for (i = 0; i < nkeys; ++i) { 245 if (keys[i]) 246 RSA_free(keys[i]); 247 } 248 free(keys); 249 free(ispub); 250 return (ecode); 251 } 252 253 int 254 cmd_rsadec(const char **keyfiles, int nkeys) 255 { 256 RSA **keys = calloc(nkeys, sizeof(RSA *)); 257 int *ispub = calloc(nkeys, sizeof(int)); 258 int ecode = 0; 259 int blksize = 0; 260 int i; 261 int off; 262 int n; 263 unsigned char *data_in; 264 unsigned char *data_out; 265 266 for (i = 0; i < nkeys; ++i) { 267 FILE *fp; 268 const char *sfx; 269 270 sfx = strrchr(keyfiles[i], '.'); 271 if (sfx && strcmp(sfx, ".pub") == 0) { 272 fp = fopen(keyfiles[i], "r"); 273 if (fp == NULL) { 274 fprintf(stderr, "hammer2 rsaenc: unable to " 275 "open %s\n", keyfiles[i]); 276 ecode = 1; 277 goto done; 278 } 279 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 280 ispub[i] = 1; 281 fclose(fp); 282 if (keys[i] == NULL) { 283 fprintf(stderr, "hammer2 rsaenc: unable to " 284 "parse public key from %s\n", 285 keyfiles[i]); 286 ecode = 1; 287 goto done; 288 } 289 } else if (sfx && strcmp(sfx, ".prv") == 0) { 290 fp = fopen(keyfiles[i], "r"); 291 if (fp == NULL) { 292 fprintf(stderr, "hammer2 rsaenc: unable to " 293 "open %s\n", keyfiles[i]); 294 ecode = 1; 295 goto done; 296 } 297 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 298 fclose(fp); 299 if (keys[i] == NULL) { 300 fprintf(stderr, "hammer2 rsaenc: unable to " 301 "parse private key from %s\n", 302 keyfiles[i]); 303 ecode = 1; 304 goto done; 305 } 306 } else { 307 fprintf(stderr, "hammer2: rsaenc: key files must end " 308 "in .pub or .prv\n"); 309 ecode = 1; 310 goto done; 311 } 312 if (i == 0) 313 blksize = RSA_size(keys[i]); 314 else 315 assert(blksize == RSA_size(keys[i])); 316 } 317 318 /* 319 * 320 */ 321 data_in = malloc(blksize); 322 data_out = malloc(blksize); 323 off = 0; 324 while ((n = read(0, data_in + off, blksize - off)) > 0) { 325 off += n; 326 if (off == blksize) { 327 for (i = 0; i < nkeys; ++i) { 328 if (ispub[i]) 329 RSA_public_decrypt(blksize, 330 data_in, data_out, 331 keys[i], 332 RSA_NO_PADDING); 333 else 334 RSA_private_decrypt(blksize, 335 data_in, data_out, 336 keys[i], 337 RSA_NO_PADDING); 338 if (i + 1 != nkeys) 339 bcopy(data_out, data_in, blksize); 340 } 341 if (write(1, data_out, blksize) != blksize) { 342 perror("write"); 343 ecode = 1; 344 break; 345 } 346 off = 0; 347 } 348 } 349 if (off) { 350 if (off < blksize) 351 bzero(data_in + off, blksize - off); 352 for (i = 0; i < nkeys; ++i) { 353 if (ispub[i]) 354 RSA_public_decrypt(blksize, 355 data_in, data_out, 356 keys[i], 357 RSA_NO_PADDING); 358 else 359 RSA_private_decrypt(blksize, 360 data_in, data_out, 361 keys[i], 362 RSA_NO_PADDING); 363 if (i + 1 != nkeys) 364 bcopy(data_out, data_in, blksize); 365 } 366 if (write(1, data_out, blksize) != blksize) { 367 perror("write"); 368 ecode = 1; 369 } 370 } 371 if (n < 0) { 372 perror("read"); 373 ecode = 1; 374 } 375 free(data_out); 376 free(data_in); 377 done: 378 for (i = 0; i < nkeys; ++i) { 379 if (keys[i]) 380 RSA_free(keys[i]); 381 } 382 free(keys); 383 free(ispub); 384 return (ecode); 385 } 386