1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Based on PuTTY's import.c for importing/exporting OpenSSH and SSH.com 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * keyfiles. 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The horribleness of the code is probably mine (matt). 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Modifications copyright 2003 Matt Johnston 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * PuTTY is copyright 1997-2003 Simon Tatham. 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Portions copyright Robert de Bath, Joris van Rantwijk, Delian 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Justin Bradford, and CORE SDI S.A. 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * obtaining a copy of this software and associated documentation files 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (the "Software"), to deal in the Software without restriction, 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * including without limitation the rights to use, copy, modify, merge, 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * publish, distribute, sublicense, and/or sell copies of the Software, 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * and to permit persons to whom the Software is furnished to do so, 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * subject to the following conditions: 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * included in all copies or substantial portions of the Software. 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "keyimport.h" 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "bignum.h" 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h" 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h" 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define PUT_32BIT(cp, value) do { \ 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (cp)[3] = (unsigned char)(value); \ 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (cp)[2] = (unsigned char)((value) >> 8); \ 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (cp)[1] = (unsigned char)((value) >> 16); \ 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (cp)[0] = (unsigned char)((value) >> 24); } while (0) 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define GET_32BIT(cp) \ 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (((unsigned long)(unsigned char)(cp)[0] << 24) | \ 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ((unsigned long)(unsigned char)(cp)[1] << 16) | \ 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ((unsigned long)(unsigned char)(cp)[2] << 8) | \ 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ((unsigned long)(unsigned char)(cp)[3])) 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int openssh_encrypted(const char *filename); 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic sign_key *openssh_read(const char *filename, char *passphrase); 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int openssh_write(const char *filename, sign_key *key, 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *passphrase); 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int dropbear_write(const char*filename, sign_key * key); 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic sign_key *dropbear_read(const char* filename); 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int sshcom_encrypted(const char *filename, char **comment); 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase); 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int sshcom_write(const char *filename, struct ssh2_userkey *key, 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *passphrase); 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint import_encrypted(const char* filename, int filetype) { 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (filetype == KEYFILE_OPENSSH) { 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return openssh_encrypted(filename); 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (filetype == KEYFILE_SSHCOM) { 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return sshcom_encrypted(filename, NULL); 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return 0; 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectsign_key *import_read(const char *filename, char *passphrase, int filetype) { 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (filetype == KEYFILE_OPENSSH) { 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return openssh_read(filename, passphrase); 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (filetype == KEYFILE_DROPBEAR) { 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return dropbear_read(filename); 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (filetype == KEYFILE_SSHCOM) { 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return sshcom_read(filename, passphrase); 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint import_write(const char *filename, sign_key *key, char *passphrase, 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int filetype) { 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (filetype == KEYFILE_OPENSSH) { 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return openssh_write(filename, key, passphrase); 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (filetype == KEYFILE_DROPBEAR) { 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return dropbear_write(filename, key); 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (filetype == KEYFILE_SSHCOM) { 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return sshcom_write(filename, key, passphrase); 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return 0; 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic sign_key *dropbear_read(const char* filename) { 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * buf = NULL; 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key *ret = NULL; 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int type; 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf = buf_new(MAX_PRIVKEY_SIZE); 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) { 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(buf, 0); 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = new_sign_key(); 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = DROPBEAR_SIGNKEY_ANY; 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){ 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(buf); 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projecterror: 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf) { 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(buf); 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret) { 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key_free(ret); 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* returns 0 on fail, 1 on success */ 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int dropbear_write(const char*filename, sign_key * key) { 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int keytype = -1; 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * buf; 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE*fp; 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int len; 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret; 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_RSA 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->rsakey != NULL) { 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keytype = DROPBEAR_SIGNKEY_RSA; 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_DSS 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->dsskey != NULL) { 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keytype = DROPBEAR_SIGNKEY_DSS; 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf = buf_new(MAX_PRIVKEY_SIZE); 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_put_priv_key(buf, key, keytype); 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = fopen(filename, "w"); 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fp) { 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = 0; 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(buf, 0); 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project do { 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = fwrite(buf_getptr(buf, buf->len - buf->pos), 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1, buf->len - buf->pos, fp); 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(buf, len); 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } while (len > 0 && buf->len != buf->pos); 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(fp); 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf->pos != buf->len) { 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = 0; 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = 1; 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(buf); 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* ---------------------------------------------------------------------- 190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Helper routines. (The base64 ones are defined in sshpubk.c.) 191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \ 194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ((c) >= 'a' && (c) <= 'z') || \ 195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ((c) >= '0' && (c) <= '9') || \ 196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (c) == '+' || (c) == '/' || (c) == '=' \ 197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ) 198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* cpl has to be less than 100 */ 200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void base64_encode_fp(FILE * fp, unsigned char *data, 201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int datalen, int cpl) 202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char out[100]; 204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int n; 205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long outlen; 206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int rawcpl; 207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project rawcpl = cpl * 3 / 4; 208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert((unsigned int)cpl < sizeof(out)); 209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (datalen > 0) { 211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project n = (datalen < rawcpl ? datalen : rawcpl); 212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = sizeof(out); 213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_encode(data, n, out, &outlen); 214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project data += n; 215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project datalen -= n; 216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fwrite(out, 1, outlen, fp); 217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fputc('\n', fp); 218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Read an ASN.1/BER identifier and length pair. 222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Flags are a combination of the #defines listed below. 224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Returns -1 if unsuccessful; otherwise returns the number of 226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * bytes used out of the source data. 227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* ASN.1 tag classes. */ 230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CLASS_UNIVERSAL (0 << 6) 231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CLASS_APPLICATION (1 << 6) 232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6) 233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CLASS_PRIVATE (3 << 6) 234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CLASS_MASK (3 << 6) 235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Primitive versus constructed bit. */ 237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ASN1_CONSTRUCTED (1 << 5) 238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int ber_read_id_len(void *source, int sourcelen, 240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int *id, int *length, int *flags) 241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *p = (unsigned char *) source; 243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (sourcelen == 0) 245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return -1; 246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *flags = (*p & 0xE0); 248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((*p & 0x1F) == 0x1F) { 249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *id = 0; 250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (*p & 0x80) { 251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *id = (*id << 7) | (*p & 0x7F); 252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++, sourcelen--; 253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (sourcelen == 0) 254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return -1; 255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *id = (*id << 7) | (*p & 0x7F); 257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++, sourcelen--; 258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *id = *p & 0x1F; 260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++, sourcelen--; 261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (sourcelen == 0) 264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return -1; 265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*p & 0x80) { 267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int n = *p & 0x7F; 268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++, sourcelen--; 269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (sourcelen < n) 270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return -1; 271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *length = 0; 272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (n--) 273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *length = (*length << 8) | (*p++); 274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sourcelen -= n; 275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *length = *p; 277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++, sourcelen--; 278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return p - (unsigned char *) source; 281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Write an ASN.1/BER identifier and length pair. Returns the 285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * number of bytes consumed. Assumes dest contains enough space. 286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Will avoid writing anything if dest is NULL, but still return 287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * amount of space required. 288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int ber_write_id_len(void *dest, int id, int length, int flags) 290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *d = (unsigned char *)dest; 292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int len = 0; 293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (id <= 30) { 295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Identifier is one byte. 297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = id | flags; 300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int n; 302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Identifier is multiple bytes: the first byte is 11111 304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * plus the flags, and subsequent bytes encode the value of 305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * the identifier, 7 bits at a time, with the top bit of 306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * each byte 1 except the last one which is 0. 307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = 0x1F | flags; 310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (n = 1; (id >> (7*n)) > 0; n++) 311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; /* count the bytes */ 312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (n--) { 313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F); 315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (length < 128) { 319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Length is one byte. 321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = length; 324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int n; 326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Length is multiple bytes. The first is 0x80 plus the 328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * number of subsequent bytes, and the subsequent bytes 329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * encode the actual length. 330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (n = 1; (length >> (8*n)) > 0; n++) 332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; /* count the bytes */ 333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = 0x80 | n; 335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (n--) { 336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len++; 337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (d) *d++ = (length >> (8*n)) & 0xFF; 338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return len; 342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Simple structure to point to an mp-int within a blob. */ 346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct mpint_pos { void *start; int bytes; }; 347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* ---------------------------------------------------------------------- 349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Code to read and write OpenSSH private keys. 350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectenum { OSSH_DSA, OSSH_RSA }; 353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct openssh_key { 354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int type; 355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int encrypted; 356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char iv[32]; 357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *keyblob; 358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int keyblob_len, keyblob_size; 359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}; 360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic struct openssh_key *load_openssh_key(const char *filename) 362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct openssh_key *ret; 364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *fp = NULL; 365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char buffer[256]; 366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *errmsg = NULL, *p = NULL; 367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int headers_done; 368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long len, outlen; 369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); 371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob = NULL; 372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_len = ret->keyblob_size = 0; 373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->encrypted = 0; 374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(ret->iv, 0, sizeof(ret->iv)); 375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strlen(filename) == 1 && filename[0] == '-') { 377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = stdin; 378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = fopen(filename, "r"); 380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fp) { 382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unable to open key file"; 383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 385f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fgets(buffer, sizeof(buffer), fp) || 386f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0 != strncmp(buffer, "-----BEGIN ", 11) || 387f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) { 388f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "File does not begin with OpenSSH key header"; 389f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 390f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 391f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n")) 392f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->type = OSSH_RSA; 393f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n")) 394f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->type = OSSH_DSA; 395f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project else { 396f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unrecognised key type"; 397f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 398f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 399f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 400f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project headers_done = 0; 401f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (1) { 402f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fgets(buffer, sizeof(buffer), fp)) { 403f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unexpected end of file"; 404f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 405f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 406f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (0 == strncmp(buffer, "-----END ", 9) && 407f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) 408f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; /* done */ 409f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((p = strchr(buffer, ':')) != NULL) { 410f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (headers_done) { 411f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Header found in body of key data"; 412f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 413f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 414f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *p++ = '\0'; 415f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (*p && isspace((unsigned char)*p)) p++; 416f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!strcmp(buffer, "Proc-Type")) { 417f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (p[0] != '4' || p[1] != ',') { 418f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Proc-Type is not 4 (only 4 is supported)"; 419f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 420f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 421f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += 2; 422f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!strcmp(p, "ENCRYPTED\n")) 423f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->encrypted = 1; 424f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (!strcmp(buffer, "DEK-Info")) { 425f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int i, j; 426f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 427f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strncmp(p, "DES-EDE3-CBC,", 13)) { 428f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Ciphers other than DES-EDE3-CBC not supported"; 429f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 430f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 431f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += 13; 432f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < 8; i++) { 433f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (1 != sscanf(p, "%2x", &j)) 434f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 435f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->iv[i] = j; 436f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += 2; 437f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 438f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (i < 8) { 439f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Expected 16-digit iv in DEK-Info"; 440f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 441f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 442f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 443f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 444f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project headers_done = 1; 445f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = strlen(buffer); 446f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = len*4/3; 447f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob_len + outlen > ret->keyblob_size) { 448f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_size = ret->keyblob_len + outlen + 256; 449f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, 450f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_size); 451f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 452f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = ret->keyblob_size - ret->keyblob_len; 453f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (base64_decode(buffer, len, 454f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ 455f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Error decoding base64"; 456f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 457f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 458f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_len += outlen; 459f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 460f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 461f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 462f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob_len == 0 || !ret->keyblob) { 463f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key body not present"; 464f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 465f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 466f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 467f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->encrypted && ret->keyblob_len % 8 != 0) { 468f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Encrypted key blob is not a multiple of cipher block size"; 469f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 470f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 471f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 472f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(buffer, 0, sizeof(buffer)); 473f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 474f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 475f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 476f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(buffer, 0, sizeof(buffer)); 477f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret) { 478f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob) { 479f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(ret->keyblob, 0, ret->keyblob_size); 480f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(ret->keyblob); 481f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 482f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&ret, 0, sizeof(ret)); 483f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(ret); 484f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 485f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (fp) { 486f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(fp); 487f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 488f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (errmsg) { 489f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Error: %s\n", errmsg); 490f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 491f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 492f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 493f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 494f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int openssh_encrypted(const char *filename) 495f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 496f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct openssh_key *key = load_openssh_key(filename); 497f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret; 498f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 499f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!key) 500f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return 0; 501f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = key->encrypted; 502f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(key->keyblob, 0, key->keyblob_size); 503f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key->keyblob); 504f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&key, 0, sizeof(key)); 505f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key); 506f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 507f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 508f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 509f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic sign_key *openssh_read(const char *filename, char *passphrase) 510f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 511f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct openssh_key *key; 512f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *p; 513f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret, id, len, flags; 514f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int i, num_integers = 0; 515f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key *retval = NULL; 516f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *errmsg; 517f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *modptr = NULL; 518f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int modlen = -9999; 519f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int type; 520f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 521f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key *retkey; 522f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * blobbuf = NULL; 523f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 524f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key = load_openssh_key(filename); 525f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 526f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!key) 527f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 528f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 529f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->encrypted) { 530f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "encrypted keys not supported currently"; 531f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 532f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 533f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* matt TODO */ 534f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 535f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Derive encryption key from passphrase and iv/salt: 536f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 537f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block A equal MD5(passphrase || iv) 538f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block B equal MD5(A || passphrase || iv) 539f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - block C would be MD5(B || passphrase || iv) and so on 540f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - encryption key is the first N bytes of A || B 541f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 542f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct MD5Context md5c; 543f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char keybuf[32]; 544f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 545f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 546f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 547f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)key->iv, 8); 548f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf, &md5c); 549f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 550f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 551f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, keybuf, 16); 552f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 553f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)key->iv, 8); 554f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf+16, &md5c); 555f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 556f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 557f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now decrypt the key blob. 558f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 559f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv, 560f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key->keyblob, key->keyblob_len); 561f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 562f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&md5c, 0, sizeof(md5c)); 563f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(keybuf, 0, sizeof(keybuf)); 564f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 565f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 566f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 567f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 568f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now we have a decrypted key blob, which contains an ASN.1 569f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * encoded private key. We must now untangle the ASN.1. 570f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 571f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * We expect the whole key blob to be formatted as a SEQUENCE 572f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (0x30 followed by a length code indicating that the rest of 573f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * the blob is part of the sequence). Within that SEQUENCE we 574f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * expect to see a bunch of INTEGERs. What those integers mean 575f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * depends on the key type: 576f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 577f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - For RSA, we expect the integers to be 0, n, e, d, p, q, 578f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * dmp1, dmq1, iqmp in that order. (The last three are d mod 579f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (p-1), d mod (q-1), inverse of q mod p respectively.) 580f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 581f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - For DSA, we expect them to be 0, p, q, g, y, x in that 582f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * order. 583f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 584f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 585f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p = key->keyblob; 586f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 587f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */ 588f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags); 589f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += ret; 590f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret < 0 || id != 16) { 591f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "ASN.1 decoding failure - wrong password?"; 592f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 593f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 594f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 595f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Expect a load of INTEGERs. */ 596f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->type == OSSH_RSA) 597f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project num_integers = 9; 598f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project else if (key->type == OSSH_DSA) 599f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project num_integers = 6; 600f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 601f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 602f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Space to create key blob in. 603f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 604f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project blobbuf = buf_new(3000); 605f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 606f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->type == OSSH_DSA) { 607f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(blobbuf, "ssh-dss", 7); 608f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (key->type == OSSH_RSA) { 609f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(blobbuf, "ssh-rsa", 7); 610f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 611f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 612f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < num_integers; i++) { 613f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, 614f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &id, &len, &flags); 615f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += ret; 616f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret < 0 || id != 2 || 617f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key->keyblob+key->keyblob_len-p < len) { 618f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "ASN.1 decoding failure"; 619f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 620f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 621f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 622f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (i == 0) { 623f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 624f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The first integer should be zero always (I think 625f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * this is some sort of version indication). 626f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 627f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len != 1 || p[0] != 0) { 628f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Version number mismatch"; 629f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 630f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 631f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (key->type == OSSH_RSA) { 632f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 633f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp 634f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * but we want e, n, d, p, q 635f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 636f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (i == 1) { 637f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Save the details for after we deal with number 2. */ 638f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modptr = (char *)p; 639f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modlen = len; 640f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (i >= 2 && i <= 5) { 641f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(blobbuf, p, len); 642f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (i == 2) { 643f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(blobbuf, modptr, modlen); 644f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 645f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 646f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (key->type == OSSH_DSA) { 647f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 648f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OpenSSH key order is p, q, g, y, x, 649f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * we want the same. 650f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 651f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(blobbuf, p, len); 652f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 653f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 654f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Skip past the number. */ 655f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p += len; 656f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 657f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 658f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 659f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now put together the actual key. Simplest way to do this is 660f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to assemble our own key blobs and feed them to the createkey 661f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * functions; this is a bit faffy but it does mean we get all 662f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * the sanity checks for free. 663f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 664f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey = new_sign_key(); 665f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(blobbuf, 0); 666f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = DROPBEAR_SIGNKEY_ANY; 667f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_get_priv_key(blobbuf, retkey, &type) 668f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project != DROPBEAR_SUCCESS) { 669f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "unable to create key structure"; 670f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key_free(retkey); 671f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey = NULL; 672f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 673f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 674f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 675f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = NULL; /* no error */ 676f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retval = retkey; 677f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 678f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 679f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (blobbuf) { 680f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_burn(blobbuf); 681f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(blobbuf); 682f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 683f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_burn(key->keyblob, key->keyblob_size); 684f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key->keyblob); 685f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_burn(key, sizeof(key)); 686f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key); 687f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (errmsg) { 688f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Error: %s\n", errmsg); 689f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 690f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return retval; 691f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 692f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 693f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int openssh_write(const char *filename, sign_key *key, 694f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *passphrase) 695f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 696f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * keyblob = NULL; 697f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * extrablob = NULL; /* used for calculated values to write */ 698f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *outblob = NULL; 699f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int outlen = -9999; 700f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos numbers[9]; 701f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int nnumbers = -1, pos, len, seqlen, i; 702f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *header = NULL, *footer = NULL; 703f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char zero[1]; 704f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char iv[8]; 705f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret = 0; 706f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *fp; 707f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int keytype = -1; 708f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 709f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_RSA 710f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ 711f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 712f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->rsakey != NULL) { 713f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keytype = DROPBEAR_SIGNKEY_RSA; 714f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 715f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 716f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_DSS 717f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->dsskey != NULL) { 718f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keytype = DROPBEAR_SIGNKEY_DSS; 719f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 720f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 721f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 722f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(keytype != -1); 723f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 724f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 725f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Fetch the key blobs. 726f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 727f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keyblob = buf_new(3000); 728f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_put_priv_key(keyblob, key, keytype); 729f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 730f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(keyblob, 0); 731f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* skip the "ssh-rsa" or "ssh-dss" header */ 732f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, buf_getint(keyblob)); 733f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 734f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 735f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Find the sequence of integers to be encoded into the OpenSSH 736f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * key blob, and also decide on the header line. 737f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 738f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0'; 739f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 740f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_RSA 741f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (keytype == DROPBEAR_SIGNKEY_RSA) { 742f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 743f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->rsakey->p == NULL || key->rsakey->q == NULL) { 744f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n"); 745f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 746f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 747f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 748f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* e */ 749f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2].bytes = buf_getint(keyblob); 750f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); 751f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[2].bytes); 752f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 753f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* n */ 754f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1].bytes = buf_getint(keyblob); 755f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); 756f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[1].bytes); 757f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 758f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* d */ 759f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3].bytes = buf_getint(keyblob); 760f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); 761f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[3].bytes); 762f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 763f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* p */ 764f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4].bytes = buf_getint(keyblob); 765f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); 766f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[4].bytes); 767f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 768f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q */ 769f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[5].bytes = buf_getint(keyblob); 770f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); 771f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[5].bytes); 772f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 773f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now calculate some extra parameters: */ 774f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init(&tmpval); 775f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init(&dmp1); 776f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init(&dmq1); 777f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init(&iqmp); 778f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 779f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* dmp1 = d mod (p-1) */ 780f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) { 781f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Bignum error for p-1\n"); 782f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 783f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 784f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) { 785f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Bignum error for dmp1\n"); 786f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 787f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 788f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 789f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* dmq1 = d mod (q-1) */ 790f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) { 791f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Bignum error for q-1\n"); 792f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 793f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 794f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) { 795f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Bignum error for dmq1\n"); 796f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 797f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 798f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 799f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* iqmp = (q^-1) mod p */ 800f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) { 801f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Bignum error for iqmp\n"); 802f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 803f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 804f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 805f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project extrablob = buf_new(2000); 806f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putmpint(extrablob, &dmp1); 807f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putmpint(extrablob, &dmq1); 808f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putmpint(extrablob, &iqmp); 809f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(extrablob, 0); 810f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear(&dmp1); 811f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear(&dmq1); 812f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear(&iqmp); 813f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear(&tmpval); 814f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 815f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* dmp1 */ 816f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[6].bytes = buf_getint(extrablob); 817f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[6].start = buf_getptr(extrablob, numbers[6].bytes); 818f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(extrablob, numbers[6].bytes); 819f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 820f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* dmq1 */ 821f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[7].bytes = buf_getint(extrablob); 822f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[7].start = buf_getptr(extrablob, numbers[7].bytes); 823f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(extrablob, numbers[7].bytes); 824f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 825f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* iqmp */ 826f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[8].bytes = buf_getint(extrablob); 827f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[8].start = buf_getptr(extrablob, numbers[8].bytes); 828f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(extrablob, numbers[8].bytes); 829f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 830f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project nnumbers = 9; 831f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project header = "-----BEGIN RSA PRIVATE KEY-----\n"; 832f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project footer = "-----END RSA PRIVATE KEY-----\n"; 833f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 834f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* DROPBEAR_RSA */ 835f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 836f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_DSS 837f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (keytype == DROPBEAR_SIGNKEY_DSS) { 838f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 839f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* p */ 840f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1].bytes = buf_getint(keyblob); 841f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); 842f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[1].bytes); 843f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 844f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q */ 845f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2].bytes = buf_getint(keyblob); 846f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); 847f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[2].bytes); 848f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 849f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* g */ 850f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3].bytes = buf_getint(keyblob); 851f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); 852f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[3].bytes); 853f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 854f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* y */ 855f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4].bytes = buf_getint(keyblob); 856f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); 857f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[4].bytes); 858f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 859f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* x */ 860f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[5].bytes = buf_getint(keyblob); 861f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); 862f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(keyblob, numbers[5].bytes); 863f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 864f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project nnumbers = 6; 865f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project header = "-----BEGIN DSA PRIVATE KEY-----\n"; 866f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project footer = "-----END DSA PRIVATE KEY-----\n"; 867f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 868f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* DROPBEAR_DSS */ 869f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 870f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 871f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now count up the total size of the ASN.1 encoded integers, 872f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * so as to determine the length of the containing SEQUENCE. 873f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 874f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = 0; 875f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < nnumbers; i++) { 876f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0); 877f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len += numbers[i].bytes; 878f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 879f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project seqlen = len; 880f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Now add on the SEQUENCE header. */ 881f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED); 882f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Round up to the cipher block size, ensuring we have at least one 883f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * byte of padding (see below). */ 884f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = len; 885f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (passphrase) 886f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = (outlen+8) &~ 7; 887f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 888f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 889f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now we know how big outblob needs to be. Allocate it. 890f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 891f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outblob = (unsigned char*)m_malloc(outlen); 892f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 893f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 894f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * And write the data into it. 895f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 896f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 897f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED); 898f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < nnumbers; i++) { 899f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0); 900f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memcpy(outblob+pos, numbers[i].start, numbers[i].bytes); 901f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += numbers[i].bytes; 902f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 903f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 904f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 905f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Padding on OpenSSH keys is deterministic. The number of 906f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * padding bytes is always more than zero, and always at most 907f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * the cipher block length. The value of each padding byte is 908f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * equal to the number of padding bytes. So a plaintext that's 909f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * an exact multiple of the block size will be padded with 08 910f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a 911f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * plaintext one byte less than a multiple of the block size 912f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * will be padded with just 01. 913f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 914f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * This enables the OpenSSL key decryption function to strip 915f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * off the padding algorithmically and return the unpadded 916f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * plaintext to the next layer: it looks at the final byte, and 917f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * then expects to find that many bytes at the end of the data 918f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * with the same value. Those are all removed and the rest is 919f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * returned. 920f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 921f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(pos == len); 922f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (pos < outlen) { 923f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outblob[pos++] = outlen - len; 924f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 925f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 926f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 927f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Encrypt the key. 928f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 929f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (passphrase) { 930f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Encrypted keys aren't supported currently\n"); 931f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 932f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 933f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 934f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 935f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * And save it. We'll use Unix line endings just in case it's 936f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * subsequently transferred in binary mode. 937f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 938f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strlen(filename) == 1 && filename[0] == '-') { 939f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = stdout; 940f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 941f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = fopen(filename, "wb"); /* ensure Unix line endings */ 942f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 943f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fp) { 944f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "Failed opening output file\n"); 945f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 946f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 947f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fputs(header, fp); 948f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_encode_fp(fp, outblob, outlen, 64); 949f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fputs(footer, fp); 950f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(fp); 951f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = 1; 952f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 953f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 954f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (outblob) { 955f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(outblob, 0, outlen); 956f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(outblob); 957f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 958f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (keyblob) { 959f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_burn(keyblob); 960f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(keyblob); 961f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 962f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (extrablob) { 963f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_burn(extrablob); 964f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(extrablob); 965f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 966f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 967f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 968f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 969f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0 970f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* XXX TODO ssh.com stuff isn't going yet */ 971f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 972f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* ---------------------------------------------------------------------- 973f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Code to read ssh.com private keys. 974f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 975f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 976f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 977f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The format of the base64 blob is largely ssh2-packet-formatted, 978f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * except that mpints are a bit different: they're more like the 979f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * old ssh1 mpint. You have a 32-bit bit count N, followed by 980f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (N+7)/8 bytes of data. 981f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 982f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * So. The blob contains: 983f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 984f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - uint32 0x3f6ff9eb (magic number) 985f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - uint32 size (total blob size) 986f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - string key-type (see below) 987f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - string cipher-type (tells you if key is encrypted) 988f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - string encrypted-blob 989f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 990f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (The first size field includes the size field itself and the 991f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * magic number before it. All other size fields are ordinary ssh2 992f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * strings, so the size field indicates how much data is to 993f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * _follow_.) 994f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 995f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The encrypted blob, once decrypted, contains a single string 996f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * which in turn contains the payload. (This allows padding to be 997f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * added after that string while still making it clear where the 998f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * real payload ends. Also it probably makes for a reasonable 999f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * decryption check.) 1000f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1001f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The payload blob, for an RSA key, contains: 1002f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint e 1003f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint d 1004f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint n (yes, the public and private stuff is intermixed) 1005f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint u (presumably inverse of p mod q) 1006f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint p (p is the smaller prime) 1007f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint q (q is the larger) 1008f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1009f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * For a DSA key, the payload blob contains: 1010f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - uint32 0 1011f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint p 1012f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint g 1013f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint q 1014f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint y 1015f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - mpint x 1016f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1017f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Alternatively, if the parameters are `predefined', that 1018f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (0,p,g,q) sequence can be replaced by a uint32 1 and a string 1019f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * containing some predefined parameter specification. *shudder*, 1020f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * but I doubt we'll encounter this in real life. 1021f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1022f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The key type strings are ghastly. The RSA key I looked at had a 1023f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * type string of 1024f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1025f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * `if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}' 1026f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1027f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * and the DSA key wasn't much better: 1028f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1029f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * `dl-modp{sign{dsa-nist-sha1},dh{plain}}' 1030f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1031f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * It isn't clear that these will always be the same. I think it 1032f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * might be wise just to look at the `if-modn{sign{rsa' and 1033f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * `dl-modp{sign{dsa' prefixes. 1034f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1035f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Finally, the encryption. The cipher-type string appears to be 1036f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * either `none' or `3des-cbc'. Looks as if this is SSH2-style 1037f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3des-cbc (i.e. outer cbc rather than inner). The key is created 1038f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * from the passphrase by means of yet another hashing faff: 1039f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1040f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - first 16 bytes are MD5(passphrase) 1041f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - next 16 bytes are MD5(passphrase || first 16 bytes) 1042f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - if there were more, they'd be MD5(passphrase || first 32), 1043f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * and so on. 1044f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1045f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1046f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb 1047f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1048f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct sshcom_key { 1049f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char comment[256]; /* allowing any length is overkill */ 1050f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *keyblob; 1051f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int keyblob_len, keyblob_size; 1052f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}; 1053f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1054f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic struct sshcom_key *load_sshcom_key(const char *filename) 1055f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1056f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct sshcom_key *ret; 1057f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *fp; 1058f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char buffer[256]; 1059f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int len; 1060f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *errmsg, *p; 1061f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int headers_done; 1062f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char base64_bit[4]; 1063f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int base64_chars = 0; 1064f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1065f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = snew(struct sshcom_key); 1066f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->comment[0] = '\0'; 1067f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob = NULL; 1068f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_len = ret->keyblob_size = 0; 1069f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1070f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = fopen(filename, "r"); 1071f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fp) { 1072f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unable to open key file"; 1073f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1074f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1075f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fgets(buffer, sizeof(buffer), fp) || 1076f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0 != strcmp(buffer, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n")) { 1077f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "File does not begin with ssh.com key header"; 1078f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1079f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1080f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1081f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project headers_done = 0; 1082f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (1) { 1083f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fgets(buffer, sizeof(buffer), fp)) { 1084f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unexpected end of file"; 1085f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1086f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1087f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n")) 1088f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; /* done */ 1089f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((p = strchr(buffer, ':')) != NULL) { 1090f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (headers_done) { 1091f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Header found in body of key data"; 1092f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1093f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1094f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *p++ = '\0'; 1095f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (*p && isspace((unsigned char)*p)) p++; 1096f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1097f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Header lines can end in a trailing backslash for 1098f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * continuation. 1099f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) || 1101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p[len-1] != '\n' || p[len-2] == '\\') { 1102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len > (int)((p-buffer) + sizeof(buffer)-2)) { 1103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Header line too long to deal with"; 1104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fgets(p+len-2, sizeof(buffer)-(p-buffer)-(len-2), fp)) { 1107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Unexpected end of file"; 1108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p[strcspn(p, "\n")] = '\0'; 1112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!strcmp(buffer, "Comment")) { 1113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Strip quotes in comment if present. */ 1114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (p[0] == '"' && p[strlen(p)-1] == '"') { 1115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++; 1116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p[strlen(p)-1] = '\0'; 1117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project strncpy(ret->comment, p, sizeof(ret->comment)); 1119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->comment[sizeof(ret->comment)-1] = '\0'; 1120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 1122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project headers_done = 1; 1123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p = buffer; 1125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (isbase64(*p)) { 1126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_bit[base64_chars++] = *p; 1127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (base64_chars == 4) { 1128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char out[3]; 1129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_chars = 0; 1131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = base64_decode_atom(base64_bit, out); 1133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len <= 0) { 1135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Invalid base64 encoding"; 1136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob_len + len > ret->keyblob_size) { 1140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_size = ret->keyblob_len + len + 256; 1141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob = sresize(ret->keyblob, ret->keyblob_size, 1142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char); 1143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memcpy(ret->keyblob + ret->keyblob_len, out, len); 1146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->keyblob_len += len; 1147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project p++; 1150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob_len == 0 || !ret->keyblob) { 1155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key body not present"; 1156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 1160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 1162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret) { 1163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret->keyblob) { 1164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(ret->keyblob, 0, ret->keyblob_size); 1165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(ret->keyblob); 1166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&ret, 0, sizeof(ret)); 1168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(ret); 1169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 1171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sshcom_encrypted(const char *filename, char **comment) 1174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct sshcom_key *key = load_sshcom_key(filename); 1176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos, len, answer; 1177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *comment = NULL; 1179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!key) 1180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return 0; 1181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Check magic number. 1184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) 1186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return 0; /* key is invalid */ 1187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Find the cipher-type string. 1190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project answer = 0; 1192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 8; 1193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4) 1194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto done; /* key is far too short */ 1195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4 + GET_32BIT(key->keyblob + pos); /* skip key type */ 1196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4) 1197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto done; /* key is far too short */ 1198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = GET_32BIT(key->keyblob + pos); /* find cipher-type length */ 1199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4+len) 1200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto done; /* cipher type string is incomplete */ 1201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4)) 1202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project answer = 1; 1203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project done: 1205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *comment = dupstr(key->comment); 1206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(key->keyblob, 0, key->keyblob_size); 1207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key->keyblob); 1208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&key, 0, sizeof(key)); 1209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key); 1210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return answer; 1211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) 1214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int bits; 1216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int bytes; 1217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *d = (unsigned char *) data; 1218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len < 4) 1220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project bits = GET_32BIT(d); 1222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project bytes = (bits + 7) / 8; 1224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len < 4+bytes) 1225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->start = d + 4; 1228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->bytes = bytes; 1229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return bytes+4; 1230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 1232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->start = NULL; 1233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret->bytes = -1; 1234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return len; /* ensure further calls fail as well */ 1235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int sshcom_put_mpint(void *target, void *data, int len) 1238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *d = (unsigned char *)target; 1240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *i = (unsigned char *)data; 1241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int bits = len * 8 - 1; 1242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (bits > 0) { 1244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*i & (1 << (bits & 7))) 1245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 1246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!(bits-- & 7)) 1247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project i++, len--; 1248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(d, bits+1); 1251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memcpy(d+4, i, len); 1252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return len+4; 1253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectsign_key *sshcom_read(const char *filename, char *passphrase) 1256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct sshcom_key *key = load_sshcom_key(filename); 1258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *errmsg; 1259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos, len; 1260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const char prefix_rsa[] = "if-modn{sign{rsa"; 1261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const char prefix_dsa[] = "dl-modp{sign{dsa"; 1262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project enum { RSA, DSA } type; 1263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int encrypted; 1264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *ciphertext; 1265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int cipherlen; 1266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct ssh2_userkey *ret = NULL, *retkey; 1267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const struct ssh_signkey *alg; 1268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *blob = NULL; 1269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int blobsize, publen, privlen; 1270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!key) 1272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return NULL; 1273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Check magic number. 1276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (GET_32BIT(key->keyblob) != SSHCOM_MAGIC_NUMBER) { 1278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key does not begin with magic number"; 1279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Determine the key type. 1284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 8; 1286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4 || 1287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key blob does not contain a key type string"; 1289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len > sizeof(prefix_rsa) - 1 && 1292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) { 1293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = RSA; 1294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (len > sizeof(prefix_dsa) - 1 && 1295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) { 1296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = DSA; 1297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 1298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key is of unknown type"; 1299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4+len; 1302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Determine the cipher type. 1305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4 || 1307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key blob does not contain a cipher type string"; 1309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4)) 1312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project encrypted = 0; 1313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8)) 1314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project encrypted = 1; 1315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project else { 1316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key encryption is of unknown type"; 1317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4+len; 1320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Get hold of the encrypted part of the key. 1323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->keyblob_len < pos+4 || 1325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) { 1326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Key blob does not contain actual key data"; 1327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ciphertext = (char *)key->keyblob + pos + 4; 1330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipherlen = len; 1331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cipherlen == 0) { 1332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Length of key data is zero"; 1333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Decrypt it if necessary. 1338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (encrypted) { 1340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Derive encryption key from passphrase and iv/salt: 1342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block A equal MD5(passphrase) 1344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block B equal MD5(passphrase || A) 1345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - block C would be MD5(passphrase || A || B) and so on 1346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - encryption key is the first N bytes of A || B 1347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct MD5Context md5c; 1349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char keybuf[32], iv[8]; 1350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cipherlen % 8 != 0) { 1352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "Encrypted part of key is not a multiple of cipher block" 1353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project " size"; 1354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 1358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 1359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf, &md5c); 1360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 1362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 1363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, keybuf, 16); 1364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf+16, &md5c); 1365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now decrypt the key blob. 1368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(iv, 0, sizeof(iv)); 1370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext, 1371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipherlen); 1372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&md5c, 0, sizeof(md5c)); 1374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(keybuf, 0, sizeof(keybuf)); 1375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Hereafter we return WRONG_PASSPHRASE for any parsing 1378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * error. (But only if we've just tried to decrypt it! 1379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Returning WRONG_PASSPHRASE for an unencrypted key is 1380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * automatic doom.) 1381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (encrypted) 1383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = SSH2_WRONG_PASSPHRASE; 1384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1385f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1386f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1387f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Strip away the containing string to get to the real meat. 1388f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1389f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = GET_32BIT(ciphertext); 1390f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (len > cipherlen-4) { 1391f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "containing string was ill-formed"; 1392f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1393f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1394f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ciphertext += 4; 1395f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipherlen = len; 1396f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1397f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1398f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now we break down into RSA versus DSA. In either case we'll 1399f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * construct public and private blobs in our own format, and 1400f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * end up feeding them to alg->createkey(). 1401f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1402f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project blobsize = cipherlen + 256; 1403f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project blob = snewn(blobsize, unsigned char); 1404f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project privlen = 0; 1405f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (type == RSA) { 1406f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos n, e, d, u, p, q; 1407f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos = 0; 1408f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e); 1409f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d); 1410f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n); 1411f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u); 1412f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p); 1413f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q); 1414f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!q.start) { 1415f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "key data did not contain six integers"; 1416f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1417f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1418f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1419f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project alg = &ssh_rsa; 1420f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 1421f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_string(blob+pos, "ssh-rsa", 7); 1422f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, e.start, e.bytes); 1423f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, n.start, n.bytes); 1424f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project publen = pos; 1425f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_string(blob+pos, d.start, d.bytes); 1426f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, q.start, q.bytes); 1427f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, p.start, p.bytes); 1428f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, u.start, u.bytes); 1429f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project privlen = pos - publen; 1430f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (type == DSA) { 1431f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos p, q, g, x, y; 1432f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos = 4; 1433f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (GET_32BIT(ciphertext) != 0) { 1434f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "predefined DSA parameters not supported"; 1435f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1436f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1437f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p); 1438f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g); 1439f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q); 1440f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y); 1441f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x); 1442f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!x.start) { 1443f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "key data did not contain five integers"; 1444f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1445f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1446f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1447f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project alg = &ssh_dss; 1448f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 1449f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_string(blob+pos, "ssh-dss", 7); 1450f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, p.start, p.bytes); 1451f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, q.start, q.bytes); 1452f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, g.start, g.bytes); 1453f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, y.start, y.bytes); 1454f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project publen = pos; 1455f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_mp(blob+pos, x.start, x.bytes); 1456f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project privlen = pos - publen; 1457f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1458f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1459f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(privlen > 0); /* should have bombed by now if not */ 1460f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1461f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey = snew(struct ssh2_userkey); 1462f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey->alg = alg; 1463f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey->data = alg->createkey(blob, publen, blob+publen, privlen); 1464f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!retkey->data) { 1465f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(retkey); 1466f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = "unable to create key data structure"; 1467f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1468f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1469f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project retkey->comment = dupstr(key->comment); 1470f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1471f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project errmsg = NULL; /* no error */ 1472f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = retkey; 1473f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1474f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 1475f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (blob) { 1476f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(blob, 0, blobsize); 1477f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(blob); 1478f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1479f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(key->keyblob, 0, key->keyblob_size); 1480f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key->keyblob); 1481f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&key, 0, sizeof(key)); 1482f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(key); 1483f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 1484f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1485f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1486f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sshcom_write(const char *filename, sign_key *key, 1487f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *passphrase) 1488f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 1489f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *pubblob, *privblob; 1490f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int publen, privlen; 1491f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *outblob; 1492f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int outlen; 1493f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos numbers[6]; 1494f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int nnumbers, initial_zero, pos, lenpos, i; 1495f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *type; 1496f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *ciphertext; 1497f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int cipherlen; 1498f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret = 0; 1499f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *fp; 1500f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1501f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1502f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Fetch the key blobs. 1503f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1504f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pubblob = key->alg->public_blob(key->data, &publen); 1505f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project privblob = key->alg->private_blob(key->data, &privlen); 1506f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outblob = NULL; 1507f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1508f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1509f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Find the sequence of integers to be encoded into the OpenSSH 1510f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * key blob, and also decide on the header line. 1511f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1512f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key->alg == &ssh_rsa) { 1513f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos; 1514f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos n, e, d, p, q, iqmp; 1515f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1516f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 4 + GET_32BIT(pubblob); 1517f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e); 1518f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n); 1519f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 1520f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d); 1521f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p); 1522f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q); 1523f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp); 1524f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1525f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(e.start && iqmp.start); /* can't go wrong */ 1526f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1527f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[0] = e; 1528f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1] = d; 1529f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2] = n; 1530f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3] = iqmp; 1531f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4] = q; 1532f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[5] = p; 1533f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1534f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project nnumbers = 6; 1535f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project initial_zero = 0; 1536f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}"; 1537f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (key->alg == &ssh_dss) { 1538f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int pos; 1539f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct mpint_pos p, q, g, y, x; 1540f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1541f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 4 + GET_32BIT(pubblob); 1542f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p); 1543f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q); 1544f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g); 1545f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y); 1546f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 1547f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x); 1548f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1549f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(y.start && x.start); /* can't go wrong */ 1550f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1551f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[0] = p; 1552f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[1] = g; 1553f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[2] = q; 1554f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[3] = y; 1555f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[4] = x; 1556f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1557f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project nnumbers = 5; 1558f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project initial_zero = 1; 1559f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}"; 1560f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 1561f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(0); /* zoinks! */ 1562f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1563f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1564f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1565f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Total size of key blob will be somewhere under 512 plus 1566f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * combined length of integers. We'll calculate the more 1567f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * precise size as we construct the blob. 1568f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1569f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = 512; 1570f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < nnumbers; i++) 1571f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen += 4 + numbers[i].bytes; 1572f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outblob = snewn(outlen, unsigned char); 1573f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1574f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1575f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Create the unencrypted key blob. 1576f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1577f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = 0; 1578f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4; 1579f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4; /* length field, fill in later */ 1580f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_string(outblob+pos, type, strlen(type)); 1581f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 1582f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *ciphertype = passphrase ? "3des-cbc" : "none"; 1583f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += put_string(outblob+pos, ciphertype, strlen(ciphertype)); 1584f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1585f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project lenpos = pos; /* remember this position */ 1586f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4; /* encrypted-blob size */ 1587f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4; /* encrypted-payload size */ 1588f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (initial_zero) { 1589f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(outblob+pos, 0); 1590f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += 4; 1591f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1592f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (i = 0; i < nnumbers; i++) 1593f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos += sshcom_put_mpint(outblob+pos, 1594f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project numbers[i].start, numbers[i].bytes); 1595f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Now wrap up the encrypted payload. */ 1596f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8)); 1597f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Pad encrypted blob to a multiple of cipher block size. */ 1598f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (passphrase) { 1599f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int padding = -(pos - (lenpos+4)) & 7; 1600f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (padding--) 1601f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outblob[pos++] = random_byte(); 1602f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1603f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ciphertext = (char *)outblob+lenpos+4; 1604f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipherlen = pos - (lenpos+4); 1605f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(!passphrase || cipherlen % 8 == 0); 1606f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Wrap up the encrypted blob string. */ 1607f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(outblob+lenpos, cipherlen); 1608f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* And finally fill in the total length field. */ 1609f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PUT_32BIT(outblob+4, pos); 1610f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1611f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_assert(pos < outlen); 1612f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1613f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1614f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Encrypt the key. 1615f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1616f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (passphrase) { 1617f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1618f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Derive encryption key from passphrase and iv/salt: 1619f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1620f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block A equal MD5(passphrase) 1621f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - let block B equal MD5(passphrase || A) 1622f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - block C would be MD5(passphrase || A || B) and so on 1623f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * - encryption key is the first N bytes of A || B 1624f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1625f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct MD5Context md5c; 1626f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char keybuf[32], iv[8]; 1627f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1628f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 1629f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 1630f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf, &md5c); 1631f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1632f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Init(&md5c); 1633f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); 1634f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Update(&md5c, keybuf, 16); 1635f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project MD5Final(keybuf+16, &md5c); 1636f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1637f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1638f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now decrypt the key blob. 1639f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1640f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(iv, 0, sizeof(iv)); 1641f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext, 1642f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipherlen); 1643f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1644f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(&md5c, 0, sizeof(md5c)); 1645f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(keybuf, 0, sizeof(keybuf)); 1646f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1647f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1648f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1649f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * And save it. We'll use Unix line endings just in case it's 1650f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * subsequently transferred in binary mode. 1651f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1652f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = fopen(filename, "wb"); /* ensure Unix line endings */ 1653f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!fp) 1654f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 1655f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); 1656f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(fp, "Comment: \""); 1657f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 1658f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Comment header is broken with backslash-newline if it goes 1659f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * over 70 chars. Although it's surrounded by quotes, it 1660f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * _doesn't_ escape backslashes or quotes within the string. 1661f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Don't ask me, I didn't design it. 1662f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 1663f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 1664f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int slen = 60; /* starts at 60 due to "Comment: " */ 1665f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char *c = key->comment; 1666f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while ((int)strlen(c) > slen) { 1667f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(fp, "%.*s\\\n", slen, c); 1668f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project c += slen; 1669f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project slen = 70; /* allow 70 chars on subsequent lines */ 1670f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1671f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(fp, "%s\"\n", c); 1672f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1673f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_encode_fp(fp, outblob, pos, 70); 1674f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); 1675f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(fp); 1676f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = 1; 1677f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1678f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project error: 1679f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (outblob) { 1680f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(outblob, 0, outlen); 1681f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(outblob); 1682f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1683f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (privblob) { 1684f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(privblob, 0, privlen); 1685f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(privblob); 1686f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1687f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (pubblob) { 1688f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project memset(pubblob, 0, publen); 1689f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(pubblob); 1690f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 1691f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 1692f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 1693f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* ssh.com stuff disabled */ 1694