1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/*
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Dropbear - a SSH2 server
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2002,2003 Matt Johnston
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved.
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions:
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software.
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h"
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h"
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "bignum.h"
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dss.h"
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h"
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h"
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "random.h"
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle DSS (Digital Signature Standard), aka DSA (D.S. Algorithm),
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * operations, such as key reading, signing, verification. Key generation
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * is in gendss.c, since it isn't required in the server itself.
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * See FIPS186 or the Handbook of Applied Cryptography for details of the
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithm */
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_DSS
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Load a dss key from a buffer, initialising the values.
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The key will have the same format as buf_put_dss_key.
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * These should be freed with dss_key_free.
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint buf_get_dss_pub_key(buffer* buf, dss_key *key) {
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter buf_get_dss_pub_key"))
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->p = m_malloc(sizeof(mp_int));
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->q = m_malloc(sizeof(mp_int));
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->g = m_malloc(sizeof(mp_int));
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->y = m_malloc(sizeof(mp_int));
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_mp_init_multi(key->p, key->q, key->g, key->y, NULL);
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->x = NULL;
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_incrpos(buf, 4+SSH_SIGNKEY_DSS_LEN); /* int + "ssh-dss" */
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 || buf_getmpint(buf, key->q) == DROPBEAR_FAILURE
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 || buf_getmpint(buf, key->g) == DROPBEAR_FAILURE
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 || buf_getmpint(buf, key->y) == DROPBEAR_FAILURE) {
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave buf_get_dss_pub_key: failed reading mpints"))
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return DROPBEAR_FAILURE;
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_count_bits(key->p) < MIN_DSS_KEYLEN) {
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_log(LOG_WARNING, "DSS key too short");
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave buf_get_dss_pub_key: short key"))
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return DROPBEAR_FAILURE;
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave buf_get_dss_pub_key: success"))
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return DROPBEAR_SUCCESS;
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Same as buf_get_dss_pub_key, but reads a private "x" key at the end.
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Loads a private dss key from a buffer
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint buf_get_dss_priv_key(buffer* buf, dss_key *key) {
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret = DROPBEAR_FAILURE;
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ret = buf_get_dss_pub_key(buf, key);
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ret == DROPBEAR_FAILURE) {
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return DROPBEAR_FAILURE;
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	key->x = m_malloc(sizeof(mp_int));
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_mp_init(key->x);
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ret = buf_getmpint(buf, key->x);
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ret == DROPBEAR_FAILURE) {
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->x);
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ret;
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Clear and free the memory used by a public or private key */
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid dss_key_free(dss_key *key) {
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter dsa_key_free"))
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key == NULL) {
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("enter dsa_key_free: key == NULL"))
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key->p) {
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		mp_clear(key->p);
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->p);
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key->q) {
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		mp_clear(key->q);
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->q);
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key->g) {
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		mp_clear(key->g);
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->g);
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key->y) {
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		mp_clear(key->y);
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->y);
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (key->x) {
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		mp_clear(key->x);
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(key->x);
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(key);
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave dsa_key_free"))
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* put the dss public key into the buffer in the required format:
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * string	"ssh-dss"
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * mpint	p
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * mpint	q
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * mpint	g
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * mpint	y
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid buf_put_dss_pub_key(buffer* buf, dss_key *key) {
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putmpint(buf, key->p);
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putmpint(buf, key->q);
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putmpint(buf, key->g);
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putmpint(buf, key->y);
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Same as buf_put_dss_pub_key, but with the private "x" key appended */
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid buf_put_dss_priv_key(buffer* buf, dss_key *key) {
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_put_dss_pub_key(buf, key);
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putmpint(buf, key->x);
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DROPBEAR_SIGNKEY_VERIFY
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Verify a DSS signature (in buf) made on data by the key given.
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int len) {
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char msghash[SHA1_HASH_SIZE];
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	hash_state hs;
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret = DROPBEAR_FAILURE;
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(val1);
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(val2);
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(val3);
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(val4);
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char * string = NULL;
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int stringlen;
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter buf_dss_verify"))
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* get blob, check length */
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	string = buf_getstring(buf, &stringlen);
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (stringlen != 2*SHA1_HASH_SIZE) {
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* hash the data */
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_init(&hs);
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_process(&hs, data, len);
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_done(&hs, msghash);
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* create the signature - s' and r' are the received signatures in buf */
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* w = (s')-1 mod q */
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val1 = s' */
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_cmp(&val1, key->q) != MP_LT) {
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("verify failed, s' >= q"))
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val2 = w = (s')^-1 mod q*/
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_invmod(&val1, key->q, &val2) != MP_OKAY) {
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* u1 = ((SHA(M')w) mod q */
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val1 = SHA(M') = msghash */
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val3 = u1 = ((SHA(M')w) mod q */
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* u2 = ((r')w) mod q */
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val1 = r' */
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE);
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_cmp(&val1, key->q) != MP_LT) {
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("verify failed, r' >= q"))
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* let val4 = u2 = ((r')w) mod q */
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mulmod(&val1, &val2, key->q, &val4) != MP_OKAY) {
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* v = (((g)^u1 (y)^u2) mod p) mod q */
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* val2 = g^u1 mod p */
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_exptmod(key->g, &val3, key->p, &val2) != MP_OKAY) {
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* val3 = y^u2 mod p */
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_exptmod(key->y, &val4, key->p, &val3) != MP_OKAY) {
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* val4 = ((g)^u1 (y)^u2) mod p */
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mulmod(&val2, &val3, key->p, &val4) != MP_OKAY) {
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* val2 = v = (((g)^u1 (y)^u2) mod p) mod q */
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mod(&val4, key->q, &val2) != MP_OKAY) {
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* check whether signatures verify */
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_cmp(&val2, &val1) == MP_EQ) {
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* good sig */
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = DROPBEAR_SUCCESS;
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout:
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	mp_clear_multi(&val1, &val2, &val3, &val4, NULL);
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(string);
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ret;
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* DROPBEAR_SIGNKEY_VERIFY */
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DSS_PROTOK
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* convert an unsigned mp into an array of bytes, malloced.
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * This array must be freed after use, len contains the length of the array,
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * if len != NULL */
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic unsigned char* mptobytes(mp_int *mp, int *len) {
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char* ret;
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int size;
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	size = mp_unsigned_bin_size(mp);
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ret = m_malloc(size);
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_to_unsigned_bin(mp, ret) != MP_OKAY) {
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("mem alloc error");
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (len != NULL) {
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		*len = size;
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ret;
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Sign the data presented with key, writing the signature contents
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to the buffer
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * When DSS_PROTOK is #defined:
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The alternate k generation method is based on the method used in PuTTY.
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * In particular to avoid being vulnerable to attacks using flaws in random
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * generation of k, we use the following:
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * proto_k = SHA512 ( SHA512(x) || SHA160(message) )
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * k = proto_k mod q
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Now we aren't relying on the random number generation to protect the private
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * key x, which is a long term secret */
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int len) {
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char msghash[SHA1_HASH_SIZE];
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int writelen;
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int i;
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DSS_PROTOK
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char privkeyhash[SHA512_HASH_SIZE];
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char *privkeytmp;
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char proto_k[SHA512_HASH_SIZE];
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_protok);
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_k);
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_m);
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_temp1);
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_temp2);
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_r);
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	DEF_MP_INT(dss_s);
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	hash_state hs;
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter buf_put_dss_sign"))
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(key != NULL);
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* hash the data */
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_init(&hs);
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_process(&hs, data, len);
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha1_done(&hs, msghash);
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_mp_init_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&dss_m, NULL);
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef DSS_PROTOK
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* hash the privkey */
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	privkeytmp = mptobytes(key->x, &i);
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_init(&hs);
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_process(&hs, "the quick brown fox jumped over the lazy dog", 44);
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_process(&hs, privkeytmp, i);
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_done(&hs, privkeyhash);
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_burn(privkeytmp, i);
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(privkeytmp);
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* calculate proto_k */
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_init(&hs);
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_process(&hs, privkeyhash, SHA512_HASH_SIZE);
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_process(&hs, msghash, SHA1_HASH_SIZE);
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sha512_done(&hs, proto_k);
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* generate k */
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_mp_init(&dss_protok);
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE);
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mod(&dss_protok, key->q, &dss_k) != MP_OKAY) {
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	mp_clear(&dss_protok);
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_burn(proto_k, SHA512_HASH_SIZE);
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else /* DSS_PROTOK not defined*/
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	gen_random_mpint(key->q, &dss_k);
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* now generate the actual signature */
354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* g^k mod p */
357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) !=  MP_OKAY) {
358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* r = (g^k mod p) mod q */
361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mod(&dss_temp1, key->q, &dss_r) != MP_OKAY) {
362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* x*r mod q */
366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mulmod(&dss_r, key->x, key->q, &dss_temp1) != MP_OKAY) {
367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* (SHA1(M) + xr) mod q) */
370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_addmod(&dss_m, &dss_temp1, key->q, &dss_temp2) != MP_OKAY) {
371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* (k^-1) mod q */
375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_invmod(&dss_k, key->q, &dss_temp1) != MP_OKAY) {
376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* s = (k^-1(SHA1(M) + xr)) mod q */
380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_mulmod(&dss_temp1, &dss_temp2, key->q, &dss_s) != MP_OKAY) {
381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
385f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(buf, 2*SHA1_HASH_SIZE);
386f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
387f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	writelen = mp_unsigned_bin_size(&dss_r);
388f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(writelen <= SHA1_HASH_SIZE);
389f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* need to pad to 160 bits with leading zeros */
390f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
391f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buf_putbyte(buf, 0);
392f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
393f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_to_unsigned_bin(&dss_r, buf_getwriteptr(buf, writelen))
394f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			!= MP_OKAY) {
395f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
396f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
397f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	mp_clear(&dss_r);
398f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_incrwritepos(buf, writelen);
399f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
400f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	writelen = mp_unsigned_bin_size(&dss_s);
401f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(writelen <= SHA1_HASH_SIZE);
402f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* need to pad to 160 bits with leading zeros */
403f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
404f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buf_putbyte(buf, 0);
405f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
406f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (mp_to_unsigned_bin(&dss_s, buf_getwriteptr(buf, writelen))
407f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			!= MP_OKAY) {
408f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("dss error");
409f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
410f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	mp_clear(&dss_s);
411f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_incrwritepos(buf, writelen);
412f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
413f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
414f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&dss_m, NULL);
415f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
416f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* create the signature to return */
417f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
418f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave buf_put_dss_sign"))
419f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
420f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
421f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* DROPBEAR_DSS */
422