int shishi_apreq_decrypt (Shishi * handle, Shishi_asn1 apreq, Shishi_key * key, int keyusage, Shishi_asn1 * authenticator) { int res; int i; char *buf; size_t buflen; char *cipher; size_t cipherlen; int etype; res = shishi_apreq_get_authenticator_etype (handle, apreq, &etype); if (res != SHISHI_OK) return res; if (etype != shishi_key_type (key)) return SHISHI_APREQ_BAD_KEYTYPE; res = shishi_asn1_read (handle, apreq, "authenticator.cipher", &cipher, &cipherlen); if (res != SHISHI_OK) return res; res = shishi_decrypt (handle, key, keyusage, cipher, cipherlen, &buf, &buflen); free (cipher); if (res != SHISHI_OK) { shishi_error_printf (handle, "decrypt fail, most likely wrong password\n"); return SHISHI_APREQ_DECRYPT_FAILED; } /* The crypto is so 1980; no length indicator. Trim off pad bytes until we can parse it. */ for (i = 0; i < 8; i++) { if (VERBOSEASN1 (handle)) printf ("Trying with %d pad in enckdcrep...\n", i); *authenticator = shishi_der2asn1_authenticator (handle, &buf[0], buflen - i); if (*authenticator != NULL) break; } if (*authenticator == NULL) { shishi_error_printf (handle, "Could not DER decode Authenticator. " "Password probably correct (decrypt ok) though\n"); return SHISHI_ASN1_ERROR; } return SHISHI_OK; }
/* read encrypted data on socket */ int readenc (Shishi * h, int sock, char *buf, int *len, shishi_ivector * iv, Shishi_key * enckey, int proto) { char *out; char *outbis; int rc; int val; int outlen; int dlen = 0, blocksize, enctype, hashsize; /* read size of message */ read (sock, &dlen, sizeof (int)); dlen = ntohl (dlen); /* if 0 put read size to 0 */ if (!dlen) { *len = dlen; return SHISHI_OK; } if (proto == 1) *len = dlen; /* convert size to encryption size */ enctype = shishi_key_type (enckey); blocksize = shishi_cipher_blocksize (enctype); hashsize = shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype)); switch (enctype) { case SHISHI_AES128_CTS_HMAC_SHA1_96: case SHISHI_AES256_CTS_HMAC_SHA1_96: dlen += 4 + hashsize + blocksize; break; case SHISHI_ARCFOUR_HMAC: case SHISHI_ARCFOUR_HMAC_EXP: dlen += 4 + 8 + blocksize - 1; dlen /= blocksize; dlen *= blocksize; dlen += hashsize; break; case SHISHI_DES3_CBC_HMAC_SHA1_KD: dlen += 4 + 2 * blocksize - 1; dlen /= blocksize; dlen *= blocksize; dlen += hashsize; break; case SHISHI_DES_CBC_CRC: dlen += 2 * blocksize - 1; if (proto == 2) dlen += 4; dlen += hashsize; dlen /= blocksize; dlen *= blocksize; break; default: dlen += blocksize - 1; if (proto == 2) dlen += 4; dlen += hashsize; dlen /= blocksize; dlen *= blocksize; break; } /* read encrypted data */ outbis = malloc (dlen); if (outbis == NULL) { perror ("readenc()"); return 1; } rc = read (sock, outbis, dlen); if (rc != dlen) { fprintf (stderr, "Error during read socket\n"); free (outbis); return 1; } if (proto == 1) { rc = shishi_decrypt (h, enckey, iv->keyusage, outbis, dlen, &out, &outlen); if (rc != SHISHI_OK) { fprintf (stderr, "decryption error\n"); free (outbis); return 1; } val = 0; } else { rc = shishi_crypto_decrypt (iv->ctx, outbis, dlen, &out, &outlen); if (rc != SHISHI_OK) { fprintf (stderr, "decryption error\n"); free (outbis); return 1; } /* in KCMDV0.2 first 4 bytes of decrypted data = len of data */ *len = ntohl (*((int *) out)); val = sizeof (int); } memset (buf, 0, BUFLEN); /* copy decrypted data to output */ memcpy (buf, out + val, outlen - val); free (out); free (outbis); return SHISHI_OK; }