├── Makefile ├── README.md ├── apcheader.c ├── examples ├── README.md ├── apc-secwiz-104-ca-1024.crt ├── apc-secwiz-104-ca-1024.p15 ├── apc-secwiz-104-ca-2048.crt ├── apc-secwiz-104-ca-2048.p15 ├── apc-secwiz-104-server-1024.p15 └── apc-secwiz-104-server-2048.p15 ├── p15dump.c ├── pemtrans.1 └── pemtrans.c /Makefile: -------------------------------------------------------------------------------- 1 | ## Tell the compiler where to find and 2 | #INCLUDES = -I/usr/local/openssl/include -I/usr/local/include 3 | 4 | ## Tell the compiler where to find the OpenSSL libraries. 5 | #LIBS = -L/usr/local/openssl/lib 6 | 7 | ## Where is libcl.a? 8 | #CRYPTLIB = /usr/local/lib/libcl.a 9 | 10 | ## Cryptlib is usually linked with these libraries: 11 | EXTRA_LIBS = -lresolv -lpthread 12 | 13 | ## Remember to change theese to suit your environment!! 14 | INCLUDES = -I/usr/local/include/libcl 15 | CRYPTLIB = /usr/local/lib/libcl.a 16 | 17 | pemtrans: pemtrans.c 18 | cc $(INCLUDES) $(LIBS) -o pemtrans pemtrans.c $(CRYPTLIB) \ 19 | -lcrypto -lssl $(EXTRA_LIBS) 20 | 21 | p15dump: p15dump.c 22 | cc $(INCLUDES) $(LIBS) -o p15dump p15dump.c $(CRYPTLIB) \ 23 | $(EXTRA_LIBS) 24 | 25 | apcheader: apcheader.c 26 | cc -o apcheader apcheader.c 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | APC tools 3 | ============ 4 | 5 | This project is unmaintained. 6 | Please have a look at [apc-p15-tool](https://github.com/gregtwallace/apc-p15-tool) for a better alternative. 7 | 8 | 9 | The target of this project is to provide a CLI alternative for the APC/Schneider Electric Security Wizard. 10 | 11 | The project started with a fork of the [pemtrans project form Abhijit Menon-Sen](https://github.com/amenonsen/pemtrans). 12 | pemtrans is essentially exactly what we need but the result doesn't work yet with APC devices. 13 | 14 | ## APC specific details 15 | * APC uses [cryptlib](http://www.cryptlib.com/) as crypto lib. 16 | * At the time of this writing the latest version (1.04) of the APC Security Wizard is using an ancient version of cryptlib (version 3.1.1). 17 | * It seems like there are some compatibility issues between files created by different versions of cryptlib. 18 | * The "CA Root certificate" files generated by the Security Wizard are unmodified p15 files. 19 | * The key label is "Private key" and the password is "root". 20 | * The final files for the devices generated by the "SSL Server Certificate"/"Import Signed Certificate" options are p15 files with an additional APC Header. 21 | * The header is always 228 bytes long (See [apcheader.c](apcheader.c) for details). 22 | * The remaining data of the file is the p15 files generated by cryptlib. 23 | * The key label is "Private key" and the password is "user". 24 | 25 | ## Usage 26 | * Remove APC header from server certificate 27 | * `dd if=server-apc.p15 of=server.p15 bs=228 skip=1` 28 | * Add APC header to a standard p15 file containing a 1024 bit key 29 | * `apcheader server.p15 server-apc.p15 1` 30 | -------------------------------------------------------------------------------- /apcheader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Adds the APC specific header to a file. 5 | * 6 | * Author: Frederik Kriewitz 7 | * 8 | * Use, modification, and distribution of apcheader is allowed without 9 | * any limitations. There is no warranty, express or implied. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | uint16_t cksum_map[] = { 20 | 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 21 | 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, 22 | 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, 23 | 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, 24 | 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, 25 | 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, 26 | 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, 27 | 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, 28 | 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, 29 | 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, 30 | 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 31 | 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, 32 | 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, 33 | 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, 34 | 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, 35 | 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, 36 | 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, 37 | 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, 38 | 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, 39 | 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, 40 | 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, 41 | 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 42 | 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, 43 | 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, 44 | 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, 45 | 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, 46 | 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, 47 | 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, 48 | 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, 49 | 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, 50 | 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, 51 | 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0}; 52 | 53 | int16_t calc_cksum(int16_t start, uint8_t *buf, size_t length) 54 | { 55 | // checksum function used by APC 56 | // seems to be CRC-16-CCITT 57 | uint16_t result; 58 | uint16_t lo,hi; 59 | uint16_t map_value; 60 | uint8_t key; 61 | 62 | result = start; 63 | while(length > 0) 64 | { 65 | hi = (result >> 8) & 0xFF; 66 | lo = (result & 0xFF) << 8; 67 | key = *buf ^ hi; 68 | map_value = cksum_map[key]; 69 | result = lo ^ map_value; 70 | buf++; 71 | length--; 72 | } 73 | return result; 74 | } 75 | 76 | int main(int argc, char *argv[]) 77 | { 78 | FILE *f; 79 | char *buf; 80 | char *inFile; 81 | char *outFile; 82 | int keySize; 83 | size_t fileSize; 84 | FILE *file; 85 | 86 | if(argc != 4) { 87 | fprintf(stderr, 88 | "Syntax: %s \n" 89 | " Use keySize=1 for a 1024 bit key and 2 for 2048 bit\n", 90 | argv[0]); 91 | exit(-1); 92 | } 93 | 94 | inFile = argv[1]; 95 | outFile = argv[2]; 96 | keySize = atoi(argv[3]); 97 | 98 | file = fopen(inFile, "rb+"); 99 | if(file == NULL) { 100 | fprintf( stderr, "Failed to open inFile %s: %s (errno=%d)\n", inFile, strerror(errno), errno); 101 | exit(-2); 102 | } 103 | 104 | // get file size 105 | fseek(file, 0, 2); 106 | fileSize = ftell(file); 107 | 108 | // init buffer 109 | buf = calloc(fileSize + 228, 1); 110 | if(buf == NULL) { 111 | fprintf(stderr, "buffer calloc failed: %s (errno=%d)\n", strerror(errno), errno); 112 | exit(-2); 113 | } 114 | 115 | // read inFile 116 | fseek(file, 0, 0); 117 | fread(buf+228, fileSize, 1, file); 118 | fclose(file); 119 | 120 | // add APC header 121 | *(uint32_t *)(buf + 0) = 1; // always 1 122 | *(uint32_t *)(buf + 4) = 1; // always 1 123 | strncpy((char *)(buf + 8), "SecurityWizard103", 0xC8); // apparently supposed to identify the creating tool, SecWiz v1.04 sill puts 103 here 124 | *(uint32_t *)(buf + 208) = 1; // always 1 125 | *(uint32_t *)(buf + 212) = 1; // always 1 126 | *(uint32_t *)(buf + 216) = fileSize; // size of the following data 127 | *(uint32_t *)(buf + 208) = keySize; // 1 for 1024 key, otherwise (2048 bit) 2 128 | // 16 bit checksums are moved to 32 bit int with sign-extension 129 | *(uint32_t *)(buf + 220) = (int32_t)calc_cksum(0, buf + 228, fileSize); // checksum of the original file 130 | *(uint32_t *)(buf + 224) = (int32_t)calc_cksum(0, buf, 224); // checksum of the APC header 131 | 132 | // write outFile 133 | file = fopen(outFile, "wb"); 134 | if(file == NULL) { 135 | fprintf(stderr, "Failed to open outFile %s: %s (errno=%d)\n", outFile, strerror(errno), errno); 136 | free(buf); 137 | exit(-2); 138 | } 139 | fwrite(buf, fileSize + 228, 1, file); 140 | fclose(file); 141 | free(buf); 142 | exit(0); 143 | } 144 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## CA files generated using the Security Wizard v1.04 CA Root Certificate option 2 | 3 | * 1024 Bit key 4 | * [apc-secwiz-104-ca-1024.p15](apc-secwiz-104-ca-1024.p15) 5 | * [apc-secwiz-104-ca-1024.crt](apc-secwiz-104-ca-1024.crt) 6 | * 2048 Bit key 7 | * [apc-secwiz-104-ca-2048.p15](apc-secwiz-104-ca-2048.p15) 8 | * [apc-secwiz-104-ca-2048.crt](apc-secwiz-104-ca-2048.crt) 9 | 10 | ## Server certificate files generated using the Security Wizard v1.04 SSL Server Certificate option with the corresponding 1024/2048 Bit CA from above 11 | 12 | * 1024 Bit key 13 | * [apc-secwiz-104-server-1024.p15](apc-secwiz-104-server-1024.p15) 14 | * 2048 Bit key 15 | * [apc-secwiz-104-server-2048.p15](apc-secwiz-104-server-2048.p15) 16 | -------------------------------------------------------------------------------- /examples/apc-secwiz-104-ca-1024.crt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-ca-1024.crt -------------------------------------------------------------------------------- /examples/apc-secwiz-104-ca-1024.p15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-ca-1024.p15 -------------------------------------------------------------------------------- /examples/apc-secwiz-104-ca-2048.crt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-ca-2048.crt -------------------------------------------------------------------------------- /examples/apc-secwiz-104-ca-2048.p15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-ca-2048.p15 -------------------------------------------------------------------------------- /examples/apc-secwiz-104-server-1024.p15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-server-1024.p15 -------------------------------------------------------------------------------- /examples/apc-secwiz-104-server-2048.p15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freddy36/apc_tools/c96613db51d7fc8b537f25ff7b1d5bfd2ad294ea/examples/apc-secwiz-104-server-2048.p15 -------------------------------------------------------------------------------- /p15dump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * unfinished work! 3 | * This was supposed to dump the private key of an apc certificate (strip the header first) but (using cryptlib version 3.4.1) opening the key already failed. 4 | * 5 | * Use, modification, and distribution of pemtrans is allowed without 6 | * any limitations. There is no warranty, express or implied. 7 | */ 8 | 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | void check( int n, CRYPT_HANDLE c, char *s ) 21 | { 22 | int status; 23 | int locus = 0; 24 | int type = 0; 25 | int length = 0; 26 | 27 | if ( n == CRYPT_OK ) 28 | return; 29 | 30 | cryptGetAttribute( c, CRYPT_ATTRIBUTE_ERRORLOCUS, &locus ); 31 | cryptGetAttribute( c, CRYPT_ATTRIBUTE_ERRORTYPE, &type ); 32 | 33 | fprintf( stderr, "%s failed.\n", s ); 34 | fprintf( stderr, "\tError code: %d\n", n ); 35 | if ( locus != 0 ) 36 | fprintf( stderr, "\tError locus: %d\n", locus ); 37 | if ( type != 0 ) 38 | fprintf( stderr, "\tError type: %d\n", type ); 39 | 40 | status = cryptGetAttributeString( c, CRYPT_ATTRIBUTE_ERRORMESSAGE, 41 | 0, &length ); 42 | if ( cryptStatusOK( status ) ) { 43 | char * err = malloc( length ); 44 | if ( !err ) 45 | exit( -1 ); 46 | status = cryptGetAttributeString( c, CRYPT_ATTRIBUTE_ERRORMESSAGE, 47 | err, &length ); 48 | if ( cryptStatusOK( status ) ) 49 | fprintf( stderr, "\tError message: %s\n", err ); 50 | } 51 | 52 | exit( -1 ); 53 | } 54 | 55 | 56 | int main( int argc, char *argv[] ) 57 | { 58 | int n; 59 | FILE *f; 60 | char *buf[8]; 61 | char *outFile; 62 | char *p15File; 63 | char *certFile; 64 | char *certData; 65 | char *label; 66 | char *secret; 67 | struct stat st; 68 | int usage; 69 | 70 | CRYPT_KEYSET keyset; 71 | CRYPT_CONTEXT pKey; 72 | CRYPT_PKCINFO_RSA rsa; 73 | CRYPT_CERTIFICATE cert; 74 | CRYPT_KEYOPT_TYPE opt; 75 | 76 | label = "Private key"; 77 | secret = "user"; 78 | p15File = "server.p15"; 79 | 80 | 81 | if ( argc != 4 ) { 82 | fprintf( stderr, 83 | "Syntax: %s