+ MD5Final(digest, &md5c);
+
+ sprintf(buffer, "%d ", ssh1_bignum_bitcount(key->modulus));
+ for (i = 0; i < 16; i++)
+ sprintf(buffer+strlen(buffer), "%s%02x", i?":":"", digest[i]);
+ strncpy(str, buffer, len); str[len-1] = '\0';
+ slen = strlen(str);
+ if (key->comment && slen < len-1) {
+ str[slen] = ' ';
+ strncpy(str+slen+1, key->comment, len-slen-1);
+ str[len-1] = '\0';
+ }
+}
+
+void freersakey(struct RSAKey *key) {
+ if (key->modulus) freebn(key->modulus);
+ if (key->exponent) freebn(key->exponent);
+ if (key->private_exponent) freebn(key->private_exponent);
+ if (key->comment) sfree(key->comment);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation of the ssh-rsa signing key type.
+ */
+
+#define GET_32BIT(cp) \
+ (((unsigned long)(unsigned char)(cp)[0] << 24) | \
+ ((unsigned long)(unsigned char)(cp)[1] << 16) | \
+ ((unsigned long)(unsigned char)(cp)[2] << 8) | \
+ ((unsigned long)(unsigned char)(cp)[3]))
+
+#define PUT_32BIT(cp, value) { \
+ (cp)[0] = (unsigned char)((value) >> 24); \
+ (cp)[1] = (unsigned char)((value) >> 16); \
+ (cp)[2] = (unsigned char)((value) >> 8); \
+ (cp)[3] = (unsigned char)(value); }
+
+static void getstring(char **data, int *datalen, char **p, int *length) {
+ *p = NULL;
+ if (*datalen < 4)
+ return;
+ *length = GET_32BIT(*data);
+ *datalen -= 4; *data += 4;
+ if (*datalen < *length)
+ return;
+ *p = *data;
+ *data += *length; *datalen -= *length;
+}
+static Bignum getmp(char **data, int *datalen) {
+ char *p;
+ int length;
+ Bignum b;
+
+ getstring(data, datalen, &p, &length);
+ if (!p)
+ return NULL;
+ b = bignum_from_bytes(p, length);
+ return b;
+}
+
+static void *rsa2_newkey(char *data, int len) {
+ char *p;
+ int slen;
+ struct RSAKey *rsa;
+
+ rsa = smalloc(sizeof(struct RSAKey));
+ if (!rsa) return NULL;
+ getstring(&data, &len, &p, &slen);
+
+ if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
+ sfree(rsa);
+ return NULL;
+ }
+ rsa->exponent = getmp(&data, &len);
+ rsa->modulus = getmp(&data, &len);
+ rsa->private_exponent = NULL;
+ rsa->comment = NULL;
+
+ return rsa;
+}
+
+static void rsa2_freekey(void *key) {
+ struct RSAKey *rsa = (struct RSAKey *)key;
+ freersakey(rsa);
+ sfree(rsa);
+}
+
+static char *rsa2_fmtkey(void *key) {
+ struct RSAKey *rsa = (struct RSAKey *)key;
+ char *p;
+ int len;
+
+ len = rsastr_len(rsa);
+ p = smalloc(len);
+ rsastr_fmt(p, rsa);
+ return p;
+}
+
+static unsigned char *rsa2_public_blob(void *key, int *len) {
+ struct RSAKey *rsa = (struct RSAKey *)key;
+ int elen, mlen, bloblen;
+ int i;
+ unsigned char *blob, *p;
+
+ elen = (ssh1_bignum_bitcount(rsa->exponent)+8)/8;
+ mlen = (ssh1_bignum_bitcount(rsa->modulus)+8)/8;
+
+ /*
+ * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
+ * (three length fields, 12+7=19).
+ */
+ bloblen = 19+elen+mlen;
+ blob = smalloc(bloblen);
+ p = blob;
+ PUT_32BIT(p, 7); p += 4;
+ memcpy(p, "ssh-rsa", 7); p += 7;
+ PUT_32BIT(p, elen); p += 4;
+ for (i = elen; i-- ;) *p++ = bignum_byte(rsa->exponent, i);
+ PUT_32BIT(p, mlen); p += 4;
+ for (i = mlen; i-- ;) *p++ = bignum_byte(rsa->modulus, i);
+ assert(p == blob + bloblen);
+ *len = bloblen;
+ return blob;
+}
+
+static unsigned char *rsa2_private_blob(void *key, int *len) {
+ struct RSAKey *rsa = (struct RSAKey *)key;
+ int dlen, plen, qlen, ulen, bloblen;
+ int i;
+ unsigned char *blob, *p;
+
+ dlen = (ssh1_bignum_bitcount(rsa->private_exponent)+8)/8;
+ plen = (ssh1_bignum_bitcount(rsa->p)+8)/8;
+ qlen = (ssh1_bignum_bitcount(rsa->q)+8)/8;
+ ulen = (ssh1_bignum_bitcount(rsa->iqmp)+8)/8;
+
+ /*
+ * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +
+ * sum of lengths.
+ */
+ bloblen = 16+dlen+plen+qlen+ulen;
+ blob = smalloc(bloblen);
+ p = blob;
+ PUT_32BIT(p, dlen); p += 4;
+ for (i = dlen; i-- ;) *p++ = bignum_byte(rsa->private_exponent, i);
+ PUT_32BIT(p, plen); p += 4;
+ for (i = plen; i-- ;) *p++ = bignum_byte(rsa->p, i);
+ PUT_32BIT(p, qlen); p += 4;
+ for (i = qlen; i-- ;) *p++ = bignum_byte(rsa->q, i);
+ PUT_32BIT(p, ulen); p += 4;
+ for (i = ulen; i-- ;) *p++ = bignum_byte(rsa->iqmp, i);
+ assert(p == blob + bloblen);
+ *len = bloblen;
+ return blob;