This would be no problem in general, since login_passwd, like most progams, pretty much ignores argv[0], since it's supposed to be the name that was used to call the program. Unfortunately, in this case, login_passwd is really just a hard link to a large crunched binary. Crunched binaries use argv[0] to decide which crunched main function to call. As it happens, auth_call when called by login (via auth_verify in /usr/src/lib/libc/gen/authenticate.c) ends up setting argv[0] to be "passwd".
Of course, I also crunched a binary called "passwd", so the binary generated by crunchgen ends up invoking passwd's main function instead of login_passwd's main function! Naturally, passwd is confused by the arguments that should have been passed to login_passwd, and fails. Thus, login also fails.
Right now, my workaround is to modify line 858 of /usr/src/lib/libc/gen/auth_subr.c
/* ...snip... */ argv[0] = path; /* WORKAROUND: fix a bug in the way login_passwd is called */ execve(path, argv, auth_environ); /* ...snip... */
But, really I should fix how the arguments are being copied from the va_list earlier on; I just don't know if anyone is depending on that strange first argument.