- size_t hsz = pp->ch->hashsz;
- size_t n;
-
- /* --- Ensure that everything is sensibly sized --- */
-
- if (hsz + msz + 1 > sz)
- return (-1);
-
- /* --- Fill in the initial buffer --- */
-
- q = buf;
- *q++ = 0; sz--;
- mq = q + msz;
- qq = q + sz;
- n = sz - msz;
- memcpy(q, msg, msz);
- if (pp->salt)
- memcpy(mq, pp->salt, hsz);
- else
- memset(mq, 0, hsz);
- memset(mq + hsz, 0, n - hsz);
-
- /* --- Do the encryption --- */
-
- c = pp->cc->init(msg, msz);
- c->ops->encrypt(c, mq, mq, n);
- c->ops->destroy(c);
-
- /* --- Done --- */
-
- return (0);
+ unsigned mask;
+ size_t pssz, hsz = pp->ch->hashsz;
+
+ /* --- Check the message length --- */
+
+ nbits--;
+ sz = (nbits + 7)/8;
+ mask = (1 << nbits%8) - 1;
+ if (!mask) mask = 0xff;
+ if (hsz + pp->ssz + 2 > sz)
+ return (0);
+
+ /* --- Generate a random salt --- */
+
+ pssz = sz - pp->ssz - hsz - 2;
+ memset(b, 0, pssz);
+ b[pssz] = 0x01;
+ s = b + pssz + 1;
+ r = s + pp->ssz;
+ GR_FILL(pp->r, s, pp->ssz);
+
+ /* --- Compute the salted hash --- */
+
+ h = GH_INIT(pp->ch);
+ GH_HASH(h, z8, 8);
+ GH_HASH(h, m, msz);
+ GH_HASH(h, s, pp->ssz);
+ GH_DONE(h, r);
+ r[hsz] = 0xbc;
+
+ /* --- Do the masking --- */
+
+ c = GC_INIT(pp->cc, r, hsz);
+ GC_ENCRYPT(c, b, b, pssz + pp->ssz + 1);
+ GC_DESTROY(c);
+ b[0] &= mask;
+ return (mp_loadb(d, b, sz));